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.
Files changed (34) hide show
  1. {solarc_eclipse-0.5.2/solarc_eclipse.egg-info → solarc_eclipse-0.6.1}/PKG-INFO +62 -23
  2. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/README.md +60 -21
  3. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/__init__.py +2 -2
  4. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/analysis.py +3 -0
  5. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/cli.py +2 -2
  6. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/config.py +4 -4
  7. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data_processing.py +19 -9
  8. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/main.py +45 -1
  9. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/synthesis.py +676 -133
  10. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/pyproject.toml +1 -1
  11. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/setup.py +1 -1
  12. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1/solarc_eclipse.egg-info}/PKG-INFO +62 -23
  13. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/LICENSE +0 -0
  14. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/MANIFEST.in +0 -0
  15. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/grating_reflection_efficiency.dat +0 -0
  16. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/primary_mirror_coating_reflectance.dat +0 -0
  17. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/source.txt +0 -0
  18. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/throughput_aluminium_1000_angstrom.dat +0 -0
  19. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/throughput_aluminium_oxide_1000_angstrom.dat +0 -0
  20. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/data/throughput/throughput_carbon_1000_angstrom.dat +0 -0
  21. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/fitting.py +0 -0
  22. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/monte_carlo.py +0 -0
  23. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/pinhole_diffraction.py +0 -0
  24. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/psf.py +0 -0
  25. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/radiometric.py +0 -0
  26. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/synthesis_cli.py +0 -0
  27. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/euvst_response/utils.py +0 -0
  28. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/setup.cfg +0 -0
  29. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/SOURCES.txt +0 -0
  30. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/dependency_links.txt +0 -0
  31. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/entry_points.txt +0 -0
  32. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/not-zip-safe +0 -0
  33. {solarc_eclipse-0.5.2 → solarc_eclipse-0.6.1}/solarc_eclipse.egg-info/requires.txt +0 -0
  34. {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.5.2
4
- Summary: ECLIPSE: Emission Calculation and Line Intensity Prediction for SOLAR-C EUVST
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 Intensity Prediction for SOLAR-C EUVST
44
+ # ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
45
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.
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
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17543844.svg)](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
- git clone https://github.com/jamesmckevitt/eclipse.git
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 in Mm (default: `0.192 0.192 0.064`)
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 in km/s (default: `5.0`)
200
- - `--vel-lim`: Velocity limit ±km/s (default: `300.0`)
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 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)
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 synthesize only specific lines for development
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 guidence on recommended values, see McKevitt et al. (2025) (in prep.).
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 Intensity Prediction for SOLAR-C EUVST
1
+ # ECLIPSE: Emission Calculation and Line Prediction for SOLAR-C EUVST
2
2
 
3
- 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.
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
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17543844.svg)](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
- git clone https://github.com/jamesmckevitt/eclipse.git
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 in Mm (default: `0.192 0.192 0.064`)
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 in km/s (default: `5.0`)
157
- - `--vel-lim`: Velocity limit ±km/s (default: `300.0`)
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 in Mm):**
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 synthesize only specific lines for development
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 guidence on recommended values, see McKevitt et al. (2025) (in prep.).
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 Intensity Prediction for SOLAR-C EUVST
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.5.2"
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 Intensity Prediction for SOLAR-C EUVST
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 Intensity Prediction for SOLAR-C EUVST",
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 = 230 * u.K
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 230K)
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 293K
142
- gain_e_per_dn: u.Quantity = 2.0 * u.electron / u.DN
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) -> NDCube:
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
- NDCube
38
- Summed cube of all line intensities with proper WCS and metadata.
39
- Uses the wavelength grid from the metadata_line.
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], 0, 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], 0, 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: True)
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":