solarc-eclipse 0.5.2__tar.gz → 0.6.1__tar.gz
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.
- {solarc_eclipse-0.5.2/solarc_eclipse.egg-info → solarc_eclipse-0.6.1}/PKG-INFO +62 -23
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/README.md +60 -21
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/__init__.py +2 -2
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/analysis.py +3 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/cli.py +2 -2
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/config.py +4 -4
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data_processing.py +19 -9
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/main.py +45 -1
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/synthesis.py +676 -133
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/pyproject.toml +1 -1
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/setup.py +1 -1
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1/solarc_eclipse.egg-info}/PKG-INFO +62 -23
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/LICENSE +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/MANIFEST.in +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/grating_reflection_efficiency.dat +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/primary_mirror_coating_reflectance.dat +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/source.txt +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/throughput_aluminium_1000_angstrom.dat +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/throughput_aluminium_oxide_1000_angstrom.dat +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/throughput_carbon_1000_angstrom.dat +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/fitting.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/monte_carlo.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/pinhole_diffraction.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/psf.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/radiometric.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/synthesis_cli.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/utils.py +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/setup.cfg +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/SOURCES.txt +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/dependency_links.txt +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/entry_points.txt +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/not-zip-safe +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/requires.txt +0 -0
- {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: solarc-eclipse
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: ECLIPSE: Emission Calculation and Line
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
|
|
5
5
|
Home-page: https://github.com/jamesmckevitt/eclipse
|
|
6
6
|
Author: James McKevitt
|
|
7
7
|
Author-email: James McKevitt <jm2@mssl.ucl.ac.uk>
|
|
@@ -41,14 +41,16 @@ Dynamic: home-page
|
|
|
41
41
|
Dynamic: license-file
|
|
42
42
|
Dynamic: requires-python
|
|
43
43
|
|
|
44
|
-
# ECLIPSE: Emission Calculation and Line
|
|
44
|
+
# ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
|
|
45
45
|
|
|
46
|
-
The ECLIPSE code (Emission Calculation and Line
|
|
46
|
+
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.
|
|
47
47
|
|
|
48
48
|
Contact: James McKevitt (jm2@mssl.ucl.ac.uk). License: Contact for permission to use.
|
|
49
49
|
|
|
50
50
|
The instrument response generated by this code will be updated during instrument development, testing, and commissioning.
|
|
51
51
|
|
|
52
|
+
[](https://doi.org/10.5281/zenodo.17543844)
|
|
53
|
+
|
|
52
54
|
## Installation
|
|
53
55
|
|
|
54
56
|
### From PyPI (recommended)
|
|
@@ -60,8 +62,7 @@ pip install solarc-eclipse
|
|
|
60
62
|
### From source
|
|
61
63
|
|
|
62
64
|
```bash
|
|
63
|
-
|
|
64
|
-
pip install eclipse
|
|
65
|
+
pip install git+https://github.com/jamesmckevitt/eclipse.git
|
|
65
66
|
```
|
|
66
67
|
|
|
67
68
|
## Quick Start
|
|
@@ -158,15 +159,15 @@ synthesise-spectra \
|
|
|
158
159
|
--vy-file vy/result_prim_3.0270000 \
|
|
159
160
|
--vz-file vz/result_prim_2.0270000 \
|
|
160
161
|
--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 \
|
|
162
|
+
--voxel-dx "0.192 Mm" \
|
|
163
|
+
--voxel-dy "0.192 Mm" \
|
|
164
|
+
--voxel-dz "0.064 Mm" \
|
|
165
|
+
--vel-res "5.0 km/s" \
|
|
166
|
+
--vel-lim "300.0 km/s" \
|
|
166
167
|
--integration-axis z \
|
|
167
|
-
--crop-x -50 50 \
|
|
168
|
-
--crop-y -50 50 \
|
|
169
|
-
--crop-z 0 20 \
|
|
168
|
+
--crop-x "-50 Mm" "50 Mm" \
|
|
169
|
+
--crop-y "-50 Mm" "50 Mm" \
|
|
170
|
+
--crop-z "0 Mm" "20 Mm" \
|
|
170
171
|
--downsample 1 \
|
|
171
172
|
--precision float64 \
|
|
172
173
|
--mean-mol-wt 1.29 \
|
|
@@ -193,11 +194,11 @@ synthesise-spectra --help
|
|
|
193
194
|
|
|
194
195
|
**Grid Parameters:**
|
|
195
196
|
- `--cube-shape`: Cube dimensions as three integers (default: `512 768 256`)
|
|
196
|
-
- `--voxel-dx`, `--voxel-dy`, `--voxel-dz`: Voxel sizes
|
|
197
|
+
- `--voxel-dx`, `--voxel-dy`, `--voxel-dz`: Voxel sizes with units (default: `"0.192 Mm"`, `"0.192 Mm"`, `"0.064 Mm"`)
|
|
197
198
|
|
|
198
199
|
**Velocity Grid:**
|
|
199
|
-
- `--vel-res`: Velocity resolution
|
|
200
|
-
- `--vel-lim`: Velocity limit
|
|
200
|
+
- `--vel-res`: Velocity resolution with units (default: `"5.0 km/s"`)
|
|
201
|
+
- `--vel-lim`: Velocity limit +-km/s with units (default: `"300.0 km/s"`)
|
|
201
202
|
|
|
202
203
|
**Integration and Viewing:**
|
|
203
204
|
- `--integration-axis`: Integration axis: `x`, `y`, or `z` (default: `z`)
|
|
@@ -205,10 +206,10 @@ synthesise-spectra --help
|
|
|
205
206
|
- `x`: Side view from the left (integrates left-to-right)
|
|
206
207
|
- `y`: Side view from the front (integrates front-to-back)
|
|
207
208
|
|
|
208
|
-
**Spatial Cropping (Heliocentric coordinates
|
|
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)
|
|
209
|
+
**Spatial Cropping (Heliocentric coordinates with units):**
|
|
210
|
+
- `--crop-x`: X-range to crop with units, e.g., `--crop-x "-50 Mm" "50 Mm"` (optional)
|
|
211
|
+
- `--crop-y`: Y-range to crop with units, e.g., `--crop-y "-50 Mm" "50 Mm"` (optional)
|
|
212
|
+
- `--crop-z`: Z-range to crop with units, e.g., `--crop-z "0 Mm" "20 Mm"` (optional)
|
|
212
213
|
- Omit any crop option to use the full range in that dimension
|
|
213
214
|
|
|
214
215
|
**Processing Options:**
|
|
@@ -219,6 +220,40 @@ synthesise-spectra --help
|
|
|
219
220
|
**Line Selection:**
|
|
220
221
|
- `--limit-lines`: Limit to specific lines, e.g., `--limit-lines Fe12_195.1190 Fe12_195.1790`
|
|
221
222
|
|
|
223
|
+
#### Dynamic Mode (Time-varying Atmospheres)
|
|
224
|
+
|
|
225
|
+
For simulating raster scans over evolving atmospheres, use dynamic mode which combines MHD timesteps based on instrument scanning:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
synthesise-spectra \
|
|
229
|
+
--data-dir ./data/atmosphere \
|
|
230
|
+
--goft-file ./data/gofnt.sav \
|
|
231
|
+
--output-dir ./run/input \
|
|
232
|
+
--slit-rest-time "40 s" \
|
|
233
|
+
--slit-width "0.2 arcsec" \
|
|
234
|
+
--temp-dir temp \
|
|
235
|
+
--temp-filename eosT \
|
|
236
|
+
--rho-dir rho \
|
|
237
|
+
--rho-filename result_prim_0 \
|
|
238
|
+
--vz-dir vz \
|
|
239
|
+
--vz-filename result_prim_2 \
|
|
240
|
+
--time-dir time \
|
|
241
|
+
--time-filename tau_slice_0.100 \
|
|
242
|
+
--cube-shape 512 768 256 \
|
|
243
|
+
--voxel-dx "0.192 Mm" \
|
|
244
|
+
--voxel-dy "0.192 Mm" \
|
|
245
|
+
--voxel-dz "0.064 Mm" \
|
|
246
|
+
--vel-res "5.0 km/s" \
|
|
247
|
+
--vel-lim "300.0 km/s" \
|
|
248
|
+
--integration-axis z
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Dynamic Mode Options:**
|
|
252
|
+
- `--slit-rest-time`: Slit rest time per position - enables dynamic mode
|
|
253
|
+
- `--slit-width`: Slit width
|
|
254
|
+
- `--temp-dir`, `--rho-dir`, `--vx-dir`, `--vy-dir`, `--vz-dir`, `--time-dir`: Directories containing timestep files
|
|
255
|
+
- `--temp-filename`, `--rho-filename`, `--vx-filename`, `--vy-filename`, `--vz-filename`, `--time-filename`: Filename prefix before timestep suffix
|
|
256
|
+
|
|
222
257
|
#### Output
|
|
223
258
|
|
|
224
259
|
The synthesis produces a pickle file containing:
|
|
@@ -230,7 +265,7 @@ The synthesis produces a pickle file containing:
|
|
|
230
265
|
|
|
231
266
|
- Use `--downsample 2` or `--downsample 4` for initial testing
|
|
232
267
|
- Use `--precision float32` to reduce memory usage (may affect accuracy)
|
|
233
|
-
- Use `--limit-lines` to
|
|
268
|
+
- Use `--limit-lines` to synthesise only specific lines for development
|
|
234
269
|
- Use spatial cropping to focus on regions of interest and reduce computation time
|
|
235
270
|
- Monitor memory usage - full resolution synthesis can require 50+ GB RAM
|
|
236
271
|
- Side views (`--integration-axis x` or `y`) may require different velocity files
|
|
@@ -328,7 +363,11 @@ ccd_temperature: -60 Celsius # Default (expected operating temperature)
|
|
|
328
363
|
vis_sl: 0 photon / (s * pixel) # Default, (ideal case, no stray light)
|
|
329
364
|
```
|
|
330
365
|
|
|
331
|
-
For
|
|
366
|
+
For guidance on recommended values, see McKevitt et al. (2025) (in prep.).
|
|
367
|
+
|
|
368
|
+
If you synthesised data in dynamic mode, your configuration must specify:
|
|
369
|
+
- Exactly one slit width matching the synthesis slit width
|
|
370
|
+
- Exactly one exposure time matching the synthesis exposure time
|
|
332
371
|
|
|
333
372
|
#### Running Simulations
|
|
334
373
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
# ECLIPSE: Emission Calculation and Line
|
|
1
|
+
# ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
|
|
2
2
|
|
|
3
|
-
The ECLIPSE code (Emission Calculation and Line
|
|
3
|
+
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.
|
|
4
4
|
|
|
5
5
|
Contact: James McKevitt (jm2@mssl.ucl.ac.uk). License: Contact for permission to use.
|
|
6
6
|
|
|
7
7
|
The instrument response generated by this code will be updated during instrument development, testing, and commissioning.
|
|
8
8
|
|
|
9
|
+
[](https://doi.org/10.5281/zenodo.17543844)
|
|
10
|
+
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
11
13
|
### From PyPI (recommended)
|
|
@@ -17,8 +19,7 @@ pip install solarc-eclipse
|
|
|
17
19
|
### From source
|
|
18
20
|
|
|
19
21
|
```bash
|
|
20
|
-
|
|
21
|
-
pip install eclipse
|
|
22
|
+
pip install git+https://github.com/jamesmckevitt/eclipse.git
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
## Quick Start
|
|
@@ -115,15 +116,15 @@ synthesise-spectra \
|
|
|
115
116
|
--vy-file vy/result_prim_3.0270000 \
|
|
116
117
|
--vz-file vz/result_prim_2.0270000 \
|
|
117
118
|
--cube-shape 512 768 256 \
|
|
118
|
-
--voxel-dx 0.192 \
|
|
119
|
-
--voxel-dy 0.192 \
|
|
120
|
-
--voxel-dz 0.064 \
|
|
121
|
-
--vel-res 5.0 \
|
|
122
|
-
--vel-lim 300.0 \
|
|
119
|
+
--voxel-dx "0.192 Mm" \
|
|
120
|
+
--voxel-dy "0.192 Mm" \
|
|
121
|
+
--voxel-dz "0.064 Mm" \
|
|
122
|
+
--vel-res "5.0 km/s" \
|
|
123
|
+
--vel-lim "300.0 km/s" \
|
|
123
124
|
--integration-axis z \
|
|
124
|
-
--crop-x -50 50 \
|
|
125
|
-
--crop-y -50 50 \
|
|
126
|
-
--crop-z 0 20 \
|
|
125
|
+
--crop-x "-50 Mm" "50 Mm" \
|
|
126
|
+
--crop-y "-50 Mm" "50 Mm" \
|
|
127
|
+
--crop-z "0 Mm" "20 Mm" \
|
|
127
128
|
--downsample 1 \
|
|
128
129
|
--precision float64 \
|
|
129
130
|
--mean-mol-wt 1.29 \
|
|
@@ -150,11 +151,11 @@ synthesise-spectra --help
|
|
|
150
151
|
|
|
151
152
|
**Grid Parameters:**
|
|
152
153
|
- `--cube-shape`: Cube dimensions as three integers (default: `512 768 256`)
|
|
153
|
-
- `--voxel-dx`, `--voxel-dy`, `--voxel-dz`: Voxel sizes
|
|
154
|
+
- `--voxel-dx`, `--voxel-dy`, `--voxel-dz`: Voxel sizes with units (default: `"0.192 Mm"`, `"0.192 Mm"`, `"0.064 Mm"`)
|
|
154
155
|
|
|
155
156
|
**Velocity Grid:**
|
|
156
|
-
- `--vel-res`: Velocity resolution
|
|
157
|
-
- `--vel-lim`: Velocity limit
|
|
157
|
+
- `--vel-res`: Velocity resolution with units (default: `"5.0 km/s"`)
|
|
158
|
+
- `--vel-lim`: Velocity limit +-km/s with units (default: `"300.0 km/s"`)
|
|
158
159
|
|
|
159
160
|
**Integration and Viewing:**
|
|
160
161
|
- `--integration-axis`: Integration axis: `x`, `y`, or `z` (default: `z`)
|
|
@@ -162,10 +163,10 @@ synthesise-spectra --help
|
|
|
162
163
|
- `x`: Side view from the left (integrates left-to-right)
|
|
163
164
|
- `y`: Side view from the front (integrates front-to-back)
|
|
164
165
|
|
|
165
|
-
**Spatial Cropping (Heliocentric coordinates
|
|
166
|
-
- `--crop-x`: X-range to crop, e.g., `--crop-x -50 50` (optional)
|
|
167
|
-
- `--crop-y`: Y-range to crop, e.g., `--crop-y -50 50` (optional)
|
|
168
|
-
- `--crop-z`: Z-range to crop, e.g., `--crop-z 0 20` (optional)
|
|
166
|
+
**Spatial Cropping (Heliocentric coordinates with units):**
|
|
167
|
+
- `--crop-x`: X-range to crop with units, e.g., `--crop-x "-50 Mm" "50 Mm"` (optional)
|
|
168
|
+
- `--crop-y`: Y-range to crop with units, e.g., `--crop-y "-50 Mm" "50 Mm"` (optional)
|
|
169
|
+
- `--crop-z`: Z-range to crop with units, e.g., `--crop-z "0 Mm" "20 Mm"` (optional)
|
|
169
170
|
- Omit any crop option to use the full range in that dimension
|
|
170
171
|
|
|
171
172
|
**Processing Options:**
|
|
@@ -176,6 +177,40 @@ synthesise-spectra --help
|
|
|
176
177
|
**Line Selection:**
|
|
177
178
|
- `--limit-lines`: Limit to specific lines, e.g., `--limit-lines Fe12_195.1190 Fe12_195.1790`
|
|
178
179
|
|
|
180
|
+
#### Dynamic Mode (Time-varying Atmospheres)
|
|
181
|
+
|
|
182
|
+
For simulating raster scans over evolving atmospheres, use dynamic mode which combines MHD timesteps based on instrument scanning:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
synthesise-spectra \
|
|
186
|
+
--data-dir ./data/atmosphere \
|
|
187
|
+
--goft-file ./data/gofnt.sav \
|
|
188
|
+
--output-dir ./run/input \
|
|
189
|
+
--slit-rest-time "40 s" \
|
|
190
|
+
--slit-width "0.2 arcsec" \
|
|
191
|
+
--temp-dir temp \
|
|
192
|
+
--temp-filename eosT \
|
|
193
|
+
--rho-dir rho \
|
|
194
|
+
--rho-filename result_prim_0 \
|
|
195
|
+
--vz-dir vz \
|
|
196
|
+
--vz-filename result_prim_2 \
|
|
197
|
+
--time-dir time \
|
|
198
|
+
--time-filename tau_slice_0.100 \
|
|
199
|
+
--cube-shape 512 768 256 \
|
|
200
|
+
--voxel-dx "0.192 Mm" \
|
|
201
|
+
--voxel-dy "0.192 Mm" \
|
|
202
|
+
--voxel-dz "0.064 Mm" \
|
|
203
|
+
--vel-res "5.0 km/s" \
|
|
204
|
+
--vel-lim "300.0 km/s" \
|
|
205
|
+
--integration-axis z
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Dynamic Mode Options:**
|
|
209
|
+
- `--slit-rest-time`: Slit rest time per position - enables dynamic mode
|
|
210
|
+
- `--slit-width`: Slit width
|
|
211
|
+
- `--temp-dir`, `--rho-dir`, `--vx-dir`, `--vy-dir`, `--vz-dir`, `--time-dir`: Directories containing timestep files
|
|
212
|
+
- `--temp-filename`, `--rho-filename`, `--vx-filename`, `--vy-filename`, `--vz-filename`, `--time-filename`: Filename prefix before timestep suffix
|
|
213
|
+
|
|
179
214
|
#### Output
|
|
180
215
|
|
|
181
216
|
The synthesis produces a pickle file containing:
|
|
@@ -187,7 +222,7 @@ The synthesis produces a pickle file containing:
|
|
|
187
222
|
|
|
188
223
|
- Use `--downsample 2` or `--downsample 4` for initial testing
|
|
189
224
|
- Use `--precision float32` to reduce memory usage (may affect accuracy)
|
|
190
|
-
- Use `--limit-lines` to
|
|
225
|
+
- Use `--limit-lines` to synthesise only specific lines for development
|
|
191
226
|
- Use spatial cropping to focus on regions of interest and reduce computation time
|
|
192
227
|
- Monitor memory usage - full resolution synthesis can require 50+ GB RAM
|
|
193
228
|
- Side views (`--integration-axis x` or `y`) may require different velocity files
|
|
@@ -285,7 +320,11 @@ ccd_temperature: -60 Celsius # Default (expected operating temperature)
|
|
|
285
320
|
vis_sl: 0 photon / (s * pixel) # Default, (ideal case, no stray light)
|
|
286
321
|
```
|
|
287
322
|
|
|
288
|
-
For
|
|
323
|
+
For guidance on recommended values, see McKevitt et al. (2025) (in prep.).
|
|
324
|
+
|
|
325
|
+
If you synthesised data in dynamic mode, your configuration must specify:
|
|
326
|
+
- Exactly one slit width matching the synthesis slit width
|
|
327
|
+
- Exactly one exposure time matching the synthesis exposure time
|
|
289
328
|
|
|
290
329
|
#### Running Simulations
|
|
291
330
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
|
-
ECLIPSE: Emission Calculation and Line
|
|
2
|
+
ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
|
|
3
3
|
|
|
4
4
|
This package provides tools for modeling the performance of the EUV spectrograph EUVST, on SOLAR-C.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "0.
|
|
7
|
+
__version__ = "0.6.1"
|
|
8
8
|
__author__ = "James McKevitt"
|
|
9
9
|
__email__ = "jm2@mssl.ucl.ac.uk"
|
|
10
10
|
|
|
@@ -561,6 +561,9 @@ def create_sunpy_maps_from_combo(
|
|
|
561
561
|
|
|
562
562
|
maps['velocity_std'] = sunpy.map.Map(analysis["v_std"].value.T, wcs_2d)
|
|
563
563
|
maps['velocity_std'].meta['bunit'] = str(analysis["v_std"].unit)
|
|
564
|
+
|
|
565
|
+
maps['velocity_true'] = sunpy.map.Map(analysis["v_true"].value.T, wcs_2d)
|
|
566
|
+
maps['velocity_true'].meta['bunit'] = str(analysis["v_true"].unit)
|
|
564
567
|
|
|
565
568
|
# Velocity error (truth - mean)
|
|
566
569
|
maps['velocity_err'] = sunpy.map.Map(analysis["v_err"].value.T, wcs_2d)
|
|
@@ -20,7 +20,7 @@ ASCII_LOGO = """
|
|
|
20
20
|
| |___| |____| |____ _| |_| | ____) | |____
|
|
21
21
|
|______\_____|______|_____|_| |_____/|______|
|
|
22
22
|
|
|
23
|
-
ECLIPSE: Emission Calculation and Line
|
|
23
|
+
ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
|
|
24
24
|
|
|
25
25
|
Contact: James McKevitt (jm2@mssl.ucl.ac.uk). License: Contact for permission to use.
|
|
26
26
|
"""
|
|
@@ -35,7 +35,7 @@ def main():
|
|
|
35
35
|
"""Main CLI entry point."""
|
|
36
36
|
parser = argparse.ArgumentParser(
|
|
37
37
|
prog="eclipse",
|
|
38
|
-
description="ECLIPSE: Emission Calculation and Line
|
|
38
|
+
description="ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST",
|
|
39
39
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
40
40
|
)
|
|
41
41
|
|
|
@@ -49,14 +49,14 @@ def calculate_dark_current(temp: u.Quantity, q_d0_293k: u.Quantity, ccd_type: st
|
|
|
49
49
|
"""
|
|
50
50
|
temp_kelvin = temp.to(u.Kelvin, equivalencies=u.temperature())
|
|
51
51
|
max_temp = 300 * u.K
|
|
52
|
-
min_temp =
|
|
52
|
+
min_temp = 198 * u.K
|
|
53
53
|
|
|
54
54
|
# Check temperature limits
|
|
55
55
|
if temp_kelvin > max_temp:
|
|
56
56
|
raise ValueError(f"Cannot calculate dark current at {temp_kelvin}. "
|
|
57
57
|
f"Maximum temperature is {max_temp}")
|
|
58
58
|
|
|
59
|
-
# Apply minimum temperature limit (clamp to
|
|
59
|
+
# Apply minimum temperature limit (clamp to 198K; based on MSSL test results)
|
|
60
60
|
if temp_kelvin < min_temp:
|
|
61
61
|
temp_kelvin = min_temp
|
|
62
62
|
|
|
@@ -138,8 +138,8 @@ class Detector_SWC:
|
|
|
138
138
|
qe_euv: float = 0.76
|
|
139
139
|
read_noise_rms: u.Quantity = 10.0 * u.electron / u.pixel
|
|
140
140
|
dark_current: u.Quantity = 21.0 * u.electron / (u.pixel * u.s) # Default value, will be overridden
|
|
141
|
-
_dark_current_293k: u.Quantity = 20000.0 * u.electron / (u.pixel * u.s) # Q_d0 at
|
|
142
|
-
gain_e_per_dn: u.Quantity = 2.
|
|
141
|
+
_dark_current_293k: u.Quantity = 20000.0 * u.electron / (u.pixel * u.s) # Q_d0 at 293 K
|
|
142
|
+
gain_e_per_dn: u.Quantity = 2.78 * u.electron / u.DN # MSSL EM test results
|
|
143
143
|
max_dn: u.Quantity = 65535 * u.DN / u.pixel
|
|
144
144
|
pix_size: u.Quantity = (13.5 * u.um).cgs / u.pixel
|
|
145
145
|
wvl_res: u.Quantity = (16.9 * u.mAA).cgs / u.pixel
|
|
@@ -16,7 +16,7 @@ from tqdm import tqdm
|
|
|
16
16
|
from .utils import tqdm_joblib, distance_to_angle
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def load_atmosphere(pkl_file: str, metadata_line: str = None) ->
|
|
19
|
+
def load_atmosphere(pkl_file: str, metadata_line: str = None) -> tuple:
|
|
20
20
|
"""
|
|
21
21
|
Load synthetic atmosphere cube from pickle file.
|
|
22
22
|
|
|
@@ -34,9 +34,10 @@ def load_atmosphere(pkl_file: str, metadata_line: str = None) -> NDCube:
|
|
|
34
34
|
|
|
35
35
|
Returns
|
|
36
36
|
-------
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
tuple
|
|
38
|
+
(summed_cube, dynamic_mode_info) where:
|
|
39
|
+
- summed_cube: NDCube with summed line intensities
|
|
40
|
+
- dynamic_mode_info: dict with dynamic mode metadata (or None if static)
|
|
40
41
|
"""
|
|
41
42
|
with open(pkl_file, "rb") as f:
|
|
42
43
|
tmp = dill.load(f)
|
|
@@ -49,6 +50,9 @@ def load_atmosphere(pkl_file: str, metadata_line: str = None) -> NDCube:
|
|
|
49
50
|
if not line_cubes:
|
|
50
51
|
raise ValueError("No line cubes found in synthesis results")
|
|
51
52
|
|
|
53
|
+
# Get dynamic mode info if present
|
|
54
|
+
dynamic_mode_info = tmp.get("dynamic_mode", {"enabled": False})
|
|
55
|
+
|
|
52
56
|
# Get the line names
|
|
53
57
|
line_names = list(line_cubes.keys())
|
|
54
58
|
|
|
@@ -96,7 +100,8 @@ def load_atmosphere(pkl_file: str, metadata_line: str = None) -> NDCube:
|
|
|
96
100
|
"combined_lines": line_names,
|
|
97
101
|
"n_lines": len(line_names),
|
|
98
102
|
"metadata_source": metadata_line,
|
|
99
|
-
"summed_intensity": True
|
|
103
|
+
"summed_intensity": True,
|
|
104
|
+
"dynamic_mode": dynamic_mode_info,
|
|
100
105
|
})
|
|
101
106
|
|
|
102
107
|
# Create the summed cube using the reference cube's WCS
|
|
@@ -107,7 +112,7 @@ def load_atmosphere(pkl_file: str, metadata_line: str = None) -> NDCube:
|
|
|
107
112
|
meta=combined_meta
|
|
108
113
|
)
|
|
109
114
|
|
|
110
|
-
return summed_cube
|
|
115
|
+
return summed_cube, dynamic_mode_info
|
|
111
116
|
|
|
112
117
|
|
|
113
118
|
def resample_ndcube_spectral_axis(ndcube, spectral_axis, output_resolution, ncpu=-1):
|
|
@@ -191,6 +196,11 @@ def reproject_ndcube_heliocentric_to_helioprojective(new_cube_spec, sim, det):
|
|
|
191
196
|
dy = wcs_hc.wcs.cdelt[1] * wcs_hc.wcs.cunit[1]
|
|
192
197
|
x_angle = distance_to_angle(dx)
|
|
193
198
|
y_angle = distance_to_angle(dy)
|
|
199
|
+
|
|
200
|
+
crval_x_hc = wcs_hc.wcs.crval[2] * u.Unit(wcs_hc.wcs.cunit[2])
|
|
201
|
+
crval_y_hc = wcs_hc.wcs.crval[1] * u.Unit(wcs_hc.wcs.cunit[1])
|
|
202
|
+
crval_x_hp = distance_to_angle(crval_x_hc).to_value(u.arcsec)
|
|
203
|
+
crval_y_hp = distance_to_angle(crval_y_hc).to_value(u.arcsec)
|
|
194
204
|
|
|
195
205
|
wcs_hp = WCS(naxis=3)
|
|
196
206
|
wcs_hp.wcs.ctype = [wcs_hc.wcs.ctype[0], 'HPLT-TAN', 'HPLN-TAN']
|
|
@@ -198,7 +208,7 @@ def reproject_ndcube_heliocentric_to_helioprojective(new_cube_spec, sim, det):
|
|
|
198
208
|
wcs_hp.wcs.crpix = [wcs_hc.wcs.crpix[0],
|
|
199
209
|
(ny + 1) / 2,
|
|
200
210
|
(nx + 1) / 2]
|
|
201
|
-
wcs_hp.wcs.crval = [wcs_hc.wcs.crval[0],
|
|
211
|
+
wcs_hp.wcs.crval = [wcs_hc.wcs.crval[0], crval_y_hp, crval_x_hp]
|
|
202
212
|
wcs_hp.wcs.cdelt = [wcs_hc.wcs.cdelt[0], y_angle.to_value(u.arcsec), x_angle.to_value(u.arcsec)]
|
|
203
213
|
new_cube_spec_hp = NDCube(new_cube_spec.data, wcs=wcs_hp, unit=new_cube_spec.unit, meta=new_cube_spec.meta)
|
|
204
214
|
|
|
@@ -219,7 +229,7 @@ def reproject_ndcube_heliocentric_to_helioprojective(new_cube_spec, sim, det):
|
|
|
219
229
|
wcs_tgt.wcs.ctype = [wcs_hc.wcs.ctype[0], 'HPLT-TAN', 'HPLN-TAN']
|
|
220
230
|
wcs_tgt.wcs.cunit = [wcs_hc.wcs.cunit[0], 'arcsec', 'arcsec']
|
|
221
231
|
wcs_tgt.wcs.crpix = [crpix_spec, crpix_y, crpix_x]
|
|
222
|
-
wcs_tgt.wcs.crval = [wcs_hc.wcs.crval[0],
|
|
232
|
+
wcs_tgt.wcs.crval = [wcs_hc.wcs.crval[0], crval_y_hp, crval_x_hp]
|
|
223
233
|
wcs_tgt.wcs.cdelt = [wcs_hc.wcs.cdelt[0],
|
|
224
234
|
(det.plate_scale_angle * u.pix).to_value(u.arcsec),
|
|
225
235
|
(sim.slit_width).to_value(u.arcsec)]
|
|
@@ -248,7 +258,7 @@ def rebin_atmosphere(cube_sim, det, sim, use_dask=False):
|
|
|
248
258
|
sim : Simulation
|
|
249
259
|
Simulation configuration
|
|
250
260
|
use_dask : bool, optional
|
|
251
|
-
Whether to use Dask for automatic parallelization (default:
|
|
261
|
+
Whether to use Dask for automatic parallelization (default: False)
|
|
252
262
|
|
|
253
263
|
Returns
|
|
254
264
|
-------
|
|
@@ -226,7 +226,51 @@ def main() -> None:
|
|
|
226
226
|
# Load synthetic atmosphere cube
|
|
227
227
|
print("Loading atmosphere...")
|
|
228
228
|
print(f"Using '{reference_line}' as reference line for wavelength grid and metadata...")
|
|
229
|
-
cube_sim = load_atmosphere(synthesis_file, reference_line)
|
|
229
|
+
cube_sim, dynamic_mode_info = load_atmosphere(synthesis_file, reference_line)
|
|
230
|
+
|
|
231
|
+
# Check for dynamic mode and validate parameters
|
|
232
|
+
is_dynamic_mode = dynamic_mode_info.get("enabled", False)
|
|
233
|
+
if is_dynamic_mode:
|
|
234
|
+
print("Synthesis was done in DYNAMIC MODE (time-varying atmosphere)")
|
|
235
|
+
print(f" Slit width: {dynamic_mode_info['slit_width']}")
|
|
236
|
+
print(f" Slit rest time: {dynamic_mode_info['slit_rest_time']}")
|
|
237
|
+
print(f" Timesteps used: {len(dynamic_mode_info['available_timesteps'])}")
|
|
238
|
+
|
|
239
|
+
# Check that exactly one slit width is provided for dynamic mode
|
|
240
|
+
synth_slit_width = dynamic_mode_info["slit_width"]
|
|
241
|
+
if len(slit_widths) != 1:
|
|
242
|
+
raise ValueError(
|
|
243
|
+
f"Dynamic mode synthesis requires exactly one slit width. "
|
|
244
|
+
f"Config specifies {len(slit_widths)} slit widths: {slit_widths}. "
|
|
245
|
+
f"Please provide only the synthesis slit width: {synth_slit_width}"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Validate that the single slit width matches synthesis
|
|
249
|
+
if not np.isclose(slit_widths[0].to_value(u.arcsec), synth_slit_width.to_value(u.arcsec), rtol=1e-6):
|
|
250
|
+
raise ValueError(
|
|
251
|
+
f"Slit width mismatch: synthesis was done with {synth_slit_width}, "
|
|
252
|
+
f"but config specifies {slit_widths[0]}. "
|
|
253
|
+
f"For dynamic mode synthesis, the slit width must match exactly: {synth_slit_width}"
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# Check that exactly one exposure time is provided for dynamic mode
|
|
257
|
+
synth_rest_time = dynamic_mode_info["slit_rest_time"]
|
|
258
|
+
if len(exposures) != 1:
|
|
259
|
+
raise ValueError(
|
|
260
|
+
f"Dynamic mode synthesis requires exactly one exposure time. "
|
|
261
|
+
f"Config specifies {len(exposures)} exposure times: {exposures}. "
|
|
262
|
+
f"Please provide only the synthesis slit rest time: {synth_rest_time}"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Validate that the single exposure time matches synthesis
|
|
266
|
+
if not np.isclose(exposures[0].to_value(u.s), synth_rest_time.to_value(u.s), rtol=1e-6):
|
|
267
|
+
raise ValueError(
|
|
268
|
+
f"Exposure time mismatch: synthesis was done with {synth_rest_time}, "
|
|
269
|
+
f"but config specifies {exposures[0]}. "
|
|
270
|
+
f"For dynamic mode synthesis, the exposure time must match exactly: {synth_rest_time}"
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
print(" Dynamic mode parameters validated successfully!")
|
|
230
274
|
|
|
231
275
|
# Set up base detector configuration (doesn't change with parameters)
|
|
232
276
|
if instrument == "SWC":
|