dkist-processing-visp 5.1.2rc2__py3-none-any.whl → 5.2.0rc1__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.
- changelog/234.bugfix.rst +2 -0
- changelog/234.doc.rst +1 -0
- changelog/234.feature.rst +1 -0
- changelog/234.science.rst +2 -0
- changelog/253.misc.rst +1 -0
- dkist_processing_visp/models/parameters.py +43 -1
- dkist_processing_visp/models/tags.py +11 -0
- dkist_processing_visp/models/task_name.py +2 -0
- dkist_processing_visp/tasks/geometric.py +1 -1
- dkist_processing_visp/tasks/science.py +88 -11
- dkist_processing_visp/tasks/solar.py +12 -205
- dkist_processing_visp/tasks/wavelength_calibration.py +430 -0
- dkist_processing_visp/tasks/write_l1.py +2 -0
- dkist_processing_visp/tests/conftest.py +11 -0
- dkist_processing_visp/tests/header_models.py +22 -6
- dkist_processing_visp/tests/local_trial_workflows/l0_cals_only.py +21 -0
- dkist_processing_visp/tests/local_trial_workflows/l0_polcals_as_science.py +21 -0
- dkist_processing_visp/tests/local_trial_workflows/l0_solar_gain_as_science.py +20 -0
- dkist_processing_visp/tests/local_trial_workflows/l0_to_l1.py +21 -0
- dkist_processing_visp/tests/local_trial_workflows/local_trial_helpers.py +27 -0
- dkist_processing_visp/tests/test_parameters.py +11 -5
- dkist_processing_visp/tests/test_science.py +60 -5
- dkist_processing_visp/tests/test_solar.py +0 -1
- dkist_processing_visp/tests/test_wavelength_calibration.py +297 -0
- dkist_processing_visp/tests/test_write_l1.py +0 -2
- dkist_processing_visp/workflows/l0_processing.py +4 -1
- dkist_processing_visp/workflows/trial_workflows.py +4 -1
- {dkist_processing_visp-5.1.2rc2.dist-info → dkist_processing_visp-5.2.0rc1.dist-info}/METADATA +33 -33
- {dkist_processing_visp-5.1.2rc2.dist-info → dkist_processing_visp-5.2.0rc1.dist-info}/RECORD +34 -27
- docs/gain_correction.rst +3 -0
- docs/index.rst +1 -0
- docs/wavelength_calibration.rst +64 -0
- changelog/251.feature.rst +0 -1
- {dkist_processing_visp-5.1.2rc2.dist-info → dkist_processing_visp-5.2.0rc1.dist-info}/WHEEL +0 -0
- {dkist_processing_visp-5.1.2rc2.dist-info → dkist_processing_visp-5.2.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -28,6 +28,7 @@ from dkist_processing_visp.tasks.geometric import GeometricCalibration
|
|
|
28
28
|
from dkist_processing_visp.tasks.instrument_polarization import InstrumentPolarizationCalibration
|
|
29
29
|
from dkist_processing_visp.tasks.lamp import LampCalibration
|
|
30
30
|
from dkist_processing_visp.tasks.solar import SolarCalibration
|
|
31
|
+
from dkist_processing_visp.tasks.wavelength_calibration import WavelengthCalibration
|
|
31
32
|
from dkist_processing_visp.tests.conftest import VispInputDatasetParameterValues
|
|
32
33
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadBackgroundCal
|
|
33
34
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadCalibratedData
|
|
@@ -37,6 +38,9 @@ from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers impor
|
|
|
37
38
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadInstPolCal
|
|
38
39
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadLampCal
|
|
39
40
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadSolarCal
|
|
41
|
+
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
42
|
+
LoadWavelengthCalibration,
|
|
43
|
+
)
|
|
40
44
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
41
45
|
ParseCalOnlyL0InputData,
|
|
42
46
|
)
|
|
@@ -51,6 +55,9 @@ from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers impor
|
|
|
51
55
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
52
56
|
SaveSolarGainAsScience,
|
|
53
57
|
)
|
|
58
|
+
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
59
|
+
SaveWavelengthCalibration,
|
|
60
|
+
)
|
|
54
61
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SetAxesTypes
|
|
55
62
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
56
63
|
SetCadenceConstants,
|
|
@@ -158,6 +165,7 @@ def main(
|
|
|
158
165
|
load_lamp: bool = False,
|
|
159
166
|
load_geometric: bool = False,
|
|
160
167
|
load_solar: bool = False,
|
|
168
|
+
load_wavelength_calibration: bool = False,
|
|
161
169
|
load_inst_pol: bool = False,
|
|
162
170
|
load_solar_gain_as_science: bool = False,
|
|
163
171
|
load_calibrated_data: bool = False,
|
|
@@ -223,6 +231,11 @@ def main(
|
|
|
223
231
|
else:
|
|
224
232
|
manual_processing_run.run_task(task=SolarCalibration)
|
|
225
233
|
manual_processing_run.run_task(task=SaveSolarCal)
|
|
234
|
+
if load_wavelength_calibration:
|
|
235
|
+
manual_processing_run.run_task(task=LoadWavelengthCalibration)
|
|
236
|
+
else:
|
|
237
|
+
manual_processing_run.run_task(task=WavelengthCalibration)
|
|
238
|
+
manual_processing_run.run_task(task=SaveWavelengthCalibration)
|
|
226
239
|
|
|
227
240
|
if load_inst_pol:
|
|
228
241
|
manual_processing_run.run_task(task=LoadInstPolCal)
|
|
@@ -349,6 +362,12 @@ if __name__ == "__main__":
|
|
|
349
362
|
help="Load solar calibration from previously saved run",
|
|
350
363
|
action="store_true",
|
|
351
364
|
)
|
|
365
|
+
parser.add_argument(
|
|
366
|
+
"-W",
|
|
367
|
+
"--load-wavelength-calibration",
|
|
368
|
+
help="Load wavelength calibration solution from previously saved run",
|
|
369
|
+
action="store_true",
|
|
370
|
+
)
|
|
352
371
|
parser.add_argument(
|
|
353
372
|
"-P",
|
|
354
373
|
"--load-inst-pol",
|
|
@@ -378,6 +397,7 @@ if __name__ == "__main__":
|
|
|
378
397
|
load_lamp=args.load_lamp,
|
|
379
398
|
load_geometric=args.load_geometric,
|
|
380
399
|
load_solar=args.load_solar,
|
|
400
|
+
load_wavelength_calibration=args.load_wavelength_calibration,
|
|
381
401
|
load_inst_pol=args.load_inst_pol,
|
|
382
402
|
load_solar_gain_as_science=args.load_solar_gain_as_science,
|
|
383
403
|
load_calibrated_data=args.load_calibrated_data,
|
|
@@ -32,6 +32,7 @@ from dkist_processing_visp.tasks.quality_metrics import VispL1QualityMetrics
|
|
|
32
32
|
from dkist_processing_visp.tasks.science import ScienceCalibration
|
|
33
33
|
from dkist_processing_visp.tasks.solar import SolarCalibration
|
|
34
34
|
from dkist_processing_visp.tasks.visp_base import VispTaskBase
|
|
35
|
+
from dkist_processing_visp.tasks.wavelength_calibration import WavelengthCalibration
|
|
35
36
|
from dkist_processing_visp.tasks.write_l1 import VispWriteL1Frame
|
|
36
37
|
from dkist_processing_visp.tests.conftest import VispInputDatasetParameterValues
|
|
37
38
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadBackgroundCal
|
|
@@ -41,6 +42,9 @@ from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers impor
|
|
|
41
42
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadInstPolCal
|
|
42
43
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadLampCal
|
|
43
44
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import LoadSolarCal
|
|
45
|
+
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
46
|
+
LoadWavelengthCalibration,
|
|
47
|
+
)
|
|
44
48
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveBackgroundCal
|
|
45
49
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveDarkCal
|
|
46
50
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveGeometricCal
|
|
@@ -48,6 +52,9 @@ from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers impor
|
|
|
48
52
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveInstPolCal
|
|
49
53
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveLampCal
|
|
50
54
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveSolarCal
|
|
55
|
+
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
56
|
+
SaveWavelengthCalibration,
|
|
57
|
+
)
|
|
51
58
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import tag_inputs_task
|
|
52
59
|
from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
|
|
53
60
|
transfer_trial_data_locally_task,
|
|
@@ -178,6 +185,7 @@ def main(
|
|
|
178
185
|
load_lamp: bool = False,
|
|
179
186
|
load_geometric: bool = False,
|
|
180
187
|
load_solar: bool = False,
|
|
188
|
+
load_wavelength_calibration: bool = False,
|
|
181
189
|
load_inst_pol: bool = False,
|
|
182
190
|
transfer_trial_data: str | None = None,
|
|
183
191
|
):
|
|
@@ -236,6 +244,12 @@ def main(
|
|
|
236
244
|
manual_processing_run.run_task(task=SolarCalibration)
|
|
237
245
|
manual_processing_run.run_task(task=SaveSolarCal)
|
|
238
246
|
|
|
247
|
+
if load_wavelength_calibration:
|
|
248
|
+
manual_processing_run.run_task(task=LoadWavelengthCalibration)
|
|
249
|
+
else:
|
|
250
|
+
manual_processing_run.run_task(task=WavelengthCalibration)
|
|
251
|
+
manual_processing_run.run_task(task=SaveWavelengthCalibration)
|
|
252
|
+
|
|
239
253
|
if load_inst_pol:
|
|
240
254
|
manual_processing_run.run_task(task=LoadInstPolCal)
|
|
241
255
|
else:
|
|
@@ -345,6 +359,12 @@ if __name__ == "__main__":
|
|
|
345
359
|
help="Load solar calibration from previously saved run",
|
|
346
360
|
action="store_true",
|
|
347
361
|
)
|
|
362
|
+
parser.add_argument(
|
|
363
|
+
"-W",
|
|
364
|
+
"--load-wavelength-calibration",
|
|
365
|
+
help="Load wavelength calibration solution from previously saved run",
|
|
366
|
+
action="store_true",
|
|
367
|
+
)
|
|
348
368
|
parser.add_argument(
|
|
349
369
|
"-P",
|
|
350
370
|
"--load-inst-pol",
|
|
@@ -365,6 +385,7 @@ if __name__ == "__main__":
|
|
|
365
385
|
load_lamp=args.load_lamp,
|
|
366
386
|
load_geometric=args.load_geometric,
|
|
367
387
|
load_solar=args.load_solar,
|
|
388
|
+
load_wavelength_calibration=args.load_wavelength_calibration,
|
|
368
389
|
load_inst_pol=args.load_inst_pol,
|
|
369
390
|
transfer_trial_data=args.transfer_trial_data,
|
|
370
391
|
)
|
|
@@ -11,6 +11,7 @@ from dkist_processing_common.codecs.fits import fits_array_decoder
|
|
|
11
11
|
from dkist_processing_common.codecs.fits import fits_hdulist_encoder
|
|
12
12
|
from dkist_processing_common.models.constants import BudName
|
|
13
13
|
from dkist_processing_common.models.fits_access import MetadataKey
|
|
14
|
+
from dkist_processing_common.models.metric_code import MetricCode
|
|
14
15
|
from dkist_processing_common.models.task_name import TaskName
|
|
15
16
|
from dkist_processing_common.parsers.cs_step import CSStepFlower
|
|
16
17
|
from dkist_processing_common.parsers.cs_step import NumCSStepBud
|
|
@@ -270,6 +271,7 @@ class SaveSolarCal(SaveTaskTags):
|
|
|
270
271
|
@property
|
|
271
272
|
def tag_lists_to_save(self) -> list[list[str]]:
|
|
272
273
|
return super().tag_lists_to_save + [
|
|
274
|
+
[VispTag.intermediate_frame(beam=1), VispTag.task_characteristic_spectra()],
|
|
273
275
|
[VispTag.quality("TASK_TYPES"), VispTag.workflow_task("SolarCalibration")],
|
|
274
276
|
[VispTag.quality(VispMetricCode.solar_first_vignette)],
|
|
275
277
|
[VispTag.quality(VispMetricCode.solar_final_vignette)],
|
|
@@ -280,6 +282,31 @@ class SaveSolarCal(SaveTaskTags):
|
|
|
280
282
|
return "solar_cal.asdf"
|
|
281
283
|
|
|
282
284
|
|
|
285
|
+
class SaveWavelengthCalibration(SaveTaskTags):
|
|
286
|
+
@property
|
|
287
|
+
def task_str(self) -> str:
|
|
288
|
+
return VispTaskName.wavelength_calibration.value
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def relative_save_file(self) -> str:
|
|
292
|
+
return "wavelength_calibration.asdf"
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def tag_lists_to_save(self) -> list[list[str]]:
|
|
296
|
+
return super().tag_lists_to_save + [
|
|
297
|
+
[
|
|
298
|
+
VispTag.quality(MetricCode.wavecal_fit),
|
|
299
|
+
VispTag.workflow_task("WavelengthCalibration"),
|
|
300
|
+
],
|
|
301
|
+
]
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class LoadWavelengthCalibration(LoadTaskTags):
|
|
305
|
+
@property
|
|
306
|
+
def relative_save_file(self) -> str:
|
|
307
|
+
return "wavelength_calibration.asdf"
|
|
308
|
+
|
|
309
|
+
|
|
283
310
|
class LoadSolarCal(LoadTaskTags):
|
|
284
311
|
@property
|
|
285
312
|
def relative_save_file(self) -> str:
|
|
@@ -37,6 +37,8 @@ def unit_parameter_names_and_units() -> dict[str, u.Unit | list[u.Unit]]:
|
|
|
37
37
|
"solar_vignette_crval_bounds_px": u.pix,
|
|
38
38
|
"wavecal_camera_lens_parameters": [u.m, u.m / u.nm, u.m / u.nm**2],
|
|
39
39
|
"wavecal_pixel_pitch_micron_per_pix": u.um / u.pix,
|
|
40
|
+
"wavecal_crval_bounds_px": u.pix,
|
|
41
|
+
"wavecal_incident_light_angle_bounds_deg": u.deg,
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
|
|
@@ -106,7 +108,7 @@ def test_non_wave_parameters(
|
|
|
106
108
|
if (
|
|
107
109
|
parameter_name not in parse_parameter_names
|
|
108
110
|
and not is_wavelength_param
|
|
109
|
-
and parameter_name
|
|
111
|
+
and parameter_name not in ["solar_vignette_wavecal_fit_kwargs", "wavecal_fit_kwargs"]
|
|
110
112
|
):
|
|
111
113
|
param_obj_value = getattr(task_param_attr, parameter_name)
|
|
112
114
|
if isinstance(pv, tuple):
|
|
@@ -197,22 +199,26 @@ class AnyInt:
|
|
|
197
199
|
pytest.param(dict(), dict(), id="no_kwargs"),
|
|
198
200
|
],
|
|
199
201
|
)
|
|
202
|
+
@pytest.mark.parametrize(
|
|
203
|
+
"fit_kwarg_name", ["visp_solar_vignette_wavecal_fit_kwargs", "visp_wavecal_fit_kwargs"]
|
|
204
|
+
)
|
|
200
205
|
def test_fit_kwarg_parameters(
|
|
201
206
|
basic_science_task_with_parameter_mixin,
|
|
202
207
|
db_value,
|
|
203
208
|
expected,
|
|
209
|
+
fit_kwarg_name,
|
|
204
210
|
):
|
|
205
211
|
"""
|
|
206
212
|
Given: A Science task with the parameter mixin
|
|
207
213
|
When: Accessing properties for parameters that do not depend on wavelength
|
|
208
214
|
Then: The correct value is returned
|
|
209
215
|
"""
|
|
216
|
+
kwargs = {fit_kwarg_name: db_value}
|
|
217
|
+
|
|
210
218
|
task, _ = next(
|
|
211
|
-
basic_science_task_with_parameter_mixin(
|
|
212
|
-
VispInputDatasetParameterValues(visp_solar_vignette_wavecal_fit_kwargs=db_value)
|
|
213
|
-
)
|
|
219
|
+
basic_science_task_with_parameter_mixin(VispInputDatasetParameterValues(**kwargs))
|
|
214
220
|
)
|
|
215
|
-
kwarg_dict = task.parameters.
|
|
221
|
+
kwarg_dict = getattr(task.parameters, fit_kwarg_name.removeprefix("visp_"))
|
|
216
222
|
assert kwarg_dict.keys() == expected.keys()
|
|
217
223
|
for k in expected.keys():
|
|
218
224
|
if expected[k] is AnyInt:
|
|
@@ -12,6 +12,7 @@ from dkist_header_validator import spec122_validator
|
|
|
12
12
|
from dkist_processing_common._util.scratch import WorkflowFileSystem
|
|
13
13
|
from dkist_processing_common.codecs.fits import fits_array_encoder
|
|
14
14
|
from dkist_processing_common.codecs.fits import fits_hdu_decoder
|
|
15
|
+
from dkist_processing_common.codecs.json import json_encoder
|
|
15
16
|
from dkist_processing_common.models.fits_access import MetadataKey
|
|
16
17
|
from dkist_processing_common.models.tags import Tag
|
|
17
18
|
|
|
@@ -65,6 +66,7 @@ def write_input_observe_frames_to_task(
|
|
|
65
66
|
num_maps: int,
|
|
66
67
|
data_shape: tuple[int, int],
|
|
67
68
|
polarimeter_mode: Literal["observe_polarimetric", "obser_intensity"] = "observe_polarimetric",
|
|
69
|
+
swap_wcs_axes: bool = False,
|
|
68
70
|
):
|
|
69
71
|
array_shape = (1, *data_shape)
|
|
70
72
|
dataset = VispHeadersValidObserveFrames(
|
|
@@ -74,6 +76,7 @@ def write_input_observe_frames_to_task(
|
|
|
74
76
|
num_raster_steps=num_raster_steps,
|
|
75
77
|
num_maps=num_maps,
|
|
76
78
|
polarimeter_mode=polarimeter_mode,
|
|
79
|
+
swap_wcs_axes=swap_wcs_axes,
|
|
77
80
|
)
|
|
78
81
|
write_frames_to_task(
|
|
79
82
|
task=task,
|
|
@@ -100,6 +103,7 @@ def science_calibration_task(
|
|
|
100
103
|
recipe_run_id,
|
|
101
104
|
init_visp_constants_db,
|
|
102
105
|
request,
|
|
106
|
+
swap_wcs_axes,
|
|
103
107
|
):
|
|
104
108
|
num_map_scans = 2
|
|
105
109
|
num_raster_steps = 2
|
|
@@ -117,6 +121,8 @@ def science_calibration_task(
|
|
|
117
121
|
NUM_RASTER_STEPS=num_raster_steps,
|
|
118
122
|
NUM_BEAMS=2,
|
|
119
123
|
OBSERVE_READOUT_EXP_TIMES=(readout_exp_time,),
|
|
124
|
+
AXIS_1_TYPE="AWAV" if swap_wcs_axes else "HPLT-TAN",
|
|
125
|
+
AXIS_2_TYPE="HPLT-TAN" if swap_wcs_axes else "AWAV",
|
|
120
126
|
)
|
|
121
127
|
init_visp_constants_db(recipe_run_id, constants_db)
|
|
122
128
|
with ScienceCalibration(
|
|
@@ -134,6 +140,23 @@ def science_calibration_task(
|
|
|
134
140
|
task._purge()
|
|
135
141
|
|
|
136
142
|
|
|
143
|
+
@pytest.fixture
|
|
144
|
+
def dummy_wavelength_solution(swap_wcs_axes):
|
|
145
|
+
axis_num = 1 if swap_wcs_axes else 2
|
|
146
|
+
dummy_fit_solution = {
|
|
147
|
+
f"CTYPE{axis_num}": "AWAV-GRA",
|
|
148
|
+
f"CUNIT{axis_num}": "nm",
|
|
149
|
+
f"CRPIX{axis_num}": 5,
|
|
150
|
+
f"CRVAL{axis_num}": 9999.0,
|
|
151
|
+
f"CDELT{axis_num}": 4.56,
|
|
152
|
+
f"PV{axis_num}_0": 78.9,
|
|
153
|
+
f"PV{axis_num}_1": 51,
|
|
154
|
+
f"PV{axis_num}_2": 11121,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return dummy_fit_solution | {f"{k}A": v for k, v in dummy_fit_solution.items()}
|
|
158
|
+
|
|
159
|
+
|
|
137
160
|
@pytest.fixture(scope="function")
|
|
138
161
|
def dummy_calibration_collection():
|
|
139
162
|
input_shape = (50, 20)
|
|
@@ -148,6 +171,7 @@ def dummy_calibration_collection():
|
|
|
148
171
|
angle_dict = {VispTag.beam(beam): 0.0}
|
|
149
172
|
spec_dict = {VispTag.beam(beam): np.zeros(intermediate_shape[1])}
|
|
150
173
|
offset_dict = {VispTag.beam(beam): {VispTag.modstate(modstate): np.zeros(2)}}
|
|
174
|
+
wavecal_dict = dict()
|
|
151
175
|
|
|
152
176
|
collection = CalibrationCollection(
|
|
153
177
|
dark=dark_dict,
|
|
@@ -156,6 +180,7 @@ def dummy_calibration_collection():
|
|
|
156
180
|
angle=angle_dict,
|
|
157
181
|
spec_shift=spec_dict,
|
|
158
182
|
state_offset=offset_dict,
|
|
183
|
+
wavelength_calibration_header=wavecal_dict,
|
|
159
184
|
demod_matrices=None,
|
|
160
185
|
)
|
|
161
186
|
|
|
@@ -209,6 +234,7 @@ def calibration_collection_with_geo_shifts(shifts) -> CalibrationCollection:
|
|
|
209
234
|
angle=dict(),
|
|
210
235
|
state_offset=geo_shifts,
|
|
211
236
|
spec_shift=dict(),
|
|
237
|
+
wavelength_calibration_header=dict(),
|
|
212
238
|
demod_matrices=None,
|
|
213
239
|
)
|
|
214
240
|
|
|
@@ -246,13 +272,18 @@ def calibration_collection_with_full_overlap_slice() -> CalibrationCollection:
|
|
|
246
272
|
angle=dict(),
|
|
247
273
|
state_offset=geo_shifts,
|
|
248
274
|
spec_shift=dict(),
|
|
275
|
+
wavelength_calibration_header=dict(),
|
|
249
276
|
demod_matrices=None,
|
|
250
277
|
)
|
|
251
278
|
|
|
252
279
|
|
|
253
280
|
@pytest.mark.parametrize(
|
|
254
|
-
"background_on",
|
|
255
|
-
[
|
|
281
|
+
"background_on, swap_wcs_axes",
|
|
282
|
+
[
|
|
283
|
+
pytest.param(True, False, id="background_on-no_swap"),
|
|
284
|
+
pytest.param(False, False, id="background_off-no_swap"),
|
|
285
|
+
pytest.param(False, True, id="background_off-axes_swap"),
|
|
286
|
+
],
|
|
256
287
|
)
|
|
257
288
|
def test_science_calibration_task(
|
|
258
289
|
science_calibration_task,
|
|
@@ -260,6 +291,8 @@ def test_science_calibration_task(
|
|
|
260
291
|
assign_input_dataset_doc_to_task,
|
|
261
292
|
mocker,
|
|
262
293
|
fake_gql_client,
|
|
294
|
+
dummy_wavelength_solution,
|
|
295
|
+
swap_wcs_axes,
|
|
263
296
|
):
|
|
264
297
|
"""
|
|
265
298
|
Given: A ScienceCalibration task
|
|
@@ -290,7 +323,7 @@ def test_science_calibration_task(
|
|
|
290
323
|
),
|
|
291
324
|
)
|
|
292
325
|
|
|
293
|
-
offsets = np.tile(np.array([-10.2, 5.1]), (2, num_modstates, 1))
|
|
326
|
+
offsets = np.tile(np.array([-10.2, -5.1]), (2, num_modstates, 1))
|
|
294
327
|
offsets[0] = 0.0 # So beam 1 has zero offset
|
|
295
328
|
|
|
296
329
|
write_intermediate_darks_to_task(
|
|
@@ -312,6 +345,11 @@ def test_science_calibration_task(
|
|
|
312
345
|
data_shape=intermediate_shape,
|
|
313
346
|
)
|
|
314
347
|
write_demod_matrices_to_task(task=task, num_modstates=num_modstates)
|
|
348
|
+
task.write(
|
|
349
|
+
data=dummy_wavelength_solution,
|
|
350
|
+
tags=[VispTag.intermediate(), VispTag.task_wavelength_calibration()],
|
|
351
|
+
encoder=json_encoder,
|
|
352
|
+
)
|
|
315
353
|
write_input_observe_frames_to_task(
|
|
316
354
|
task=task,
|
|
317
355
|
readout_exp_time=readout_exp_time,
|
|
@@ -319,6 +357,7 @@ def test_science_calibration_task(
|
|
|
319
357
|
num_raster_steps=num_raster_steps,
|
|
320
358
|
num_maps=num_maps,
|
|
321
359
|
data_shape=input_shape,
|
|
360
|
+
swap_wcs_axes=swap_wcs_axes,
|
|
322
361
|
)
|
|
323
362
|
|
|
324
363
|
input_header = get_input_obs_frame_header(task=task)
|
|
@@ -365,10 +404,22 @@ def test_science_calibration_task(
|
|
|
365
404
|
assert header["VSPMAP"] == map_scan
|
|
366
405
|
|
|
367
406
|
# Check that WCS keys were updated
|
|
407
|
+
spec_axis_num = 1 if swap_wcs_axes else 2
|
|
408
|
+
spatial_axis_num = 2 if swap_wcs_axes else 1
|
|
368
409
|
if offsets[1, 0, 0] < 0:
|
|
369
|
-
assert header["
|
|
410
|
+
assert header[f"CRPIX{spec_axis_num}"] == dummy_wavelength_solution[
|
|
411
|
+
f"CRPIX{spec_axis_num}"
|
|
412
|
+
] - np.ceil(-offsets[1, 0, 0])
|
|
413
|
+
assert header[f"CRPIX{spec_axis_num}A"] == dummy_wavelength_solution[
|
|
414
|
+
f"CRPIX{spec_axis_num}A"
|
|
415
|
+
] - np.ceil(-offsets[1, 0, 0])
|
|
370
416
|
if offsets[1, 0, 1] < 0:
|
|
371
|
-
assert header["
|
|
417
|
+
assert header[f"CRPIX{spatial_axis_num}"] == input_header[
|
|
418
|
+
f"CRPIX{spatial_axis_num}"
|
|
419
|
+
] - np.ceil(-offsets[1, 0, 1])
|
|
420
|
+
assert header[f"CRPIX{spatial_axis_num}A"] == input_header[
|
|
421
|
+
f"CRPIX{spatial_axis_num}A"
|
|
422
|
+
] - np.ceil(-offsets[1, 0, 1])
|
|
372
423
|
|
|
373
424
|
quality_files = task.read(tags=[Tag.quality("TASK_TYPES")])
|
|
374
425
|
for file in quality_files:
|
|
@@ -380,6 +431,7 @@ def test_science_calibration_task(
|
|
|
380
431
|
)
|
|
381
432
|
|
|
382
433
|
|
|
434
|
+
@pytest.mark.parametrize("swap_wcs_axes", [pytest.param(False, id="no_swap")])
|
|
383
435
|
def test_readout_normalization_correct(
|
|
384
436
|
science_calibration_task, dummy_calibration_collection, assign_input_dataset_doc_to_task
|
|
385
437
|
):
|
|
@@ -550,6 +602,7 @@ def test_beam_overlap_slice(calibration_collection_with_geo_shifts, expected):
|
|
|
550
602
|
assert y_slice == expected[1]
|
|
551
603
|
|
|
552
604
|
|
|
605
|
+
@pytest.mark.parametrize("swap_wcs_axes", [pytest.param(False, id="no_swap")])
|
|
553
606
|
def test_combine_beams(
|
|
554
607
|
science_calibration_task,
|
|
555
608
|
calibrated_array_and_header_dicts,
|
|
@@ -598,6 +651,7 @@ def test_combine_beams(
|
|
|
598
651
|
],
|
|
599
652
|
ids=["Positive and negative"],
|
|
600
653
|
)
|
|
654
|
+
@pytest.mark.parametrize("swap_wcs_axes", [pytest.param(False, id="no_swap")])
|
|
601
655
|
def test_combine_and_cut_nan_masks(
|
|
602
656
|
science_calibration_task, calibration_collection_with_geo_shifts, shifts
|
|
603
657
|
):
|
|
@@ -649,6 +703,7 @@ def test_combine_and_cut_nan_masks(
|
|
|
649
703
|
assert np.sum(combined_nan_mask) == 2 # only two NaN values are in the final mask
|
|
650
704
|
|
|
651
705
|
|
|
706
|
+
@pytest.mark.parametrize("swap_wcs_axes", [pytest.param(False, id="no_swap")])
|
|
652
707
|
def test_generate_nan_mask(science_calibration_task, dummy_calibration_collection):
|
|
653
708
|
"""
|
|
654
709
|
Given: a calibration collection
|
|
@@ -9,7 +9,6 @@ import pytest
|
|
|
9
9
|
from asdf.tags.core import NDArrayType
|
|
10
10
|
from astropy import constants
|
|
11
11
|
from astropy.coordinates import EarthLocation
|
|
12
|
-
from astropy.io import fits
|
|
13
12
|
from astropy.stats import gaussian_fwhm_to_sigma
|
|
14
13
|
from astropy.time import Time
|
|
15
14
|
from dkist_processing_common._util.scratch import WorkflowFileSystem
|