dkist-processing-cryonirsp 1.9.0__py3-none-any.whl → 1.10.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.

Potentially problematic release.


This version of dkist-processing-cryonirsp might be problematic. Click here for more details.

Files changed (27) hide show
  1. dkist_processing_cryonirsp/config.py +4 -1
  2. dkist_processing_cryonirsp/models/constants.py +14 -1
  3. dkist_processing_cryonirsp/models/parameters.py +11 -19
  4. dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py +3 -2
  5. dkist_processing_cryonirsp/tasks/__init__.py +1 -1
  6. dkist_processing_cryonirsp/tasks/parse.py +15 -3
  7. dkist_processing_cryonirsp/tasks/sp_wavelength_calibration.py +300 -0
  8. dkist_processing_cryonirsp/tasks/write_l1.py +6 -16
  9. dkist_processing_cryonirsp/tests/conftest.py +13 -20
  10. dkist_processing_cryonirsp/tests/header_models.py +12 -0
  11. dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py +17 -17
  12. dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py +17 -19
  13. dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py +3 -3
  14. dkist_processing_cryonirsp/tests/test_cryo_constants.py +4 -1
  15. dkist_processing_cryonirsp/tests/test_parameters.py +4 -0
  16. dkist_processing_cryonirsp/tests/test_parse.py +28 -2
  17. dkist_processing_cryonirsp/tests/{test_sp_dispersion_axis_correction.py → test_sp_wavelength_calibration.py} +6 -23
  18. dkist_processing_cryonirsp/tests/test_write_l1.py +15 -15
  19. dkist_processing_cryonirsp/workflows/sp_l0_processing.py +3 -3
  20. dkist_processing_cryonirsp/workflows/trial_workflows.py +3 -3
  21. {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0.dist-info}/METADATA +14 -13
  22. {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0.dist-info}/RECORD +26 -25
  23. docs/index.rst +1 -0
  24. docs/wavelength_calibration.rst +62 -0
  25. dkist_processing_cryonirsp/tasks/sp_dispersion_axis_correction.py +0 -465
  26. {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0.dist-info}/WHEEL +0 -0
  27. {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@ from dkist_service_configuration.logging import logger
14
14
  from dkist_processing_cryonirsp.models.constants import CryonirspBudName
15
15
  from dkist_processing_cryonirsp.models.tags import CryonirspTag
16
16
  from dkist_processing_cryonirsp.tasks import CIBeamBoundariesCalibration
17
- from dkist_processing_cryonirsp.tasks import SPDispersionAxisCorrection
17
+ from dkist_processing_cryonirsp.tasks import SPWavelengthCalibration
18
18
  from dkist_processing_cryonirsp.tasks.bad_pixel_map import BadPixelMapCalibration
19
19
  from dkist_processing_cryonirsp.tasks.cryonirsp_base import CryonirspTaskBase
20
20
  from dkist_processing_cryonirsp.tasks.dark import DarkCalibration
@@ -47,9 +47,6 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
47
47
  LoadBeamBoundaryCal,
48
48
  )
49
49
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import LoadDarkCal
50
- from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
51
- LoadDispersionAxisCorrection,
52
- )
53
50
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
54
51
  LoadGeometricCal,
55
52
  )
@@ -61,6 +58,9 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
61
58
  LoadLinearizedFiles,
62
59
  )
63
60
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import LoadSolarCal
61
+ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
62
+ LoadWavelengthCorrection,
63
+ )
64
64
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
65
65
  save_parsing_task,
66
66
  )
@@ -71,9 +71,6 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
71
71
  SaveBeamBoundaryCal,
72
72
  )
73
73
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import SaveDarkCal
74
- from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
75
- SaveDispersionAxisCorrection,
76
- )
77
74
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
78
75
  SaveGeometricCal,
79
76
  )
@@ -85,6 +82,9 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
85
82
  SaveLinearizedFiles,
86
83
  )
87
84
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import SaveSolarCal
85
+ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
86
+ SaveWavelengthCorrection,
87
+ )
88
88
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
89
89
  tag_inputs_task,
90
90
  )
@@ -224,7 +224,7 @@ def SP_workflow(
224
224
  load_lamp: bool = False,
225
225
  load_geometric: bool = False,
226
226
  load_solar: bool = False,
227
- load_dispersion_correction: bool = False,
227
+ load_wavelength_correction: bool = False,
228
228
  load_inst_pol: bool = False,
229
229
  ) -> None:
230
230
  if load_beam_boundaries:
