Metadata-Version: 2.4
Name: solarc-eclipse
Version: 0.6.1.4
Summary: ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
Home-page: https://github.com/jamesmckevitt/eclipse
Author: James McKevitt
Author-email: James McKevitt <jm2@mssl.ucl.ac.uk>
License: Contact for permission
Project-URL: Homepage, https://github.com/jamesmckevitt/eclipse
Project-URL: Repository, https://github.com/jamesmckevitt/eclipse
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: astropy
Requires-Dist: ndcube
Requires-Dist: specutils
Requires-Dist: scipy
Requires-Dist: matplotlib
Requires-Dist: joblib
Requires-Dist: tqdm
Requires-Dist: dill
Requires-Dist: pyyaml
Requires-Dist: reproject
Requires-Dist: sunpy[all]
Requires-Dist: dask
Requires-Dist: psutil
Requires-Dist: mendeleev
Requires-Dist: h5py
Requires-Dist: fiasco
Provides-Extra: mpi
Requires-Dist: mpi4py; extra == "mpi"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST

The ECLIPSE code (Emission Calculation and Line Prediction for SOLAR-C EUVST) is used to forward model the performance of the EUV spectrograph EUVST onboard the SOLAR-C spacecraft.

Contact: James McKevitt (jm2@mssl.ucl.ac.uk). License: Contact for permission to use.

