solarc-eclipse 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- euvst_response/__init__.py +52 -0
- euvst_response/analysis.py +680 -0
- euvst_response/cli.py +113 -0
- euvst_response/config.py +396 -0
- euvst_response/data/throughput/grating_reflection_efficiency.dat +25 -0
- euvst_response/data/throughput/primary_mirror_coating_reflectance.dat +25 -0
- euvst_response/data/throughput/source.txt +3 -0
- euvst_response/data/throughput/throughput_aluminium_1000_angstrom.dat +503 -0
- euvst_response/data/throughput/throughput_aluminium_oxide_1000_angstrom.dat +503 -0
- euvst_response/data/throughput/throughput_carbon_1000_angstrom.dat +503 -0
- euvst_response/data_processing.py +269 -0
- euvst_response/fitting.py +144 -0
- euvst_response/main.py +424 -0
- euvst_response/monte_carlo.py +159 -0
- euvst_response/pinhole_diffraction.py +260 -0
- euvst_response/psf.py +46 -0
- euvst_response/radiometric.py +512 -0
- euvst_response/synthesis.py +911 -0
- euvst_response/synthesis_cli.py +12 -0
- euvst_response/utils.py +176 -0
- solarc_eclipse-0.5.0.dist-info/METADATA +354 -0
- solarc_eclipse-0.5.0.dist-info/RECORD +26 -0
- solarc_eclipse-0.5.0.dist-info/WHEEL +5 -0
- solarc_eclipse-0.5.0.dist-info/entry_points.txt +5 -0
- solarc_eclipse-0.5.0.dist-info/licenses/LICENSE +1 -0
- solarc_eclipse-0.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Command line interface for synthesis script.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
"""Entry point for the synthesis command line script."""
|
|
8
|
+
from .synthesis import main as run_synthesis
|
|
9
|
+
run_synthesis()
|
|
10
|
+
|
|
11
|
+
if __name__ == "__main__":
|
|
12
|
+
main()
|
euvst_response/utils.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for coordinate transformations, unit conversions, and general helpers.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
import contextlib
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import numpy as np
|
|
9
|
+
import astropy.units as u
|
|
10
|
+
import astropy.constants as const
|
|
11
|
+
import joblib
|
|
12
|
+
from tqdm import tqdm
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Global debug flag - can be set by command line or configuration
|
|
16
|
+
DEBUG_MODE = False
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def set_debug_mode(enabled: bool):
|
|
20
|
+
"""Set global debug mode."""
|
|
21
|
+
global DEBUG_MODE
|
|
22
|
+
DEBUG_MODE = enabled
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def debug_break(message: str = "Debug break triggered", locals_dict=None, globals_dict=None):
|
|
26
|
+
"""
|
|
27
|
+
Break into IPython debugger if debug mode is enabled.
|
|
28
|
+
|
|
29
|
+
Usage:
|
|
30
|
+
debug_break("Check values here", locals(), globals())
|
|
31
|
+
or:
|
|
32
|
+
debug_break("Error occurred")
|
|
33
|
+
"""
|
|
34
|
+
if not DEBUG_MODE:
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
print(f"\n=== DEBUG BREAK: {message} ===")
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
# Try to import and start IPython
|
|
41
|
+
from IPython import embed
|
|
42
|
+
|
|
43
|
+
# Prepare namespace for IPython
|
|
44
|
+
user_ns = {}
|
|
45
|
+
if locals_dict:
|
|
46
|
+
user_ns.update(locals_dict)
|
|
47
|
+
if globals_dict:
|
|
48
|
+
user_ns.update(globals_dict)
|
|
49
|
+
|
|
50
|
+
print("Starting IPython session...")
|
|
51
|
+
print("Available variables:", list(user_ns.keys()) if user_ns else "None provided")
|
|
52
|
+
print("Type 'exit()' or Ctrl+D to continue execution")
|
|
53
|
+
|
|
54
|
+
# Start IPython with the provided namespace
|
|
55
|
+
embed(user_ns=user_ns)
|
|
56
|
+
|
|
57
|
+
except ImportError:
|
|
58
|
+
print("IPython not available. Using standard Python debugger...")
|
|
59
|
+
import pdb
|
|
60
|
+
pdb.set_trace()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def debug_on_error(func):
|
|
64
|
+
"""
|
|
65
|
+
Decorator to automatically break into debugger on exceptions when debug mode is enabled.
|
|
66
|
+
|
|
67
|
+
Usage:
|
|
68
|
+
@debug_on_error
|
|
69
|
+
def my_function():
|
|
70
|
+
# your code here
|
|
71
|
+
"""
|
|
72
|
+
def wrapper(*args, **kwargs):
|
|
73
|
+
try:
|
|
74
|
+
return func(*args, **kwargs)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
if DEBUG_MODE:
|
|
77
|
+
print(f"\n=== EXCEPTION IN {func.__name__}: {e} ===")
|
|
78
|
+
# Get the frame where the exception occurred
|
|
79
|
+
import sys
|
|
80
|
+
frame = sys.exc_info()[2].tb_frame
|
|
81
|
+
debug_break(f"Exception in {func.__name__}: {e}", frame.f_locals, frame.f_globals)
|
|
82
|
+
raise
|
|
83
|
+
return wrapper
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def wl_to_vel(wl: u.Quantity, wl0: u.Quantity) -> u.Quantity:
|
|
87
|
+
"""Convert wavelength to line-of-sight velocity."""
|
|
88
|
+
return (wl - wl0) / wl0 * const.c
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def vel_to_wl(v: u.Quantity, wl0: u.Quantity) -> u.Quantity:
|
|
92
|
+
"""Convert line-of-sight velocity to wavelength."""
|
|
93
|
+
return wl0 * (1 + v / const.c)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def gaussian(wave, peak, centre, sigma, back):
|
|
97
|
+
"""Gaussian function for spectral line fitting."""
|
|
98
|
+
return peak * np.exp(-0.5 * ((wave - centre) / sigma) ** 2) + back
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def angle_to_distance(angle: u.Quantity) -> u.Quantity:
|
|
102
|
+
"""Convert angular size to linear distance at 1 AU."""
|
|
103
|
+
if angle.unit.physical_type != "angle":
|
|
104
|
+
raise ValueError("Input must be an angle")
|
|
105
|
+
return 2 * const.au * np.tan(angle.to(u.rad) / 2)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def distance_to_angle(distance: u.Quantity) -> u.Quantity:
|
|
109
|
+
"""Convert linear distance to angular size at 1 AU."""
|
|
110
|
+
if distance.unit.physical_type != "length":
|
|
111
|
+
raise ValueError("Input must be a length")
|
|
112
|
+
return (2 * np.arctan(distance / (2 * const.au))).to(u.arcsec)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def parse_yaml_input(val):
|
|
116
|
+
"""Parse YAML input values - handle both single values and lists."""
|
|
117
|
+
if isinstance(val, str):
|
|
118
|
+
return u.Quantity(val)
|
|
119
|
+
elif isinstance(val, (list, tuple)):
|
|
120
|
+
# Handle list of values
|
|
121
|
+
if all(isinstance(v, str) for v in val):
|
|
122
|
+
return [u.Quantity(v) for v in val]
|
|
123
|
+
else:
|
|
124
|
+
return list(val)
|
|
125
|
+
else:
|
|
126
|
+
return val
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def ensure_list(val):
|
|
130
|
+
"""Ensure input is a list (for parameter sweeps)."""
|
|
131
|
+
if not isinstance(val, (list, tuple)):
|
|
132
|
+
return [val]
|
|
133
|
+
return list(val)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def save_maps(path: str | Path, log_intensity: np.ndarray, v_map: u.Quantity,
|
|
137
|
+
x_pix_size: float, y_pix_size: float) -> None:
|
|
138
|
+
"""Save intensity and velocity maps for later comparison."""
|
|
139
|
+
np.savez(
|
|
140
|
+
path,
|
|
141
|
+
log_si=log_intensity,
|
|
142
|
+
v_map=v_map.to(u.km / u.s).value,
|
|
143
|
+
x_pix_size=x_pix_size,
|
|
144
|
+
y_pix_size=y_pix_size,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def load_maps(path: str | Path) -> dict:
|
|
149
|
+
"""Load previously saved intensity and velocity maps."""
|
|
150
|
+
dat = np.load(path)
|
|
151
|
+
return dict(
|
|
152
|
+
log_si=dat["log_si"],
|
|
153
|
+
v_map=dat["v_map"],
|
|
154
|
+
x_pix_size=float(dat["x_pix_size"]),
|
|
155
|
+
y_pix_size=float(dat["y_pix_size"]),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@contextlib.contextmanager
|
|
160
|
+
def tqdm_joblib(tqdm_object):
|
|
161
|
+
"""
|
|
162
|
+
Context manager that patches joblib so it uses the supplied tqdm
|
|
163
|
+
instance to report progress.
|
|
164
|
+
"""
|
|
165
|
+
class TqdmBatchCompletionCallback(joblib.parallel.BatchCompletionCallBack): # type: ignore[attr-defined]
|
|
166
|
+
def __call__(self, *args, **kwargs):
|
|
167
|
+
tqdm_object.update(n=self.batch_size)
|
|
168
|
+
return super().__call__(*args, **kwargs)
|
|
169
|
+
|
|
170
|
+
old_callback = joblib.parallel.BatchCompletionCallBack # type: ignore[attr-defined]
|
|
171
|
+
joblib.parallel.BatchCompletionCallBack = TqdmBatchCompletionCallback
|
|
172
|
+
try:
|
|
173
|
+
yield
|
|
174
|
+
finally:
|
|
175
|
+
joblib.parallel.BatchCompletionCallBack = old_callback
|
|
176
|
+
tqdm_object.close()
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: solarc-eclipse
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: ECLIPSE: Emission Calculation and Line Intensity Prediction for SOLAR-C EUVST
|
|
5
|
+
Home-page: https://github.com/jamesmckevitt/eclipse
|
|
6
|
+
Author: James McKevitt
|
|
7
|
+
Author-email: James McKevitt <jm2@mssl.ucl.ac.uk>
|
|
8
|
+
License: Contact for permission
|
|
9
|
+
Project-URL: Homepage, https://github.com/jamesmckevitt/eclipse
|
|
10
|
+
Project-URL: Repository, https://github.com/jamesmckevitt/eclipse
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy
|
|
23
|
+
Requires-Dist: astropy
|
|
24
|
+
Requires-Dist: ndcube
|
|
25
|
+
Requires-Dist: specutils
|
|
26
|
+
Requires-Dist: scipy
|
|
27
|
+
Requires-Dist: matplotlib
|
|
28
|
+
Requires-Dist: joblib
|
|
29
|
+
Requires-Dist: tqdm
|
|
30
|
+
Requires-Dist: dill
|
|
31
|
+
Requires-Dist: pyyaml
|
|
32
|
+
Requires-Dist: reproject
|
|
33
|
+
Requires-Dist: sunpy[all]
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest; extra == "dev"
|
|
36
|
+
Requires-Dist: black; extra == "dev"
|
|
37
|
+
Requires-Dist: flake8; extra == "dev"
|
|
38
|
+
Requires-Dist: mypy; extra == "dev"
|
|
39
|
+
Dynamic: author
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
Dynamic: requires-python
|
|
43
|
+
|
|
44
|
+
# ECLIPSE: Emission Calculation and Line Intensity Prediction for SOLAR-C EUVST
|
|
45
|
+
|
|
46
|
+
The ECLIPSE code (Emission Calculation and Line Intensity Prediction for SOLAR-C EUVST) is used to forward model the performance of the EUV spectrograph EUVST, on SOLAR-C.
|
|
47
|
+
|
|
48
|
+
Contact: James McKevitt (jm2@mssl.ucl.ac.uk). License: Contact for permission to use.
|
|
49
|
+
|
|
50
|
+
The instrument response generated by this code will be updated during instrument development, testing, and commissioning.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
### From PyPI (recommended)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install solarc-eclipse
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### From source
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git clone https://github.com/jamesmckevitt/eclipse.git
|
|
64
|
+
pip install eclipse
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
### Command Line Interface
|
|
70
|
+
|
|
71
|
+
After installation, you can run ECLIPSE from the command line:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Run synthesis script (convert 3D MHD data to synthetic spectra)
|
|
75
|
+
synthesise-spectra --data-dir ./data/atmosphere --goft-file ./data/gofnt.sav --output-dir ./run/input
|
|
76
|
+
|
|
77
|
+
# Run instrument response simulation
|
|
78
|
+
eclipse --config ./run/input/config.yaml
|
|
79
|
+
|
|
80
|
+
# Help can be accessed with
|
|
81
|
+
synthesise-spectra --help
|
|
82
|
+
eclipse --help
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Python API
|
|
86
|
+
|
|
87
|
+
You can also use ECLIPSE as a Python library:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import euvst_response
|
|
91
|
+
from euvst_response import AluminiumFilter, Detector_SWC, Telescope_EUVST
|
|
92
|
+
|
|
93
|
+
telescope = Telescope_EUVST()
|
|
94
|
+
detector = Detector_SWC()
|
|
95
|
+
|
|
96
|
+
print(f"Telescope collecting area: {telescope.collecting_area:.4f}")
|
|
97
|
+
print(f"Detector QE (EUV): {detector.qe_euv:.2f}")
|
|
98
|
+
|
|
99
|
+
# Calculate effective area at Fe XII 195.119 Å
|
|
100
|
+
fe12_wl = 195.119 * u.AA
|
|
101
|
+
effective_area = telescope.collecting_area * telescope.throughput(fe12_wl) * detector.qe_euv
|
|
102
|
+
|
|
103
|
+
# Get breakdown of throughput by component
|
|
104
|
+
pm_eff = telescope.primary_mirror_efficiency(fe12_wl)
|
|
105
|
+
grating_eff = telescope.grating_efficiency(fe12_wl)
|
|
106
|
+
micro_eff = telescope.microroughness_efficiency(fe12_wl)
|
|
107
|
+
filter_eff = telescope.filter.total_throughput(fe12_wl)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Analysis Tutorial
|
|
111
|
+
|
|
112
|
+
For analyzing simulation results, see the included Jupyter notebook `analysis_tutorial.ipynb` which demonstrates how to:
|
|
113
|
+
|
|
114
|
+
- Load simulation results
|
|
115
|
+
- Explore parameter combinations
|
|
116
|
+
- Analyze fit statistics and compute velocity/line width errors
|
|
117
|
+
- Create SunPy maps for visualization
|
|
118
|
+
|
|
119
|
+
The analysis functions are now available directly from the package:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from euvst_response import (
|
|
123
|
+
load_instrument_response_results,
|
|
124
|
+
get_results_for_combination,
|
|
125
|
+
analyse_fit_statistics,
|
|
126
|
+
create_sunpy_maps_from_combo,
|
|
127
|
+
summary_table
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Detailed instructions
|
|
132
|
+
|
|
133
|
+
### 1. Generate contribution functions for the desired emission lines
|
|
134
|
+
|
|
135
|
+
Edit `make_gofnt.pro` to specify the desired emission lines and the location of the CHIANTI files. You can use CHIANTI to identify the required lines.
|
|
136
|
+
|
|
137
|
+
Run the following command:
|
|
138
|
+
```bash
|
|
139
|
+
idl -e "make_goft"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 2. Run the line synthesis
|
|
143
|
+
|
|
144
|
+
The synthesis script converts 3D MHD simulation data into synthetic solar spectra. It can be run directly from the command line with extensive configuration options.
|
|
145
|
+
|
|
146
|
+
#### Basic Usage
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Example using all available command line options
|
|
150
|
+
synthesise-spectra \
|
|
151
|
+
--data-dir ./data/atmosphere \
|
|
152
|
+
--goft-file ./data/gofnt.sav \
|
|
153
|
+
--output-dir ./run/input \
|
|
154
|
+
--output-name synthesised_spectra.pkl \
|
|
155
|
+
--temp-file temp/eosT.0270000 \
|
|
156
|
+
--rho-file rho/result_prim_0.0270000 \
|
|
157
|
+
--vx-file vx/result_prim_1.0270000 \
|
|
158
|
+
--vy-file vy/result_prim_3.0270000 \
|
|
159
|
+
--vz-file vz/result_prim_2.0270000 \
|
|
160
|
+
--cube-shape 512 768 256 \
|
|
161
|
+
--voxel-dx 0.192 \
|
|
162
|
+
--voxel-dy 0.192 \
|
|
163
|
+
--voxel-dz 0.064 \
|
|
164
|
+
--vel-res 5.0 \
|
|
165
|
+
--vel-lim 300.0 \
|
|
166
|
+
--integration-axis z \
|
|
167
|
+
--crop-x -50 50 \
|
|
168
|
+
--crop-y -50 50 \
|
|
169
|
+
--crop-z 0 20 \
|
|
170
|
+
--downsample 1 \
|
|
171
|
+
--precision float64 \
|
|
172
|
+
--mean-mol-wt 1.29 \
|
|
173
|
+
--limit-lines Fe12_195.1190
|
|
174
|
+
|
|
175
|
+
# Show all available options
|
|
176
|
+
synthesise-spectra --help
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Command Line Options
|
|
180
|
+
|
|
181
|
+
**Input/Output Paths:**
|
|
182
|
+
- `--data-dir`: Directory containing simulation data (default: `data/atmosphere`)
|
|
183
|
+
- `--goft-file`: Path to CHIANTI G(T,N) save file (default: `./data/gofnt.sav`)
|
|
184
|
+
- `--output-dir`: Output directory for results (default: `./run/input`)
|
|
185
|
+
- `--output-name`: Output filename (default: `synthesised_spectra.pkl`)
|
|
186
|
+
|
|
187
|
+
**Simulation Files:**
|
|
188
|
+
- `--temp-file`: Temperature file relative to data-dir (default: `temp/eosT.0270000`)
|
|
189
|
+
- `--rho-file`: Density file relative to data-dir (default: `rho/result_prim_0.0270000`)
|
|
190
|
+
- `--vx-file`: X-velocity file (required if `--integration-axis x`)
|
|
191
|
+
- `--vy-file`: Y-velocity file (required if `--integration-axis y`)
|
|
192
|
+
- `--vz-file`: Z-velocity file (required if `--integration-axis z`)
|
|
193
|
+
|
|
194
|
+
**Grid Parameters:**
|
|
195
|
+
- `--cube-shape`: Cube dimensions as three integers (default: `512 768 256`)
|
|
196
|
+
- `--voxel-dx`, `--voxel-dy`, `--voxel-dz`: Voxel sizes in Mm (default: `0.192 0.192 0.064`)
|
|
197
|
+
|
|
198
|
+
**Velocity Grid:**
|
|
199
|
+
- `--vel-res`: Velocity resolution in km/s (default: `5.0`)
|
|
200
|
+
- `--vel-lim`: Velocity limit ±km/s (default: `300.0`)
|
|
201
|
+
|
|
202
|
+
**Integration and Viewing:**
|
|
203
|
+
- `--integration-axis`: Integration axis: `x`, `y`, or `z` (default: `z`)
|
|
204
|
+
- `z`: Standard top-down view (integrates through height)
|
|
205
|
+
- `x`: Side view from the left (integrates left-to-right)
|
|
206
|
+
- `y`: Side view from the front (integrates front-to-back)
|
|
207
|
+
|
|
208
|
+
**Spatial Cropping (Heliocentric coordinates in Mm):**
|
|
209
|
+
- `--crop-x`: X-range to crop, e.g., `--crop-x -50 50` (optional)
|
|
210
|
+
- `--crop-y`: Y-range to crop, e.g., `--crop-y -50 50` (optional)
|
|
211
|
+
- `--crop-z`: Z-range to crop, e.g., `--crop-z 0 20` (optional)
|
|
212
|
+
- Omit any crop option to use the full range in that dimension
|
|
213
|
+
|
|
214
|
+
**Processing Options:**
|
|
215
|
+
- `--downsample`: Downsampling factor (default: `1` = no downsampling)
|
|
216
|
+
- `--precision`: Numerical precision `float32` or `float64` (default: `float64`)
|
|
217
|
+
- `--mean-mol-wt`: Mean molecular weight (default: `1.29`)
|
|
218
|
+
|
|
219
|
+
**Line Selection:**
|
|
220
|
+
- `--limit-lines`: Limit to specific lines, e.g., `--limit-lines Fe12_195.1190 Fe12_195.1790`
|
|
221
|
+
|
|
222
|
+
#### Output
|
|
223
|
+
|
|
224
|
+
The synthesis produces a pickle file containing:
|
|
225
|
+
- `line_cubes`: Individual NDCube objects for each spectral line with proper WCS
|
|
226
|
+
- `config`: Runtime configuration for reproducibility
|
|
227
|
+
- Additional technical data for internal use
|
|
228
|
+
|
|
229
|
+
#### Performance Tips
|
|
230
|
+
|
|
231
|
+
- Use `--downsample 2` or `--downsample 4` for initial testing
|
|
232
|
+
- Use `--precision float32` to reduce memory usage (may affect accuracy)
|
|
233
|
+
- Use `--limit-lines` to synthesize only specific lines for development
|
|
234
|
+
- Use spatial cropping to focus on regions of interest and reduce computation time
|
|
235
|
+
- Monitor memory usage - full resolution synthesis can require 50+ GB RAM
|
|
236
|
+
- Side views (`--integration-axis x` or `y`) may require different velocity files
|
|
237
|
+
|
|
238
|
+
#### Working with Synthesis Results
|
|
239
|
+
|
|
240
|
+
The synthesis results can be loaded and analyzed using the package API:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
import euvst_response
|
|
244
|
+
|
|
245
|
+
# Load synthesis results - this sums all line cubes into a single cube
|
|
246
|
+
# By default uses Fe XII 195.119 Å as reference for wavelength grid
|
|
247
|
+
cube = euvst_response.load_atmosphere("./run/input/synthesised_spectra.pkl")
|
|
248
|
+
print(f"Combined cube shape: {cube.data.shape}")
|
|
249
|
+
|
|
250
|
+
# Access individual line cubes if needed
|
|
251
|
+
import pickle
|
|
252
|
+
with open("./run/input/synthesised_spectra.pkl", "rb") as f:
|
|
253
|
+
data = pickle.load(f)
|
|
254
|
+
|
|
255
|
+
# Access individual line cubes
|
|
256
|
+
fe12_195 = data["line_cubes"]["Fe12_195.1190"]
|
|
257
|
+
print(f"Fe XII 195.119 cube shape: {fe12_195.data.shape}")
|
|
258
|
+
print(f"Rest wavelength: {fe12_195.meta['rest_wav']}")
|
|
259
|
+
|
|
260
|
+
# List all available lines
|
|
261
|
+
print(f"Available spectral lines: {list(data['line_cubes'].keys())}")
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Pre-computed Atmospheres
|
|
265
|
+
|
|
266
|
+
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
|
|
267
|
+
|
|
268
|
+
**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`.
|
|
269
|
+
|
|
270
|
+
### 3. Simulate the instrument response
|
|
271
|
+
|
|
272
|
+
#### Configuration File
|
|
273
|
+
|
|
274
|
+
ECLIPSE uses YAML configuration files to specify simulation parameters. You can specify single values or lists of values for parameter sweeps.
|
|
275
|
+
|
|
276
|
+
**Key configuration options:**
|
|
277
|
+
- `instrument`: Choose between SWC (EUVST-SW) or EIS (Hinode)
|
|
278
|
+
- `synthesis_file`: Path to the synthesised spectra pickle file (default: `./run/input/synthesised_spectra.pkl`)
|
|
279
|
+
- `reference_line`: Spectral line to use as reference for wavelength grid when combining all lines (default: `Fe12_195.1190`)
|
|
280
|
+
- `expos`: Exposure time(s) for simulations
|
|
281
|
+
- `n_iter`: Number of Monte Carlo iterations
|
|
282
|
+
- Parameter sweeps for filters, detector settings, etc.
|
|
283
|
+
|
|
284
|
+
Here's a complete example configuration file:
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
# Instrument selection
|
|
288
|
+
instrument: SWC # Options: SWC (EUVST Short Wavelength) or EIS (Hinode/EIS)
|
|
289
|
+
|
|
290
|
+
# Synthesis file path - location of the synthesised spectra pickle file
|
|
291
|
+
synthesis_file: ./run/input/synthesised_spectra.pkl # Default location
|
|
292
|
+
|
|
293
|
+
# Reference line for wavelength grid and metadata when combining all spectral lines
|
|
294
|
+
reference_line: Fe12_195.1190 # Default reference line (Fe XII 195.119 Å)
|
|
295
|
+
|
|
296
|
+
# Point Spread Function
|
|
297
|
+
psf: False # Enable PSF convolution
|
|
298
|
+
# Or test with and without PSF:
|
|
299
|
+
# psf: [True, False] # Run simulations both with and without PSF
|
|
300
|
+
|
|
301
|
+
# Exposure times - can be single value or list
|
|
302
|
+
expos: [0.5 s, 1 s, 2 s, 5 s, 10 s, 20 s, 40 s, 80 s]
|
|
303
|
+
|
|
304
|
+
# Monte Carlo simulation parameters
|
|
305
|
+
n_iter: 1000 # Number of Monte Carlo iterations
|
|
306
|
+
ncpu: -1 # Number of CPU cores (-1 = use all available)
|
|
307
|
+
|
|
308
|
+
# Parameter sweeps - you can specify single values or lists for any parameter
|
|
309
|
+
# The simulation will run all combinations of parameters
|
|
310
|
+
|
|
311
|
+
# Slit width
|
|
312
|
+
slit_width: 0.2 arcsec # Narrowest slit on EUVST
|
|
313
|
+
|
|
314
|
+
# Filter parameters (SWC only)
|
|
315
|
+
# Thickness of aluminum oxide layer on entrance filter
|
|
316
|
+
oxide_thickness: 95 angstrom # Default (expected value)
|
|
317
|
+
|
|
318
|
+
# Carbon contamination thickness on filter
|
|
319
|
+
c_thickness: 0 angstrom # Default (ideal case, no contamination)
|
|
320
|
+
|
|
321
|
+
# Aluminum filter thickness
|
|
322
|
+
aluminium_thickness: 1485 angstrom # Default (expected value)
|
|
323
|
+
|
|
324
|
+
# CCD temperature for dark current calculation
|
|
325
|
+
ccd_temperature: -60 Celsius # Default (expected operating temperature)
|
|
326
|
+
|
|
327
|
+
# Visible stray light level
|
|
328
|
+
vis_sl: 0 photon / (s * pixel) # Default, (ideal case, no stray light)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
For guidence on recommended values, see McKevitt et al. (2025) (in prep.).
|
|
332
|
+
|
|
333
|
+
#### Running Simulations
|
|
334
|
+
|
|
335
|
+
Run the instrument response function using:
|
|
336
|
+
```bash
|
|
337
|
+
eclipse --config ./run/input/config.yaml
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Command-line options:**
|
|
341
|
+
- `--config`: Path to YAML configuration file (required)
|
|
342
|
+
- `--debug`: Enable debug mode with IPython breakpoints on errors (optional)
|
|
343
|
+
|
|
344
|
+
#### Output
|
|
345
|
+
|
|
346
|
+
Results are saved as pickle files in the `run/result/` directory with the same base name as the configuration file. The output includes:
|
|
347
|
+
- Simulated detector signals (DN and photon counts)
|
|
348
|
+
- Fitted spectral line parameters (intensity, velocity, width)
|
|
349
|
+
- Statistical analysis of velocity precision vs. exposure time
|
|
350
|
+
- Ground truth comparisons
|
|
351
|
+
|
|
352
|
+
## Acknowledgements
|
|
353
|
+
|
|
354
|
+
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.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
euvst_response/__init__.py,sha256=DKFpqD73FrVmdRx5s29ufqJpl5rxqLGRZ2CEvXzUueY,2105
|
|
2
|
+
euvst_response/analysis.py,sha256=N-yWpd7G2QuBpDTTg2AmYBZk06iqj0zTwb1aoVJF01U,29601
|
|
3
|
+
euvst_response/cli.py,sha256=AIgXpTL6uTjUx4whTYbbo7hr4s0FQCM4TnJbEClIelA,3004
|
|
4
|
+
euvst_response/config.py,sha256=PXFFCH2Bigr13qDEpNZT4YsWdY4JlmWlpnsEjxWEvrQ,15192
|
|
5
|
+
euvst_response/data_processing.py,sha256=6w08qf7NE9lH9MpWbRJtSlWL-6_0GRXGN4RwGicLljQ,9718
|
|
6
|
+
euvst_response/fitting.py,sha256=NSYnT1x9mzbp1R7CEmu71gPUiT2_jJhPSK7svRR2UXE,4920
|
|
7
|
+
euvst_response/main.py,sha256=aSyg2AqgcoLGpX9bCJYWNYz7pKdMZL9J-kd4DaDVTy4,21251
|
|
8
|
+
euvst_response/monte_carlo.py,sha256=-slxTDrBiLh3waZ984fGcYbSIunUmax9honvseNtqg4,5837
|
|
9
|
+
euvst_response/pinhole_diffraction.py,sha256=HgwQMnbZwZQjCoE0INZpWRSVn8WOfrUnCCTGI302Xx0,10018
|
|
10
|
+
euvst_response/psf.py,sha256=Csz1635VwU4bHYgj18qrdoOOqlHJNlzTOzDlLed9P2o,1651
|
|
11
|
+
euvst_response/radiometric.py,sha256=zZqgXT9Vn8Jp2B7e5-PejkcGfZ_1tDDVh-hq4oEGAwU,17501
|
|
12
|
+
euvst_response/synthesis.py,sha256=ALgJ7SfFyzrYl-aL73_AcTEHd1vSyzfj0kDR4STAL1g,33705
|
|
13
|
+
euvst_response/synthesis_cli.py,sha256=XGiMXg0A7pFWXn9Yfps2jDfBphG26vnmLaxJBxalebU,258
|
|
14
|
+
euvst_response/utils.py,sha256=zAiKn2eGJet5glMiXhqWMJ4-sX_JuZHDCTUgMnrYQPI,5360
|
|
15
|
+
euvst_response/data/throughput/grating_reflection_efficiency.dat,sha256=OsaBQ5XhnuZU1EUoDHUZqH9UFThhwNF6s-SnnCh28zI,648
|
|
16
|
+
euvst_response/data/throughput/primary_mirror_coating_reflectance.dat,sha256=1ibNeUajw1zzLfDc25juSAcjwSf4r7Fz1RHZjledcEE,653
|
|
17
|
+
euvst_response/data/throughput/source.txt,sha256=pb3LQz4UzFbE0-ObUOtYpHXgSrOT4CS4Y-2iJwgLn4A,130
|
|
18
|
+
euvst_response/data/throughput/throughput_aluminium_1000_angstrom.dat,sha256=19SmUQBMZsi-yUnmbattTtmPQJZSK8F4yWGvGciZnl8,14100
|
|
19
|
+
euvst_response/data/throughput/throughput_aluminium_oxide_1000_angstrom.dat,sha256=-opQvD-6oK--g6dy5Rcfm1G_2kB0CdHhFk7Bqe7EFzw,14101
|
|
20
|
+
euvst_response/data/throughput/throughput_carbon_1000_angstrom.dat,sha256=TuVMkAr9JBMavD0UVth7kNTvDXLSr47Z60UouQdMUbU,14096
|
|
21
|
+
solarc_eclipse-0.5.0.dist-info/licenses/LICENSE,sha256=j4MYreXd863pwE5tkHNS1jEuA_cpsiv4bEFKODaA7Qw,64
|
|
22
|
+
solarc_eclipse-0.5.0.dist-info/METADATA,sha256=YLF2NrVbkf7Y4_7GZEl8dN1Dj7Ap5mtgf4N5AiQa4XY,12893
|
|
23
|
+
solarc_eclipse-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
solarc_eclipse-0.5.0.dist-info/entry_points.txt,sha256=IeUgF0srH4zC4eaDoz9g8U7aRa4T9N9S1YcKnYLITQc,203
|
|
25
|
+
solarc_eclipse-0.5.0.dist-info/top_level.txt,sha256=xnMo4ka9WH0Cw_EIkb66PpCsWuoZJ2aAFh9IL2p2_3s,15
|
|
26
|
+
solarc_eclipse-0.5.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Do not use or edit this code without permission from the author.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
euvst_response
|