@@ -257,11 +257,11 @@ def SP_workflow(
257
257
  manual_processing_run.run_task(task=SPSolarGainCalibration)
258
258
  manual_processing_run.run_task(task=SaveSolarCal)
259
259
 
260
- if load_dispersion_correction:
261
- manual_processing_run.run_task(task=LoadDispersionAxisCorrection)
260
+ if load_wavelength_correction:
261
+ manual_processing_run.run_task(task=LoadWavelengthCorrection)
262
262
  else:
263
- manual_processing_run.run_task(task=SPDispersionAxisCorrection)
264
- manual_processing_run.run_task(task=SaveDispersionAxisCorrection)
263
+ manual_processing_run.run_task(task=SPWavelengthCalibration)
264
+ manual_processing_run.run_task(task=SaveWavelengthCorrection)
265
265
 
266
266
  if load_inst_pol:
267
267
  manual_processing_run.run_task(task=LoadInstPolCal)
@@ -287,7 +287,7 @@ def main(
287
287
  load_lamp: bool = False,
288
288
  load_geometric: bool = False,
289
289
  load_solar: bool = False,
290
- load_dispersion_correction: bool = False,
290
+ load_wavelength_correction: bool = False,
291
291
  load_inst_pol: bool = False,
292
292
  use_apm: bool = False,
293
293
  param_path: Path = None,
@@ -378,7 +378,7 @@ def main(
378
378
  load_lamp=load_lamp,
379
379
  load_geometric=load_geometric,
380
380
  load_solar=load_solar,
381
- load_dispersion_correction=load_dispersion_correction,
381
+ load_wavelength_correction=load_wavelength_correction,
382
382
  load_inst_pol=load_inst_pol,
383
383
  )
384
384
  elif arm_id == "CI":
@@ -481,8 +481,8 @@ if __name__ == "__main__":
481
481
  )
482
482
  parser.add_argument(
483
483
  "-W",
484
- "--load-dispersion-correction",
485
- help="Load dispersion correction solution from previously saved run",
484
+ "--load-wavelength-correction",
485
+ help="Load wavelength correction solution from previously saved run",
486
486
  action="store_true",
487
487
  )
488
488
  parser.add_argument(
@@ -524,7 +524,7 @@ if __name__ == "__main__":
524
524
  load_lamp=args.load_lamp,
525
525
  load_geometric=args.load_geometric,
526
526
  load_solar=args.load_solar,
527
- load_dispersion_correction=args.load_dispersion_correction,
527
+ load_wavelength_correction=args.load_wavelength_correction,
528
528
  load_inst_pol=args.load_inst_pol,
529
529
  use_apm=args.use_apm,
530
530
  param_path=Path(args.param_path),
@@ -39,12 +39,10 @@ from dkist_processing_cryonirsp.tasks.parse import ParseL0CryonirspSPLinearizedD
39
39
  from dkist_processing_cryonirsp.tasks.quality_metrics import CryonirspL0QualityMetrics
40
40
  from dkist_processing_cryonirsp.tasks.quality_metrics import CryonirspL1QualityMetrics
41
41
  from dkist_processing_cryonirsp.tasks.sp_beam_boundaries import SPBeamBoundariesCalibration
42
- from dkist_processing_cryonirsp.tasks.sp_dispersion_axis_correction import (
43
- SPDispersionAxisCorrection,
44
- )
45
42
  from dkist_processing_cryonirsp.tasks.sp_geometric import SPGeometricCalibration
46
43
  from dkist_processing_cryonirsp.tasks.sp_science import SPScienceCalibration
47
44
  from dkist_processing_cryonirsp.tasks.sp_solar_gain import SPSolarGainCalibration
45
+ from dkist_processing_cryonirsp.tasks.sp_wavelength_calibration import SPWavelengthCalibration
48
46
  from dkist_processing_cryonirsp.tasks.write_l1 import CIWriteL1Frame
49
47
  from dkist_processing_cryonirsp.tasks.write_l1 import SPWriteL1Frame
50
48
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
@@ -61,9 +59,6 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
61
59
  LoadBeamBoundaryCal,
62
60
  )
63
61
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import LoadDarkCal
64
- from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
65
- LoadDispersionAxisCorrection,
66
- )
67
62
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
68
63
  LoadGeometricCal,
69
64
  )
@@ -75,6 +70,9 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
75
70
  LoadLinearizedFiles,
76
71
  )
77
72
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import LoadSolarCal
73
+ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
74
+ LoadWavelengthCorrection,
75
+ )
78
76
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
79
77
  save_parsing_task,
80
78
  )
@@ -85,9 +83,6 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
85
83
  SaveBeamBoundaryCal,
86
84
  )
87
85
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import SaveDarkCal
88
- from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
89
- SaveDispersionAxisCorrection,
90
- )
91
86
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
92
87
  SaveGeometricCal,
93
88
  )
@@ -99,6 +94,9 @@ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers
99
94
  SaveLinearizedFiles,
100
95
  )
101
96
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import SaveSolarCal
97
+ from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
98
+ SaveWavelengthCorrection,
99
+ )
102
100
  from dkist_processing_cryonirsp.tests.local_trial_workflows.local_trial_helpers import (
103
101
  tag_inputs_task,
104
102
  )