The instrument response generated by this code will be updated during instrument development, testing, and commissioning.

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17543844.svg)](https://doi.org/10.5281/zenodo.17543844)

## Installation

### From PyPI (recommended)

```bash
pip install solarc-eclipse
```

### From source

```bash
pip install git+https://github.com/jamesmckevitt/eclipse.git
```

## Quick Start

### Command Line Interface

After installation, you can run ECLIPSE from the command line:

```bash
# Run synthesis script (convert 3D MHD data to synthetic spectra)
synthesise-spectra --data-dir ./data/atmosphere --lines Fe12_195.1190 --output-dir ./run/input

# Run instrument response simulation
eclipse --config ./run/input/config.yaml

# Help can be accessed with
synthesise-spectra --help
eclipse --help
```

### Python API

You can also use ECLIPSE as a Python library:

```python
import euvst_response
from euvst_response import AluminiumFilter, Detector_SWC, Telescope_EUVST

telescope = Telescope_EUVST()
detector = Detector_SWC()

print(f"Telescope collecting area: {telescope.collecting_area:.4f}")
print(f"Detector QE (EUV): {detector.qe_euv:.2f}")

# Calculate effective area at Fe XII 195.119 Angstrom
fe12_wl = 195.119 * u.AA
effective_area = telescope.collecting_area * telescope.throughput(fe12_wl) * detector.qe_euv

# Get breakdown of throughput by component
pm_eff = telescope.primary_mirror_efficiency(fe12_wl)
grating_eff = telescope.grating_efficiency(fe12_wl)
micro_eff = telescope.microroughness_efficiency(fe12_wl)
filter_eff = telescope.filter.total_throughput(fe12_wl)
```

### Analysis Tutorial

For analyzing simulation results, see the included Jupyter notebook `analysis_tutorial.ipynb` which demonstrates how to:

- Load simulation results
- Explore parameter combinations
- Analyze fit statistics and compute velocity/line width errors
- Create SunPy maps for visualization

The analysis functions are now available directly from the package:

```python
from euvst_response import (
    load_instrument_response_results,
    get_results_for_combination,
    analyse_fit_statistics,
    create_sunpy_maps_from_combo,
    summary_table
)

# Load results
results = load_instrument_response_results("run/result/my_results.pkl")

# Get results for a specific parameter combination:
combo = get_results_for_combination(
    results, exposure=40*u.s, slit_width=0.4*u.arcsec, offchip_bin_slit=2
)

# Create SunPy maps
maps = create_sunpy_maps_from_combo(combo, rest_wavelength=195.119*u.AA, data_type='dn')
```

## Detailed instructions

### 1. Run the line synthesis

The synthesis script converts 3D MHD simulation data into synthetic solar spectra. Contribution functions G(T, n_e) are computed on-the-fly using [fiasco](https://fiasco.readthedocs.io/) (a Python interface to the CHIANTI atomic database).

#### Basic Usage

```bash
# Example using all available command line options
synthesise-spectra \
  --data-dir ./data/atmosphere \
  --lines Fe12_195.1190 Fe12_195.1790 \
  --abundance sun_coronal_2021_chianti \
  --n-workers 4 \
  --output-dir ./run/input \
  --output-name synthesised_spectra.pkl \
  --temp-file temp/eosT.0270000 \
  --rho-file rho/result_prim_0.0270000 \
  --vx-file vx/result_prim_1.0270000 \
  --vy-file vy/result_prim_3.0270000 \
  --vz-file vz/result_prim_2.0270000 \
  --cube-shape 512 768 256 \
  --voxel-dx "0.192 Mm" \
  --voxel-dy "0.192 Mm" \
  --voxel-dz "0.064 Mm" \
  --vel-res "5.0 km/s" \
  --vel-lim "300.0 km/s" \
  --integration-axis z \
  --crop-x "-50 Mm" "50 Mm" \
  --crop-y "-50 Mm" "50 Mm" \
  --crop-z "0 Mm" "20 Mm" \
  --downsample 1 \
  --precision float64 \
  --mean-mol-wt 1.29

# Show all available options
synthesise-spectra --help
```

#### Command Line Options

**Input/Output Paths:**
- `--data-dir`: Directory containing simulation data (default: `data/atmosphere`)
- `--output-dir`: Output directory for results (default: `./run/input`)
- `--output-name`: Output filename (default: `synthesised_spectra.pkl`)

**Line and Abundance Selection:**
- `--lines`: Emission lines to synthesise, e.g., `--lines Fe12_195.1190 Fe12_195.1790` (required)
- `--abundance`: CHIANTI abundance dataset name (default: `sun_coronal_2021_chianti`)
- `--n-workers`: Number of parallel workers for the fiasco G(T, n_e) computation. Each distinct ion is computed in a separate process. `0` uses all available CPUs (default: `0`). Set to `1` for serial execution.

**Simulation Files:**
- `--temp-file`: Temperature file relative to data-dir (default: `temp/eosT.0270000`)
- `--rho-file`: Density file relative to data-dir (default: `rho/result_prim_0.0270000`)
- `--vx-file`: X-velocity file (required if `--integration-axis x`)
- `--vy-file`: Y-velocity file (required if `--integration-axis y`)
- `--vz-file`: Z-velocity file (required if `--integration-axis z`)

**Grid Parameters:**
- `--cube-shape`: Cube dimensions as three integers (default: `512 768 256`)
- `--voxel-dx`, `--voxel-dy`, `--voxel-dz`: Voxel sizes with units (default: `"0.192 Mm"`, `"0.192 Mm"`, `"0.064 Mm"`)

**Velocity Grid:**
- `--vel-res`: Velocity resolution with units (default: `"5.0 km/s"`)
- `--vel-lim`: Velocity limit +-km/s with units (default: `"300.0 km/s"`)

**Integration and Viewing:**
- `--integration-axis`: Integration axis: `x`, `y`, or `z` (default: `z`)
  - `z`: Standard top-down view (integrates through height)
  - `x`: Side view from the left (integrates left-to-right)
  - `y`: Side view from the front (integrates front-to-back)

**Spatial Cropping (Heliocentric coordinates with units):**
- `--crop-x`: X-range to crop with units, e.g., `--crop-x "-50 Mm" "50 Mm"` (optional)
- `--crop-y`: Y-range to crop with units, e.g., `--crop-y "-50 Mm" "50 Mm"` (optional)
- `--crop-z`: Z-range to crop with units, e.g., `--crop-z "0 Mm" "20 Mm"` (optional)
- Omit any crop option to use the full range in that dimension

**Processing Options:**
- `--downsample`: Downsampling factor (default: `1` = no downsampling)
- `--precision`: Numerical precision `float32` or `float64` (default: `float64`)
- `--mean-mol-wt`: Mean molecular weight (default: `1.29`)

#### Dynamic Mode (Time-varying Atmospheres)

For simulating raster scans over evolving atmospheres, use dynamic mode which combines MHD timesteps based on instrument scanning:

```bash
synthesise-spectra \
  --data-dir ./data/atmosphere \
  --lines Fe12_195.1190 \
  --abundance sun_coronal_2021_chianti \
  --output-dir ./run/input \
  --slit-rest-time "40 s" \
  --slit-width "0.2 arcsec" \
  --temp-dir temp \
  --temp-filename eosT \
  --rho-dir rho \
  --rho-filename result_prim_0 \
  --vz-dir vz \
  --vz-filename result_prim_2 \
  --time-dir time \
  --time-filename tau_slice_0.100 \
  --cube-shape 512 768 256 \
  --voxel-dx "0.192 Mm" \
  --voxel-dy "0.192 Mm" \
  --voxel-dz "0.064 Mm" \
  --vel-res "5.0 km/s" \
  --vel-lim "300.0 km/s" \
  --integration-axis z
```

**Dynamic Mode Options:**
- `--slit-rest-time`: Slit rest time per position - enables dynamic mode
- `--slit-width`: Slit width
- `--temp-dir`, `--rho-dir`, `--vx-dir`, `--vy-dir`, `--vz-dir`, `--time-dir`: Directories containing timestep files
- `--temp-filename`, `--rho-filename`, `--vx-filename`, `--vy-filename`, `--vz-filename`, `--time-filename`: Filename prefix before timestep suffix

#### Output

The synthesis produces a pickle file containing:
- `line_cubes`: Individual NDCube objects for each spectral line with proper WCS
- `config`: Runtime configuration for reproducibility
- Additional technical data for internal use

#### Performance Tips

- Use `--downsample 2` or `--downsample 4` for initial testing
- Use `--precision float32` to reduce memory usage (may affect accuracy)
- Use spatial cropping to focus on regions of interest and reduce computation time
- Monitor memory usage - full resolution synthesis can require 50+ GB RAM
- Side views (`--integration-axis x` or `y`) may require different velocity files

#### Working with Synthesis Results

The synthesis results can be loaded and analyzed using the package API:

```python
import euvst_response

# Load synthesis results - this sums all line cubes into a single cube
# By default uses Fe XII 195.119 Angstrom as reference for wavelength grid
cube = euvst_response.load_atmosphere("./run/input/synthesised_spectra.pkl")
print(f"Combined cube shape: {cube.data.shape}")

# Access individual line cubes if needed
import pickle
with open("./run/input/synthesised_spectra.pkl", "rb") as f:
    data = pickle.load(f)

# Access individual line cubes
fe12_195 = data["line_cubes"]["Fe12_195.1190"]
print(f"Fe XII 195.119 cube shape: {fe12_195.data.shape}")
print(f"Rest wavelength: {fe12_195.meta['rest_wav']}")

# List all available lines
print(f"Available spectral lines: {list(data['line_cubes'].keys())}")
```

#### Pre-computed Atmospheres

This step can require a lot of memory at full resolution. A fully synthesised atmosphere using the Cheung et al. (2018) atmosphere (doi:10.1038/s41550-018-0629-3) for the Fe XII 195.119 and 195.179 lines, including 5 background lines from each side, can be downloaded here: https://liveuclac-my.sharepoint.com/:f:/g/personal/ucasjem_ucl_ac_uk/Es-ts6rwXIlInAweGI7hmdMB5BoGqv9uSpIXOvMkzhS3cw?e=54si7R

**Important:** You can place the synthesised atmosphere file anywhere and specify its location using the `synthesis_file` parameter in your YAML configuration file. The default location is `./run/input/synthesised_spectra.pkl`.

### 2. Simulate the instrument response

#### Configuration File

ECLIPSE uses YAML configuration files to specify simulation parameters. You can specify single values or lists of values for parameter sweeps.

**Key configuration options:**
- `instrument`: Choose between SWC (EUVST-SW) or EIS (Hinode)
- `synthesis_file`: Path to the synthesised spectra pickle file (default: `./run/input/synthesised_spectra.pkl`)
- `reference_line`: Spectral line to use as reference for wavelength grid when combining all lines (default: `Fe12_195.1190`)
- `expos`: Exposure time(s) for simulations
- `n_iter`: Number of Monte Carlo iterations
- Parameter sweeps for filters, detector settings, etc.

Here's a complete example configuration file:

```yaml
# Instrument selection
instrument: SWC  # Options: SWC (EUVST Short Wavelength) or EIS (Hinode/EIS)

# Synthesis file path - location of the synthesised spectra pickle file
synthesis_file: ./run/input/synthesised_spectra.pkl  # Default location

# Reference line for wavelength grid and metadata when combining all spectral lines
reference_line: Fe12_195.1190  # Default reference line (Fe XII 195.119 Angstrom)

# Point Spread Function
psf: False  # Enable PSF convolution
# Or test with and without PSF:
# psf: [True, False]  # Run simulations both with and without PSF

# Exposure times - can be single value or list
expos: [0.5 s, 1 s, 2 s, 5 s, 10 s, 20 s, 40 s, 80 s]

# Monte Carlo simulation parameters
n_iter: 1000      # Number of Monte Carlo iterations
ncpu: -1        # Number of CPU cores (-1 = use all available)

# Parameter sweeps - you can specify single values or lists for any parameter
# The simulation will run all combinations of parameters

# Slit width
slit_width: 0.2 arcsec  # Narrowest slit on EUVST

# Filter parameters (SWC only)
# Thickness of aluminum oxide layer on entrance filter
oxide_thickness: 95 angstrom  # Default (expected value)

# Carbon contamination thickness on filter
c_thickness: 0 angstrom  # Default (ideal case, no contamination)

# Aluminum filter thickness
aluminium_thickness: 1485 angstrom  # Default (expected value)

# CCD temperature for dark current calculation
ccd_temperature: -60 Celsius  # Default (expected operating temperature)

# Visible stray light level
vis_sl: 0 photon / (s * cm**2)  # Default, (ideal case, no stray light)

# Multi-component Gaussian fitting (optional, omit for single-Gaussian)
fitting:
  primary_component: 0
  constrain_positive_intensity: true
  components:
    - wavelength: 195.119 angstrom
      amplitude_greater_than: 1  # must be brighter than component 1
    - wavelength: 195.179 angstrom
      tie_center: 0  # Centroid offset tied to component 0
      tie_width: 0  # Same width as component 0
```

Off-chip binning in the slit direction can also be performed:

```yaml
offchip_bin_slit: 2          # Bin every 2 slit pixels
offchip_bin_slit: [1, 2, 4]  # Sweep over multiple binning factors
```

Alternatively, you can specify paired slit width and off-chip binning values to only simulate specific combinations:

```yaml
# Paired slit width / off-chip binning
# Only the listed (slit_width, offchip_bin_slit) pairs are simulated
slit_bin_pairs:
  - slit_width: 0.2 arcsec
    offchip_bin_slit: 1
  - slit_width: 0.4 arcsec
    offchip_bin_slit: 2
  - slit_width: 0.8 arcsec
    offchip_bin_slit: 5
  - slit_width: 1.6 arcsec
    offchip_bin_slit: 10
```

For guidance on recommended values, see McKevitt et al. (2025) (in prep.).

By default, both the DN and photon signals are fitted at every Monte Carlo iteration. To speed up the simulation when only one is needed, use the `fit_signals` option:

```yaml
fit_signals: dn       # Fit only the DN signal
fit_signals: photon   # Fit only the photon signal
fit_signals: both     # Fit both (default)
```

If you synthesised data in dynamic mode, your configuration must specify:
- Exactly one slit width matching the synthesis slit width
- Exactly one exposure time matching the synthesis exposure time

#### Running Simulations

Run the instrument response function using:
```bash
eclipse --config ./run/input/config.yaml
```

**Command-line options:**
- `--config`: Path to YAML configuration file (required)
- `--debug`: Enable debug mode with IPython breakpoints on errors (optional)

#### Multi-node MPI parallelisation

When launched with multiple MPI ranks on a SLURM cluster (via `srun` or `mpirun`, and setting `--ntasks-per-node`), ECLIPSE automatically distributes Monte Carlo iterations across ranks and gathers results on rank 0. No code or configuration changes are needed - MPI is auto-detected at runtime. If `mpi4py` is not installed or only one rank is present, the code falls back to single-process mode.

Requirements: `mpi4py` and `intel-mpi` (load with `module load intel-mpi` before launching).

#### Output

Results are saved as pickle files in the `run/result/` directory with the same base name as the configuration file. The output includes:
- Simulated detector signals (DN and photon counts)
- Fitted spectral line parameters (intensity, velocity, width)
- Statistical analysis of velocity precision vs. exposure time
- Ground truth comparisons

## Acknowledgements

The SOLAR-C/EUVST-SW instrument is an ESA-funded contribution to the JAXA-led SOLAR-C mission. The EUVST-LW (long wavelength) instrument is contributed by NASA. The ECLIPSE code is developed and maintained at Mullard Space Science Laboratory (UCL), and was made using Austrian Super Computing (ASC) infrastructure in collaboration with the University of Vienna.