@@ -254,7 +252,7 @@ def SP_workflow(
254
252
  load_geometric: bool = False,
255
253
  load_solar: bool = False,
256
254
  load_inst_pol: bool = False,
257
- load_dispersion_correction: bool = False,
255
+ load_wavelength_correction: bool = False,
258
256
  ) -> None:
259
257
  if load_beam_boundaries:
260
258
  manual_processing_run.run_task(task=LoadBeamBoundaryCal)
@@ -286,11 +284,11 @@ def SP_workflow(
286
284
  manual_processing_run.run_task(task=SPSolarGainCalibration)
287
285
  manual_processing_run.run_task(task=SaveSolarCal)
288
286
 
289
- if load_dispersion_correction:
290
- manual_processing_run.run_task(task=LoadDispersionAxisCorrection)
287
+ if load_wavelength_correction:
288
+ manual_processing_run.run_task(task=LoadWavelengthCorrection)
291
289
  else:
292
- manual_processing_run.run_task(task=SPDispersionAxisCorrection)
293
- manual_processing_run.run_task(task=SaveDispersionAxisCorrection)
290
+ manual_processing_run.run_task(task=SPWavelengthCalibration)
291
+ manual_processing_run.run_task(task=SaveWavelengthCorrection)
294
292
 
295
293
  if load_inst_pol:
296
294
  manual_processing_run.run_task(task=LoadInstPolCal)
@@ -322,8 +320,8 @@ def main(
322
320
  load_lamp: bool = False,
323
321
  load_geometric: bool = False,
324
322
  load_solar: bool = False,
325
- load_dispersion_correction: bool = False,
326
323
  load_inst_pol: bool = False,
324
+ load_wavelength_calibration: bool = False,
327
325
  use_apm: bool = False,
328
326
  param_path: Path = None,
329
327
  transfer_trial_data: str | None = None,
@@ -414,7 +412,7 @@ def main(
414
412
  load_lamp=load_lamp,
415
413
  load_geometric=load_geometric,
416
414
  load_solar=load_solar,
417
- load_dispersion_correction=load_dispersion_correction,
415
+ load_wavelength_correction=load_wavelength_calibration,
418
416
  load_inst_pol=load_inst_pol,
419
417
  )
420
418
  elif arm_id == "CI":
@@ -565,8 +563,8 @@ if __name__ == "__main__":
565
563
  )
566
564
  parser.add_argument(
567
565
  "-W",
568
- "--load-dispersion-correction",
569
- help="Load dispersion correction solution from previously saved run",
566
+ "--load-wavelength-calibration",
567
+ help="Load wavelength calibration solution from previously saved run",
570
568
  action="store_true",
571
569
  )
572
570
  parser.add_argument(
@@ -603,7 +601,7 @@ if __name__ == "__main__":
603
601
  load_lamp=args.load_lamp,
604
602
  load_geometric=args.load_geometric,
605
603
  load_solar=args.load_solar,
606
- load_dispersion_correction=args.load_dispersion_correction,
604
+ load_wavelength_calibration=args.load_wavelength_calibration,
607
605
  load_inst_pol=args.load_inst_pol,
608
606
  use_apm=args.use_apm,
609
607
  param_path=Path(args.param_path),
@@ -358,7 +358,7 @@ class SaveSolarCal(SaveTaskTags):
358
358
  ]
359
359
 
360
360
 
361
- class SaveDispersionAxisCorrection(SaveTaskTags):
361
+ class SaveWavelengthCorrection(SaveTaskTags):
362
362
  @property
363
363
  def task_str(self) -> str:
364
364
  return CryonirspTaskName.spectral_fit.value
@@ -383,10 +383,10 @@ class LoadSolarCal(LoadTaskTags):
383
383
  return "solar_cal.asdf"
384
384
 
385
385
 
386
- class LoadDispersionAxisCorrection(LoadTaskTags):
386
+ class LoadWavelengthCorrection(LoadTaskTags):
387
387
  @property
388
388
  def relative_save_file(self) -> str:
389
- return "sp_dispersion_axis_correction.asdf"
389
+ return "sp_wavelength_correction.asdf"
390
390
 
391
391
 
392
392
  class SaveInstPolCal(SaveTaskTags):
@@ -1,6 +1,7 @@
1
1
  from dataclasses import asdict
2
2
  from dataclasses import dataclass
3
3
 
4
+ import astropy.units as u
4
5
  import pytest
5
6
 
6
7
  from dkist_processing_cryonirsp.models.exposure_conditions import AllowableOpticalDensityFilterNames
@@ -29,6 +30,7 @@ def testing_constants(polarimetric):
29
30
  )
30
31
  modulator_spin_mode: str = "Continuous" if polarimetric else "Off"
31
32
  retarder_name: str = "SiO2 OC"
33
+ grating_constant: float = 6.28
32
34
  # We don't need all the common ones, but let's put one just to check
33
35
  instrument: str = "CHECK_OUT_THIS_INSTRUMENT"
34
36
  arm_id: str = "SP"
@@ -69,10 +71,11 @@ def cryo_science_task_with_constants(
69
71
  def test_cryo_constants(cryo_science_task_with_constants, expected_constant_dict, polarimetric):
70
72
  task = cryo_science_task_with_constants
71
73
  for k, v in expected_constant_dict.items():
72
- if k.lower() in ["modulator_spin_mode", "retarder_name"]:
74
+ if k.lower() in ["modulator_spin_mode", "retarder_name", "grating_constant"]:
73
75
  continue
74
76
  if type(v) is tuple:
75
77
  v = list(v)
76
78
  assert getattr(task.constants, k.lower()) == v
77
79
  assert task.constants.correct_for_polarization == polarimetric
78
80
  assert task.constants.pac_init_set == "OCCal_VIS"
81
+ assert task.constants.grating_constant == expected_constant_dict["GRATING_CONSTANT"] / u.mm
@@ -12,6 +12,7 @@ from hypothesis import given
12
12
  from hypothesis import HealthCheck
13
13
  from hypothesis import settings
14
14
  from hypothesis import strategies as st
15
+ from pydantic import BaseModel
15
16
 
16
17
  from dkist_processing_cryonirsp.models.parameters import CryonirspParameters
17
18
  from dkist_processing_cryonirsp.models.parameters import CryonirspParsingParameters
@@ -199,9 +200,12 @@ def test_parameters(basic_science_task_with_parameter_mixin):
199
200
  or parameter_name in PARSE_PARAMETER_NAMES
200
201
  ):
201
202
  continue
203
+
202
204
  accessed_parameter_value = getattr(task_params, parameter_name)
203
205
  if isinstance(accessed_parameter_value, Quantity):
204
206
  assert pv == accessed_parameter_value.value
207
+ elif isinstance(accessed_parameter_value, BaseModel):
208
+ assert accessed_parameter_value.model_dump() == pv
205
209
  else:
206
210
  assert pv == getattr(task_params, parameter_name)
207
211
 
@@ -88,6 +88,8 @@ def write_solar_gain_frames_to_task(
88
88
  array_shape=(2, 2, 1),
89
89
  tags: list[str] | None = None,
90
90
  num_modstates: int = 1,
91
+ center_wavelength: float = 1080.0,
92
+ slit_width: float = 52.0,
91
93
  ):
92
94
  num_frames = 0
93
95
  for modstate in range(1, num_modstates + 1):
@@ -96,6 +98,8 @@ def write_solar_gain_frames_to_task(
96
98
  exposure_condition=exposure_condition,
97
99
  num_modstates=num_modstates,
98
100
  modstate=modstate,
101
+ center_wavelength=center_wavelength,
102
+ slit_width=slit_width,
99
103
  )
100
104
 
101
105
  num_frames += _write_frames_to_task(
@@ -146,6 +150,8 @@ def write_observe_frames_to_task(
146
150
  exposure_condition: ExposureConditions,
147
151
  change_translated_headers: Callable[[fits.Header | None], fits.Header] = lambda x: x,
148
152
  array_shape=(2, 2, 1),
153
+ center_wavelength: float = 1080.0,
154
+ slit_width: float = 52.0,
149
155
  tags: list[str] | None = None,
150
156
  ):
151
157
  num_frames = 0
@@ -174,6 +180,8 @@ def write_observe_frames_to_task(
174
180
  num_meas=num_measurements,
175
181
  meas_num=measurement,
176
182
  arm_id=arm_id,
183
+ center_wavelength=center_wavelength,
184
+ slit_width=slit_width,
177
185
  )
178
186
  start_time += frame_delta_time
179
187
 
@@ -250,6 +258,8 @@ def make_linearized_test_frames(
250
258
  num_map_scans: int = 1,
251
259
  num_sub_repeats: int = 1,
252
260
  num_measurements: int = 1,
261
+ center_wavelength: float = 1080.0,
262
+ slit_width: float = 52.0,
253
263
  extra_headers: dict | None = None,
254
264
  ):
255
265
  if extra_headers is None:
@@ -271,13 +281,15 @@ def make_linearized_test_frames(
271
281
  task,
272
282
  tags=lin_tag,
273
283
  exposure_condition=lamp_exposure_condition,
274
- num_modstates=num_modstates or 1, # We *always* need dark frames
284
+ num_modstates=num_modstates or 1, # We *always* need lamp frames
275
285
  )
276
286
  num_solar = write_solar_gain_frames_to_task(
277
287
  task,
278
288
  tags=lin_tag,
279
289
  exposure_condition=solar_exposure_condition,
280
- num_modstates=num_modstates or 1, # We *always* need dark frames
290
+ num_modstates=num_modstates or 1, # We *always* need solar frames
291
+ center_wavelength=center_wavelength,
292
+ slit_width=slit_width,
281
293
  )
282
294
 
283
295
  num_polcal += write_polcal_frames_to_task(
@@ -299,6 +311,8 @@ def make_linearized_test_frames(
299
311
  num_measurements=num_measurements,
300
312
  tags=lin_tag,
301
313
  change_translated_headers=change_translated_headers,
314
+ center_wavelength=center_wavelength,
315
+ slit_width=slit_width,
302
316
  )
303
317
 
304
318
  return num_dark, num_lamp, num_solar, num_polcal, num_obs
@@ -1200,6 +1214,8 @@ def test_parse_cryonirsp_linearized_data_constants(
1200
1214
  num_scan_steps = 3
1201
1215
  num_map_scans = 2
1202
1216
  num_sub_repeats = 2
1217
+ center_wavelength = 1234.0
1218
+ slit_width = 6.28
1203
1219
 
1204
1220
  make_linearized_test_frames(
1205
1221
  task,
@@ -1213,6 +1229,8 @@ def test_parse_cryonirsp_linearized_data_constants(
1213
1229
  solar_exposure_condition=solar_exp_cond,
1214
1230
  polcal_exposure_condition=polcal_exp_cond,
1215
1231
  observe_exposure_condition=obs_exp_cond,
1232
+ center_wavelength=center_wavelength,
1233
+ slit_width=slit_width,
1216
1234
  )
1217
1235
 
1218
1236
  task()
@@ -1248,6 +1266,14 @@ def test_parse_cryonirsp_linearized_data_constants(
1248
1266
  assert task.constants._db_dict["MINIMUM_CADENCE"] == 10
1249
1267
  assert task.constants._db_dict["VARIANCE_CADENCE"] == 0
1250
1268
  assert task.constants._db_dict[BudName.retarder_name] == "Cool retarder"
1269
+ if arm_id == "SP":
1270
+ assert (
1271
+ task.constants._db_dict[CryonirspBudName.center_wavelength.value] == center_wavelength
1272
+ )
1273
+ assert task.constants._db_dict[CryonirspBudName.slit_width.value] == slit_width
1274
+ assert (
1275
+ task.constants._db_dict[CryonirspBudName.grating_constant.value] == 770970.3576216539
1276
+ ) # From `SimpleModulatedHeaders`
1251
1277
 
1252
1278
 
1253
1279
  @pytest.mark.parametrize("arm_id", ["SP"])
@@ -2,19 +2,16 @@ from datetime import datetime
2
2
 
3
3
  import numpy as np
4
4
  import pytest
5
- from astropy import units as u
6
5
  from astropy.io import fits
7
6
  from dkist_header_validator import spec122_validator
8
7
  from dkist_processing_common._util.scratch import WorkflowFileSystem
9
- from dkist_processing_common.codecs.asdf import asdf_decoder
10
8
  from dkist_processing_common.codecs.fits import fits_array_encoder
11
9
  from dkist_processing_common.codecs.fits import fits_hdulist_encoder
10
+ from dkist_processing_common.codecs.json import json_decoder
12
11
  from dkist_processing_common.tests.conftest import FakeGQLClient
13
12
 
14
13
  from dkist_processing_cryonirsp.models.tags import CryonirspTag
15
- from dkist_processing_cryonirsp.tasks.sp_dispersion_axis_correction import (
16
- SPDispersionAxisCorrection,
17
- )
14
+ from dkist_processing_cryonirsp.tasks.sp_wavelength_calibration import SPWavelengthCalibration
18
15
  from dkist_processing_cryonirsp.tests.conftest import cryonirsp_testing_parameters_factory
19
16
  from dkist_processing_cryonirsp.tests.conftest import CryonirspConstantsDb
20
17
  from dkist_processing_cryonirsp.tests.conftest import generate_fits_frame
@@ -47,7 +44,7 @@ def sp_dispersion_axis_correction_task(
47
44
  SOLAR_GAIN_IP_START_TIME="2021-01-01T00:00:00",
48
45
  )
49
46
  init_cryonirsp_constants_db(recipe_run_id, constants_db)
50
- with SPDispersionAxisCorrection(
47
+ with SPWavelengthCalibration(
51
48
  recipe_run_id=recipe_run_id,
52
49
  workflow_name="sp_dispersion_axis_correction",
53
50
  workflow_version="VX.Y",
@@ -99,6 +96,8 @@ def sp_dispersion_axis_correction_task(
99
96
  )
100
97
  hdul = generate_fits_frame(header_generator=header_generator, shape=array_shape)
101
98
  header = hdul[0].header
99
+ # set the slit width to a realistic Cryo value
100
+ header["CNSLITW"] = 175
102
101
  task.write(
103
102
  data=hdul,
104
103
  tags=[
@@ -131,23 +130,7 @@ def test_sp_dispersion_axis_correction(sp_dispersion_axis_correction_task, mocke
131
130
  CryonirspTag.task_spectral_fit(),
132
131
  CryonirspTag.intermediate(),
133
132
  ]
134
- fit_result = next(task.read(tags=tags, decoder=asdf_decoder))
135
- del fit_result["asdf_library"]
136
- del fit_result["history"]
137
-
138
- expected_wavelength_vector = task.compute_expected_wavelength_vector(
139
- np.random.rand(100), original_header
140
- )
141
-
142
- (
143
- telluric_atlas_wave,
144
- telluric_atlas_trans,
145
- solar_atlas_wave_air,
146
- solar_atlas_trans_flipped,
147
- ) = task.load_and_resample_fts_atlas(expected_wavelength_vector)
148
-
149
- assert len(telluric_atlas_wave) == len(telluric_atlas_trans)
150
- assert len(solar_atlas_wave_air) == len(solar_atlas_trans_flipped)
133
+ fit_result = next(task.read(tags=tags, decoder=json_decoder))
151
134
 
152
135
  # make sure that the values have changed
153
136
  assert original_header["CRVAL1"] != fit_result["CRVAL1"]
@@ -7,8 +7,8 @@ from astropy.io import fits
7
7
  from astropy.time import Time
8
8
  from dkist_fits_specifications import __version__ as spec_version
9
9
  from dkist_header_validator import spec214_validator
10
- from dkist_processing_common.codecs.asdf import asdf_encoder
11
10
  from dkist_processing_common.codecs.fits import fits_hdulist_encoder
11
+ from dkist_processing_common.codecs.json import json_encoder
12
12
  from dkist_processing_common.tests.conftest import FakeGQLClient
13
13
 
14
14
  from dkist_processing_cryonirsp.models.tags import CryonirspTag
@@ -100,7 +100,7 @@ def write_l1_task(
100
100
  hdul[0].header["CNSPINMD"] = "None"
101
101
 
102
102
  if arm_id == "SP":
103
- write_dummy_sp_dispersion_intermediate(task, hdul[0].header)
103
+ write_dummy_sp_dispersion_intermediate(task)
104
104
 
105
105
  for map_scan in range(1, num_map_scans + 1):
106
106
  for scan_step in range(1, num_scan_steps + 1):
@@ -127,24 +127,24 @@ def write_l1_task(
127
127
  task._purge()
128
128
 
129
129
 
130
- def write_dummy_sp_dispersion_intermediate(task: SPWriteL1Frame, header: fits.Header) -> None:
131
- overwrite_keys = [
132
- "CRVAL1",
133
- "CDELT1",
134
- "CRVAL1A",
135
- "CDELT1A",
136
- ]
130
+ def write_dummy_sp_dispersion_intermediate(task: SPWriteL1Frame) -> None:
131
+ dummy_fit_solution = {
132
+ "CTYPE1": "AWAV-GRA",
133
+ "CUNIT1": "nm",
134
+ "CRPIX1": 5, # This needs to be 5 for `axis_flip_tests`
135
+ "CRVAL1": 9999.0,
136
+ "CDELT1": 4.56,
137
+ "PV1_0": 78.9,
138
+ "PV1_1": 51,
139
+ "PV1_2": 11121,
140
+ }
137
141
 
138
- # Guaranteed to be different than the OG header values
139
- dummy_fit_solution = {k: header[k] * (np.random.random() + 1.1) for k in overwrite_keys}
140
- dummy_fit_solution["PV1_0"] = np.random.random()
141
- dummy_fit_solution["PV1_1"] = np.random.randint(4)
142
- dummy_fit_solution["PV1_2"] = np.random.random()
142
+ dummy_fit_solution = dummy_fit_solution | {f"{k}A": v for k, v in dummy_fit_solution.items()}
143
143
 
144
144
  task.write(
145
145
  data=dummy_fit_solution,
146
146
  tags=[CryonirspTag.intermediate(), CryonirspTag.task_spectral_fit()],
147
- encoder=asdf_encoder,
147
+ encoder=json_encoder,
148
148
  )
149
149
 
150
150
 
@@ -18,13 +18,13 @@ from dkist_processing_cryonirsp.tasks import LinearityCorrection
18
18
  from dkist_processing_cryonirsp.tasks import MakeCryonirspMovieFrames
19
19
  from dkist_processing_cryonirsp.tasks import ParseL0CryonirspRampData
20
20
  from dkist_processing_cryonirsp.tasks import SPBeamBoundariesCalibration
21
- from dkist_processing_cryonirsp.tasks import SPDispersionAxisCorrection
22
21
  from dkist_processing_cryonirsp.tasks import SPGeometricCalibration
23
22
  from dkist_processing_cryonirsp.tasks import (
24
23
  SPInstrumentPolarizationCalibration,
25
24
  )
26
25
  from dkist_processing_cryonirsp.tasks import SPScienceCalibration
27
26
  from dkist_processing_cryonirsp.tasks import SPSolarGainCalibration
27
+ from dkist_processing_cryonirsp.tasks import SPWavelengthCalibration
28
28
  from dkist_processing_cryonirsp.tasks import SPWriteL1Frame
29
29
  from dkist_processing_cryonirsp.tasks.l1_output_data import SPAssembleQualityData
30
30
  from dkist_processing_cryonirsp.tasks.parse import ParseL0CryonirspSPLinearizedData
@@ -52,11 +52,11 @@ l0_pipeline.add_node(task=DarkCalibration, upstreams=SPBeamBoundariesCalibration
52
52
  l0_pipeline.add_node(task=LampGainCalibration, upstreams=DarkCalibration)
53
53
  l0_pipeline.add_node(task=SPGeometricCalibration, upstreams=LampGainCalibration)
54
54
  l0_pipeline.add_node(task=SPSolarGainCalibration, upstreams=SPGeometricCalibration)
55
- l0_pipeline.add_node(task=SPDispersionAxisCorrection, upstreams=SPSolarGainCalibration)
55
+ l0_pipeline.add_node(task=SPWavelengthCalibration, upstreams=SPSolarGainCalibration)
56
56
  l0_pipeline.add_node(task=SPInstrumentPolarizationCalibration, upstreams=SPSolarGainCalibration)
57
57
  l0_pipeline.add_node(
58
58
  task=SPScienceCalibration,
59
- upstreams=[SPInstrumentPolarizationCalibration, SPDispersionAxisCorrection],
59
+ upstreams=[SPInstrumentPolarizationCalibration, SPWavelengthCalibration],
60
60
  )
61
61
  l0_pipeline.add_node(task=SPWriteL1Frame, upstreams=SPScienceCalibration)
62
62
 
@@ -26,13 +26,13 @@ from dkist_processing_cryonirsp.tasks import LinearityCorrection
26
26
  from dkist_processing_cryonirsp.tasks import MakeCryonirspMovieFrames
27
27
  from dkist_processing_cryonirsp.tasks import ParseL0CryonirspRampData
28
28
  from dkist_processing_cryonirsp.tasks import SPBeamBoundariesCalibration
29
- from dkist_processing_cryonirsp.tasks import SPDispersionAxisCorrection
30
29
  from dkist_processing_cryonirsp.tasks import SPGeometricCalibration
31
30
  from dkist_processing_cryonirsp.tasks import (
32
31
  SPInstrumentPolarizationCalibration,
33
32
  )
34
33
  from dkist_processing_cryonirsp.tasks import SPScienceCalibration
35
34
  from dkist_processing_cryonirsp.tasks import SPSolarGainCalibration
35
+ from dkist_processing_cryonirsp.tasks import SPWavelengthCalibration
36
36
  from dkist_processing_cryonirsp.tasks import SPWriteL1Frame
37
37
  from dkist_processing_cryonirsp.tasks.l1_output_data import CIAssembleQualityData
38
38
  from dkist_processing_cryonirsp.tasks.l1_output_data import SPAssembleQualityData
@@ -139,14 +139,14 @@ full_trial_sp_pipeline.add_node(task=DarkCalibration, upstreams=SPBeamBoundaries
139
139
  full_trial_sp_pipeline.add_node(task=LampGainCalibration, upstreams=DarkCalibration)
140
140
  full_trial_sp_pipeline.add_node(task=SPGeometricCalibration, upstreams=LampGainCalibration)
141
141
  full_trial_sp_pipeline.add_node(task=SPSolarGainCalibration, upstreams=SPGeometricCalibration)
142
- full_trial_sp_pipeline.add_node(task=SPDispersionAxisCorrection, upstreams=SPSolarGainCalibration)
142
+ full_trial_sp_pipeline.add_node(task=SPWavelengthCalibration, upstreams=SPSolarGainCalibration)
143
143
 
144
144
  full_trial_sp_pipeline.add_node(
145
145
  task=SPInstrumentPolarizationCalibration, upstreams=SPSolarGainCalibration
146
146
  )
147
147
  full_trial_sp_pipeline.add_node(
148
148
  task=SPScienceCalibration,
149
- upstreams=[SPInstrumentPolarizationCalibration, SPDispersionAxisCorrection],
149
+ upstreams=[SPInstrumentPolarizationCalibration, SPWavelengthCalibration],
150
150
  )
151
151
  full_trial_sp_pipeline.add_node(task=SPWriteL1Frame, upstreams=SPScienceCalibration)
152
152
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-cryonirsp
3
- Version: 1.9.0
3
+ Version: 1.10.0
4
4
  Summary: Science processing code for the Cryo-NIRSP instrument on DKIST
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause
@@ -30,6 +30,7 @@ Requires-Dist: peakutils==1.3.5
30
30
  Requires-Dist: scikit-image==0.25.2
31
31
  Requires-Dist: scipy==1.15.3
32
32
  Requires-Dist: sunpy==6.1.1
33
+ Requires-Dist: solar-wavelength-calibration==1.0
33
34
  Provides-Extra: test
34
35
  Requires-Dist: pytest; extra == "test"
35
36
  Requires-Dist: pytest-cov; extra == "test"
@@ -114,7 +115,7 @@ Requires-Dist: asdf_transform_schemas==0.6.0; extra == "frozen"
114
115
  Requires-Dist: asgiref==3.9.1; extra == "frozen"
115
116
  Requires-Dist: asteval==1.0.6; extra == "frozen"
116
117
  Requires-Dist: astropy==7.0.2; extra == "frozen"
117
- Requires-Dist: astropy-iers-data==0.2025.7.7.0.39.39; extra == "frozen"
118
+ Requires-Dist: astropy-iers-data==0.2025.7.14.0.40.29; extra == "frozen"
118
119
  Requires-Dist: asyncpg==0.30.0; extra == "frozen"
119
120
  Requires-Dist: attrs==25.3.0; extra == "frozen"
120
121
  Requires-Dist: babel==2.17.0; extra == "frozen"
@@ -124,7 +125,7 @@ Requires-Dist: boto3==1.39.4; extra == "frozen"
124
125
  Requires-Dist: botocore==1.39.4; extra == "frozen"
125
126
  Requires-Dist: cachelib==0.13.0; extra == "frozen"
126
127
  Requires-Dist: celery==5.5.3; extra == "frozen"
127
- Requires-Dist: certifi==2025.7.9; extra == "frozen"
128
+ Requires-Dist: certifi==2025.7.14; extra == "frozen"
128
129
  Requires-Dist: cffi==1.17.1; extra == "frozen"
129
130
  Requires-Dist: charset-normalizer==3.4.2; extra == "frozen"
130
131
  Requires-Dist: click==8.2.1; extra == "frozen"
@@ -146,7 +147,7 @@ Requires-Dist: dill==0.4.0; extra == "frozen"
146
147
  Requires-Dist: dkist-header-validator==5.2.1; extra == "frozen"
147
148
  Requires-Dist: dkist-processing-common==11.0.1; extra == "frozen"
148
149
  Requires-Dist: dkist-processing-core==5.1.1; extra == "frozen"
149
- Requires-Dist: dkist-processing-cryonirsp==1.9.0; extra == "frozen"
150
+ Requires-Dist: dkist-processing-cryonirsp==1.10.0; extra == "frozen"
150
151
  Requires-Dist: dkist-processing-math==2.2.0; extra == "frozen"
151
152
  Requires-Dist: dkist-processing-pac==3.1.1; extra == "frozen"
152
153
  Requires-Dist: dkist-service-configuration==2.2; extra == "frozen"
@@ -208,14 +209,14 @@ Requires-Dist: networkx==3.5; extra == "frozen"
208
209
  Requires-Dist: numba==0.61.2; extra == "frozen"
209
210
  Requires-Dist: numpy==2.2.5; extra == "frozen"
210
211
  Requires-Dist: object-clerk==0.1.2; extra == "frozen"
211
- Requires-Dist: opentelemetry-api==1.34.1; extra == "frozen"
212
- Requires-Dist: opentelemetry-exporter-otlp==1.34.1; extra == "frozen"
213
- Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.34.1; extra == "frozen"
214
- Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.34.1; extra == "frozen"
215
- Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.34.1; extra == "frozen"
216
- Requires-Dist: opentelemetry-proto==1.34.1; extra == "frozen"
217
- Requires-Dist: opentelemetry-sdk==1.34.1; extra == "frozen"
218
- Requires-Dist: opentelemetry-semantic-conventions==0.55b1; extra == "frozen"
212
+ Requires-Dist: opentelemetry-api==1.35.0; extra == "frozen"
213
+ Requires-Dist: opentelemetry-exporter-otlp==1.35.0; extra == "frozen"
214
+ Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.35.0; extra == "frozen"
215
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.35.0; extra == "frozen"
216
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.35.0; extra == "frozen"
217
+ Requires-Dist: opentelemetry-proto==1.35.0; extra == "frozen"
218
+ Requires-Dist: opentelemetry-sdk==1.35.0; extra == "frozen"
219
+ Requires-Dist: opentelemetry-semantic-conventions==0.56b0; extra == "frozen"
219
220
  Requires-Dist: ordered-set==4.1.0; extra == "frozen"
220
221
  Requires-Dist: packaging==25.0; extra == "frozen"
221
222
  Requires-Dist: pandas==2.3.1; extra == "frozen"
@@ -233,7 +234,7 @@ Requires-Dist: proglog==0.1.12; extra == "frozen"
233
234
  Requires-Dist: prometheus_client==0.22.1; extra == "frozen"
234
235
  Requires-Dist: prompt_toolkit==3.0.51; extra == "frozen"
235
236
  Requires-Dist: propcache==0.3.2; extra == "frozen"
236
- Requires-Dist: protobuf==5.29.5; extra == "frozen"
237
+ Requires-Dist: protobuf==6.31.1; extra == "frozen"
237
238
  Requires-Dist: psutil==7.0.0; extra == "frozen"
238
239
  Requires-Dist: psycopg2-binary==2.9.10; extra == "frozen"
239
240
  Requires-Dist: py==1.11.0; extra == "frozen"