dkist-processing-cryonirsp 1.3.4__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.
- changelog/.gitempty +0 -0
- dkist_processing_cryonirsp/__init__.py +11 -0
- dkist_processing_cryonirsp/config.py +12 -0
- dkist_processing_cryonirsp/models/__init__.py +1 -0
- dkist_processing_cryonirsp/models/constants.py +248 -0
- dkist_processing_cryonirsp/models/exposure_conditions.py +26 -0
- dkist_processing_cryonirsp/models/parameters.py +296 -0
- dkist_processing_cryonirsp/models/tags.py +168 -0
- dkist_processing_cryonirsp/models/task_name.py +14 -0
- dkist_processing_cryonirsp/parsers/__init__.py +1 -0
- dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py +111 -0
- dkist_processing_cryonirsp/parsers/cryonirsp_l1_fits_access.py +30 -0
- dkist_processing_cryonirsp/parsers/exposure_conditions.py +163 -0
- dkist_processing_cryonirsp/parsers/map_repeats.py +40 -0
- dkist_processing_cryonirsp/parsers/measurements.py +55 -0
- dkist_processing_cryonirsp/parsers/modstates.py +31 -0
- dkist_processing_cryonirsp/parsers/optical_density_filters.py +40 -0
- dkist_processing_cryonirsp/parsers/polarimetric_check.py +120 -0
- dkist_processing_cryonirsp/parsers/scan_step.py +412 -0
- dkist_processing_cryonirsp/parsers/time.py +80 -0
- dkist_processing_cryonirsp/parsers/wavelength.py +26 -0
- dkist_processing_cryonirsp/tasks/__init__.py +19 -0
- dkist_processing_cryonirsp/tasks/assemble_movie.py +202 -0
- dkist_processing_cryonirsp/tasks/bad_pixel_map.py +96 -0
- dkist_processing_cryonirsp/tasks/beam_boundaries_base.py +279 -0
- dkist_processing_cryonirsp/tasks/ci_beam_boundaries.py +55 -0
- dkist_processing_cryonirsp/tasks/ci_science.py +169 -0
- dkist_processing_cryonirsp/tasks/cryonirsp_base.py +67 -0
- dkist_processing_cryonirsp/tasks/dark.py +98 -0
- dkist_processing_cryonirsp/tasks/gain.py +251 -0
- dkist_processing_cryonirsp/tasks/instrument_polarization.py +447 -0
- dkist_processing_cryonirsp/tasks/l1_output_data.py +44 -0
- dkist_processing_cryonirsp/tasks/linearity_correction.py +582 -0
- dkist_processing_cryonirsp/tasks/make_movie_frames.py +302 -0
- dkist_processing_cryonirsp/tasks/mixin/__init__.py +1 -0
- dkist_processing_cryonirsp/tasks/mixin/beam_access.py +52 -0
- dkist_processing_cryonirsp/tasks/mixin/corrections.py +177 -0
- dkist_processing_cryonirsp/tasks/mixin/intermediate_frame.py +193 -0
- dkist_processing_cryonirsp/tasks/mixin/linearized_frame.py +309 -0
- dkist_processing_cryonirsp/tasks/mixin/shift_measurements.py +297 -0
- dkist_processing_cryonirsp/tasks/parse.py +281 -0
- dkist_processing_cryonirsp/tasks/quality_metrics.py +271 -0
- dkist_processing_cryonirsp/tasks/science_base.py +511 -0
- dkist_processing_cryonirsp/tasks/sp_beam_boundaries.py +270 -0
- dkist_processing_cryonirsp/tasks/sp_dispersion_axis_correction.py +484 -0
- dkist_processing_cryonirsp/tasks/sp_geometric.py +585 -0
- dkist_processing_cryonirsp/tasks/sp_science.py +299 -0
- dkist_processing_cryonirsp/tasks/sp_solar_gain.py +475 -0
- dkist_processing_cryonirsp/tasks/trial_output_data.py +61 -0
- dkist_processing_cryonirsp/tasks/write_l1.py +1033 -0
- dkist_processing_cryonirsp/tests/__init__.py +1 -0
- dkist_processing_cryonirsp/tests/conftest.py +456 -0
- dkist_processing_cryonirsp/tests/header_models.py +592 -0
- dkist_processing_cryonirsp/tests/local_trial_workflows/__init__.py +0 -0
- dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py +541 -0
- dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py +615 -0
- dkist_processing_cryonirsp/tests/local_trial_workflows/linearize_only.py +96 -0
- dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py +592 -0
- dkist_processing_cryonirsp/tests/test_assemble_movie.py +144 -0
- dkist_processing_cryonirsp/tests/test_assemble_qualilty.py +517 -0
- dkist_processing_cryonirsp/tests/test_bad_pixel_maps.py +115 -0
- dkist_processing_cryonirsp/tests/test_ci_beam_boundaries.py +106 -0
- dkist_processing_cryonirsp/tests/test_ci_science.py +355 -0
- dkist_processing_cryonirsp/tests/test_corrections.py +126 -0
- dkist_processing_cryonirsp/tests/test_cryo_base.py +202 -0
- dkist_processing_cryonirsp/tests/test_cryo_constants.py +76 -0
- dkist_processing_cryonirsp/tests/test_dark.py +287 -0
- dkist_processing_cryonirsp/tests/test_gain.py +278 -0
- dkist_processing_cryonirsp/tests/test_instrument_polarization.py +531 -0
- dkist_processing_cryonirsp/tests/test_linearity_correction.py +245 -0
- dkist_processing_cryonirsp/tests/test_make_movie_frames.py +111 -0
- dkist_processing_cryonirsp/tests/test_parameters.py +266 -0
- dkist_processing_cryonirsp/tests/test_parse.py +1439 -0
- dkist_processing_cryonirsp/tests/test_quality.py +203 -0
- dkist_processing_cryonirsp/tests/test_sp_beam_boundaries.py +112 -0
- dkist_processing_cryonirsp/tests/test_sp_dispersion_axis_correction.py +155 -0
- dkist_processing_cryonirsp/tests/test_sp_geometric.py +319 -0
- dkist_processing_cryonirsp/tests/test_sp_make_movie_frames.py +121 -0
- dkist_processing_cryonirsp/tests/test_sp_science.py +483 -0
- dkist_processing_cryonirsp/tests/test_sp_solar.py +198 -0
- dkist_processing_cryonirsp/tests/test_trial_create_quality_report.py +79 -0
- dkist_processing_cryonirsp/tests/test_trial_output_data.py +251 -0
- dkist_processing_cryonirsp/tests/test_workflows.py +9 -0
- dkist_processing_cryonirsp/tests/test_write_l1.py +436 -0
- dkist_processing_cryonirsp/workflows/__init__.py +2 -0
- dkist_processing_cryonirsp/workflows/ci_l0_processing.py +77 -0
- dkist_processing_cryonirsp/workflows/sp_l0_processing.py +84 -0
- dkist_processing_cryonirsp/workflows/trial_workflows.py +190 -0
- dkist_processing_cryonirsp-1.3.4.dist-info/METADATA +194 -0
- dkist_processing_cryonirsp-1.3.4.dist-info/RECORD +111 -0
- dkist_processing_cryonirsp-1.3.4.dist-info/WHEEL +5 -0
- dkist_processing_cryonirsp-1.3.4.dist-info/top_level.txt +4 -0
- docs/Makefile +134 -0
- docs/bad_pixel_calibration.rst +47 -0
- docs/beam_angle_calculation.rst +53 -0
- docs/beam_boundary_computation.rst +88 -0
- docs/changelog.rst +7 -0
- docs/ci_science_calibration.rst +33 -0
- docs/conf.py +52 -0
- docs/index.rst +21 -0
- docs/l0_to_l1_cryonirsp_ci-full-trial.rst +10 -0
- docs/l0_to_l1_cryonirsp_ci.rst +10 -0
- docs/l0_to_l1_cryonirsp_sp-full-trial.rst +10 -0
- docs/l0_to_l1_cryonirsp_sp.rst +10 -0
- docs/linearization.rst +43 -0
- docs/make.bat +170 -0
- docs/requirements.txt +1 -0
- docs/requirements_table.rst +8 -0
- docs/scientific_changelog.rst +10 -0
- docs/sp_science_calibration.rst +59 -0
- licenses/LICENSE.rst +11 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from unittest.mock import ANY
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pytest
|
|
7
|
+
from astropy.io import fits
|
|
8
|
+
from dkist_header_validator import spec122_validator
|
|
9
|
+
from dkist_processing_common._util.scratch import WorkflowFileSystem
|
|
10
|
+
from dkist_processing_common.codecs.fits import fits_hdulist_encoder
|
|
11
|
+
from dkist_processing_common.models.task_name import TaskName
|
|
12
|
+
from dkist_processing_common.tests.conftest import FakeGQLClient
|
|
13
|
+
from dkist_processing_pac.fitter.polcal_fitter import PolcalFitter
|
|
14
|
+
from dkist_processing_pac.input_data.dresser import Dresser
|
|
15
|
+
|
|
16
|
+
from dkist_processing_cryonirsp.models.exposure_conditions import AllowableOpticalDensityFilterNames
|
|
17
|
+
from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
|
|
18
|
+
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
19
|
+
from dkist_processing_cryonirsp.tasks.instrument_polarization import (
|
|
20
|
+
CIInstrumentPolarizationCalibration,
|
|
21
|
+
)
|
|
22
|
+
from dkist_processing_cryonirsp.tasks.instrument_polarization import (
|
|
23
|
+
SPInstrumentPolarizationCalibration,
|
|
24
|
+
)
|
|
25
|
+
from dkist_processing_cryonirsp.tests.conftest import cryonirsp_testing_parameters_factory
|
|
26
|
+
from dkist_processing_cryonirsp.tests.conftest import CryonirspConstantsDb
|
|
27
|
+
from dkist_processing_cryonirsp.tests.conftest import generate_fits_frame
|
|
28
|
+
from dkist_processing_cryonirsp.tests.header_models import CryonirspHeadersValidPolcalFrames
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class DummyPolcalFitter(PolcalFitter):
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
*,
|
|
35
|
+
local_dresser: Dresser,
|
|
36
|
+
global_dresser: Dresser,
|
|
37
|
+
fit_mode: str,
|
|
38
|
+
init_set: str,
|
|
39
|
+
fit_TM: bool = False,
|
|
40
|
+
threads: int = 1,
|
|
41
|
+
super_name: str = "",
|
|
42
|
+
_dont_fit: bool = False,
|
|
43
|
+
**fit_kwargs,
|
|
44
|
+
):
|
|
45
|
+
with patch("dkist_processing_pac.fitter.polcal_fitter.FitObjects"):
|
|
46
|
+
super().__init__(
|
|
47
|
+
local_dresser=local_dresser,
|
|
48
|
+
global_dresser=global_dresser,
|
|
49
|
+
fit_mode="use_M12_I_sys_per_step",
|
|
50
|
+
init_set="OCCal_VIS",
|
|
51
|
+
_dont_fit=True,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
self.num_modstates = local_dresser.nummod
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def demodulation_matrices(self) -> np.ndarray:
|
|
58
|
+
return np.ones((1, 1, 4, self.num_modstates))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _create_polcal_dark_or_gain_array(
|
|
62
|
+
task, array_shape, num_mod, exposure_conditions, polcal_type, start_time
|
|
63
|
+
):
|
|
64
|
+
ds = CryonirspHeadersValidPolcalFrames(
|
|
65
|
+
# Using array_shape here for dataset_shape so only 1 frame is created:
|
|
66
|
+
dataset_shape=array_shape,
|
|
67
|
+
array_shape=array_shape,
|
|
68
|
+
time_delta=10,
|
|
69
|
+
num_modstates=1,
|
|
70
|
+
modstate=1,
|
|
71
|
+
start_time=start_time,
|
|
72
|
+
)
|
|
73
|
+
header_generator = (
|
|
74
|
+
spec122_validator.validate_and_translate_to_214_l0(d.header(), return_type=fits.HDUList)[
|
|
75
|
+
0
|
|
76
|
+
].header
|
|
77
|
+
for d in ds
|
|
78
|
+
)
|
|
79
|
+
hdul = generate_fits_frame(header_generator=header_generator, shape=array_shape)
|
|
80
|
+
cs_step = 1 if polcal_type == TaskName.polcal_gain.value else 0
|
|
81
|
+
for m in range(1, num_mod + 1):
|
|
82
|
+
task.write(
|
|
83
|
+
data=hdul,
|
|
84
|
+
tags=[
|
|
85
|
+
CryonirspTag.task(polcal_type),
|
|
86
|
+
CryonirspTag.task_polcal(),
|
|
87
|
+
CryonirspTag.modstate(m),
|
|
88
|
+
CryonirspTag.cs_step(cs_step),
|
|
89
|
+
CryonirspTag.linearized(),
|
|
90
|
+
CryonirspTag.frame(),
|
|
91
|
+
CryonirspTag.exposure_conditions(exposure_conditions),
|
|
92
|
+
],
|
|
93
|
+
encoder=fits_hdulist_encoder,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _create_polcal_arrays(
|
|
98
|
+
task,
|
|
99
|
+
dataset_shape,
|
|
100
|
+
array_shape,
|
|
101
|
+
exposure_conditions,
|
|
102
|
+
start_time,
|
|
103
|
+
num_modstates,
|
|
104
|
+
num_cs_steps,
|
|
105
|
+
):
|
|
106
|
+
for modstate in range(1, num_modstates + 1):
|
|
107
|
+
# Create polcal input frames for this modstate
|
|
108
|
+
ds = CryonirspHeadersValidPolcalFrames(
|
|
109
|
+
dataset_shape=dataset_shape,
|
|
110
|
+
array_shape=array_shape,
|
|
111
|
+
time_delta=10,
|
|
112
|
+
num_modstates=num_modstates,
|
|
113
|
+
modstate=modstate,
|
|
114
|
+
start_time=start_time,
|
|
115
|
+
)
|
|
116
|
+
header_generator = (
|
|
117
|
+
spec122_validator.validate_and_translate_to_214_l0(
|
|
118
|
+
d.header(), return_type=fits.HDUList
|
|
119
|
+
)[0].header
|
|
120
|
+
for d in ds
|
|
121
|
+
)
|
|
122
|
+
# cs_step does not map to a single keyword, so not needed in the fake headers
|
|
123
|
+
# We start at 2 because dark and gain are 0 and 1
|
|
124
|
+
for cs_step in range(2, num_cs_steps):
|
|
125
|
+
hdul = generate_fits_frame(header_generator=header_generator, shape=array_shape)
|
|
126
|
+
task.write(
|
|
127
|
+
data=hdul,
|
|
128
|
+
tags=[
|
|
129
|
+
CryonirspTag.task_polcal(),
|
|
130
|
+
CryonirspTag.modstate(modstate),
|
|
131
|
+
CryonirspTag.cs_step(cs_step),
|
|
132
|
+
CryonirspTag.linearized(),
|
|
133
|
+
CryonirspTag.frame(),
|
|
134
|
+
CryonirspTag.exposure_conditions(exposure_conditions),
|
|
135
|
+
],
|
|
136
|
+
encoder=fits_hdulist_encoder,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@pytest.fixture(scope="function")
|
|
141
|
+
def ci_instrument_polarization_calibration_task(
|
|
142
|
+
tmp_path,
|
|
143
|
+
recipe_run_id,
|
|
144
|
+
assign_input_dataset_doc_to_task,
|
|
145
|
+
init_cryonirsp_constants_db,
|
|
146
|
+
mocker,
|
|
147
|
+
):
|
|
148
|
+
num_beams = 1
|
|
149
|
+
num_modstates = 2
|
|
150
|
+
num_cs_steps = 2
|
|
151
|
+
num_spatial_steps = 1
|
|
152
|
+
exposure_time = 0.01 # From CryoHeadersValidPolcalFrames fixture (Check this value)
|
|
153
|
+
exposure_conditions = ExposureConditions(
|
|
154
|
+
exposure_time, AllowableOpticalDensityFilterNames.OPEN.value
|
|
155
|
+
)
|
|
156
|
+
# intermediate_shape = (10, 10)
|
|
157
|
+
dataset_shape = (num_cs_steps, 20, 10)
|
|
158
|
+
array_shape = (1, 20, 10)
|
|
159
|
+
constants_db = CryonirspConstantsDb(
|
|
160
|
+
NUM_MODSTATES=num_modstates,
|
|
161
|
+
NUM_BEAMS=num_beams,
|
|
162
|
+
NUM_CS_STEPS=num_cs_steps,
|
|
163
|
+
POLCAL_EXPOSURE_CONDITIONS_LIST=(exposure_conditions,),
|
|
164
|
+
ARM_ID="CI",
|
|
165
|
+
NUM_SPATIAL_STEPS=num_spatial_steps,
|
|
166
|
+
)
|
|
167
|
+
init_cryonirsp_constants_db(recipe_run_id, constants_db)
|
|
168
|
+
with CIInstrumentPolarizationCalibration(
|
|
169
|
+
recipe_run_id=recipe_run_id,
|
|
170
|
+
workflow_name="ci_instrument_polarization_calibration",
|
|
171
|
+
workflow_version="VX.Y",
|
|
172
|
+
) as task:
|
|
173
|
+
try: # This try... block is here to make sure the dbs get cleaned up if there's a failure in the fixture
|
|
174
|
+
task.scratch = WorkflowFileSystem(
|
|
175
|
+
scratch_base_path=tmp_path, recipe_run_id=recipe_run_id
|
|
176
|
+
)
|
|
177
|
+
param_class = cryonirsp_testing_parameters_factory(param_path=tmp_path)
|
|
178
|
+
assign_input_dataset_doc_to_task(task, param_class())
|
|
179
|
+
mocker.patch(
|
|
180
|
+
"dkist_processing_cryonirsp.tasks.instrument_polarization.PolcalFitter",
|
|
181
|
+
new=DummyPolcalFitter,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Don't test place-holder QA stuff for now
|
|
185
|
+
quality_metric_mocker = mocker.patch(
|
|
186
|
+
"dkist_processing_cryonirsp.tasks.instrument_polarization.CIInstrumentPolarizationCalibration.quality_store_polcal_results",
|
|
187
|
+
autospec=True,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Create beam border intermediate array that is consistent with a single pixel array
|
|
191
|
+
task.intermediate_frame_write_arrays(
|
|
192
|
+
arrays=np.array([0, 1, 0, 1]), task_tag=CryonirspTag.task_beam_boundaries(), beam=1
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# Create fake bad pixel map
|
|
196
|
+
task.intermediate_frame_write_arrays(
|
|
197
|
+
arrays=np.zeros((1, 1)), task_tag=CryonirspTag.task_bad_pixel_map()
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
start_time = datetime.now()
|
|
201
|
+
# Create a single fake polcal raw dark array
|
|
202
|
+
_create_polcal_dark_or_gain_array(
|
|
203
|
+
task,
|
|
204
|
+
array_shape,
|
|
205
|
+
num_modstates,
|
|
206
|
+
exposure_conditions,
|
|
207
|
+
TaskName.polcal_dark.value,
|
|
208
|
+
start_time,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Create a single fake polcal gain array
|
|
212
|
+
_create_polcal_dark_or_gain_array(
|
|
213
|
+
task,
|
|
214
|
+
array_shape,
|
|
215
|
+
num_modstates,
|
|
216
|
+
exposure_conditions,
|
|
217
|
+
TaskName.polcal_gain.value,
|
|
218
|
+
start_time,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Create a set of full polcal frames
|
|
222
|
+
_create_polcal_arrays(
|
|
223
|
+
task,
|
|
224
|
+
dataset_shape,
|
|
225
|
+
array_shape,
|
|
226
|
+
exposure_conditions,
|
|
227
|
+
start_time,
|
|
228
|
+
num_modstates,
|
|
229
|
+
num_cs_steps,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
yield task, quality_metric_mocker
|
|
233
|
+
finally:
|
|
234
|
+
task._purge()
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@pytest.fixture(scope="function")
|
|
238
|
+
def ci_instrument_polarization_calibration_task_with_no_data(
|
|
239
|
+
tmp_path, recipe_run_id, assign_input_dataset_doc_to_task, init_cryonirsp_constants_db
|
|
240
|
+
):
|
|
241
|
+
init_cryonirsp_constants_db(recipe_run_id, CryonirspConstantsDb())
|
|
242
|
+
with CIInstrumentPolarizationCalibration(
|
|
243
|
+
recipe_run_id=recipe_run_id,
|
|
244
|
+
workflow_name="ci_instrument_polarization_calibration",
|
|
245
|
+
workflow_version="VX.Y",
|
|
246
|
+
) as task:
|
|
247
|
+
try: # This try... block is here to make sure the dbs get cleaned up if there's a failure in the fixture
|
|
248
|
+
param_class = cryonirsp_testing_parameters_factory(param_path=tmp_path)
|
|
249
|
+
assign_input_dataset_doc_to_task(task, param_class())
|
|
250
|
+
yield task
|
|
251
|
+
finally:
|
|
252
|
+
task._purge()
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
@pytest.fixture(scope="function")
|
|
256
|
+
def sp_instrument_polarization_calibration_task(
|
|
257
|
+
tmp_path,
|
|
258
|
+
recipe_run_id,
|
|
259
|
+
assign_input_dataset_doc_to_task,
|
|
260
|
+
init_cryonirsp_constants_db,
|
|
261
|
+
mocker,
|
|
262
|
+
):
|
|
263
|
+
num_beams = 2
|
|
264
|
+
num_modstates = 2
|
|
265
|
+
num_cs_steps = 2
|
|
266
|
+
num_spatial_steps = 1
|
|
267
|
+
exposure_time = 0.01 # From CryoHeadersValidPolcalFrames fixture (Check this value)
|
|
268
|
+
exposure_conditions = ExposureConditions(
|
|
269
|
+
exposure_time, AllowableOpticalDensityFilterNames.OPEN.value
|
|
270
|
+
)
|
|
271
|
+
# intermediate_shape = (10, 10)
|
|
272
|
+
dataset_shape = (num_cs_steps, 20, 10)
|
|
273
|
+
array_shape = (1, 20, 10)
|
|
274
|
+
constants_db = CryonirspConstantsDb(
|
|
275
|
+
NUM_MODSTATES=num_modstates,
|
|
276
|
+
NUM_BEAMS=num_beams,
|
|
277
|
+
NUM_CS_STEPS=num_cs_steps,
|
|
278
|
+
POLCAL_EXPOSURE_CONDITIONS_LIST=(exposure_conditions,),
|
|
279
|
+
ARM_ID="SP",
|
|
280
|
+
NUM_SPATIAL_STEPS=num_spatial_steps,
|
|
281
|
+
)
|
|
282
|
+
init_cryonirsp_constants_db(recipe_run_id, constants_db)
|
|
283
|
+
with SPInstrumentPolarizationCalibration(
|
|
284
|
+
recipe_run_id=recipe_run_id,
|
|
285
|
+
workflow_name="sp_instrument_polarization_calibration",
|
|
286
|
+
workflow_version="VX.Y",
|
|
287
|
+
) as task:
|
|
288
|
+
try: # This try... block is here to make sure the dbs get cleaned up if there's a failure in the fixture
|
|
289
|
+
task.scratch = WorkflowFileSystem(
|
|
290
|
+
scratch_base_path=tmp_path, recipe_run_id=recipe_run_id
|
|
291
|
+
)
|
|
292
|
+
param_class = cryonirsp_testing_parameters_factory(param_path=tmp_path)
|
|
293
|
+
assign_input_dataset_doc_to_task(task, param_class())
|
|
294
|
+
mocker.patch(
|
|
295
|
+
"dkist_processing_cryonirsp.tasks.instrument_polarization.PolcalFitter",
|
|
296
|
+
new=DummyPolcalFitter,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# Don't test place-holder QA stuff for now
|
|
300
|
+
quality_metric_mocker = mocker.patch(
|
|
301
|
+
"dkist_processing_cryonirsp.tasks.instrument_polarization.SPInstrumentPolarizationCalibration.quality_store_polcal_results",
|
|
302
|
+
autospec=True,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# Create beam border intermediate arrays that are consistent with a single pixel array
|
|
306
|
+
for beam in range(1, num_beams + 1):
|
|
307
|
+
task.intermediate_frame_write_arrays(
|
|
308
|
+
arrays=np.array([0, 1, 0, 1]),
|
|
309
|
+
task_tag=CryonirspTag.task_beam_boundaries(),
|
|
310
|
+
beam=beam,
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Create fake bad pixel map
|
|
314
|
+
task.intermediate_frame_write_arrays(
|
|
315
|
+
arrays=np.zeros((1, 1)), task_tag=CryonirspTag.task_bad_pixel_map()
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
start_time = datetime.now()
|
|
319
|
+
# Create a single fake polcal raw dark array
|
|
320
|
+
_create_polcal_dark_or_gain_array(
|
|
321
|
+
task,
|
|
322
|
+
array_shape,
|
|
323
|
+
num_modstates,
|
|
324
|
+
exposure_conditions,
|
|
325
|
+
TaskName.polcal_dark.value,
|
|
326
|
+
start_time,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# Create a single fake polcal gain array
|
|
330
|
+
_create_polcal_dark_or_gain_array(
|
|
331
|
+
task,
|
|
332
|
+
array_shape,
|
|
333
|
+
num_modstates,
|
|
334
|
+
exposure_conditions,
|
|
335
|
+
TaskName.polcal_gain.value,
|
|
336
|
+
start_time,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
# Create a set of full polcal frames
|
|
340
|
+
_create_polcal_arrays(
|
|
341
|
+
task,
|
|
342
|
+
dataset_shape,
|
|
343
|
+
array_shape,
|
|
344
|
+
exposure_conditions,
|
|
345
|
+
start_time,
|
|
346
|
+
num_modstates,
|
|
347
|
+
num_cs_steps,
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
yield task, quality_metric_mocker
|
|
351
|
+
finally:
|
|
352
|
+
task._purge()
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@pytest.fixture(scope="function")
|
|
356
|
+
def sp_instrument_polarization_calibration_task_with_no_data(
|
|
357
|
+
tmp_path, recipe_run_id, assign_input_dataset_doc_to_task, init_cryonirsp_constants_db
|
|
358
|
+
):
|
|
359
|
+
init_cryonirsp_constants_db(recipe_run_id, CryonirspConstantsDb())
|
|
360
|
+
with SPInstrumentPolarizationCalibration(
|
|
361
|
+
recipe_run_id=recipe_run_id,
|
|
362
|
+
workflow_name="sp_instrument_polarization_calibration",
|
|
363
|
+
workflow_version="VX.Y",
|
|
364
|
+
) as task:
|
|
365
|
+
try: # This try... block is here to make sure the dbs get cleaned up if there's a failure in the fixture
|
|
366
|
+
param_class = cryonirsp_testing_parameters_factory(param_path=tmp_path)
|
|
367
|
+
assign_input_dataset_doc_to_task(task, param_class())
|
|
368
|
+
yield task
|
|
369
|
+
finally:
|
|
370
|
+
task._purge()
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
@pytest.fixture()
|
|
374
|
+
def full_beam_shape() -> tuple[int, int]:
|
|
375
|
+
return (100, 256)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
@pytest.fixture()
|
|
379
|
+
def single_demodulation_matrix() -> np.ndarray:
|
|
380
|
+
return np.arange(40).reshape(1, 1, 4, 10)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@pytest.fixture()
|
|
384
|
+
def multiple_demodulation_matrices() -> np.ndarray:
|
|
385
|
+
return np.arange(2 * 3 * 4 * 10).reshape(2, 3, 4, 10)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def test_ci_instrument_polarization_calibration_task(
|
|
389
|
+
ci_instrument_polarization_calibration_task, mocker
|
|
390
|
+
):
|
|
391
|
+
"""
|
|
392
|
+
Given: An InstrumentPolarizationCalibration task
|
|
393
|
+
When: Calling the task instance
|
|
394
|
+
Then: A demodulation matrix for each beam is produced and the correct call to the quality storage system was made
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
mocker.patch(
|
|
398
|
+
"dkist_processing_common.tasks.mixin.metadata_store.GraphQLClient", new=FakeGQLClient
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
# When
|
|
402
|
+
task, quality_mocker = ci_instrument_polarization_calibration_task
|
|
403
|
+
task()
|
|
404
|
+
|
|
405
|
+
# Then
|
|
406
|
+
for beam in [1]:
|
|
407
|
+
tags = [
|
|
408
|
+
CryonirspTag.intermediate(),
|
|
409
|
+
CryonirspTag.task_demodulation_matrices(),
|
|
410
|
+
CryonirspTag.beam(beam),
|
|
411
|
+
]
|
|
412
|
+
assert len(list(task.read(tags=tags))) == 1
|
|
413
|
+
|
|
414
|
+
quality_mocker.assert_any_call(
|
|
415
|
+
task,
|
|
416
|
+
polcal_fitter=ANY,
|
|
417
|
+
label=f"CI Beam {beam}",
|
|
418
|
+
bin_nums=[
|
|
419
|
+
task.parameters.polcal_num_spatial_bins,
|
|
420
|
+
task.parameters.polcal_num_spatial_bins,
|
|
421
|
+
],
|
|
422
|
+
bin_labels=["spatial", "spatial"],
|
|
423
|
+
skip_recording_constant_pars=False,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def test_sp_instrument_polarization_calibration_task(
|
|
428
|
+
sp_instrument_polarization_calibration_task, mocker
|
|
429
|
+
):
|
|
430
|
+
"""
|
|
431
|
+
Given: An InstrumentPolarizationCalibration task
|
|
432
|
+
When: Calling the task instance
|
|
433
|
+
Then: A demodulation matrix for each beam is produced and the correct call to the quality storage system was made
|
|
434
|
+
"""
|
|
435
|
+
|
|
436
|
+
mocker.patch(
|
|
437
|
+
"dkist_processing_common.tasks.mixin.metadata_store.GraphQLClient", new=FakeGQLClient
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
# When
|
|
441
|
+
task, quality_mocker = sp_instrument_polarization_calibration_task
|
|
442
|
+
task()
|
|
443
|
+
|
|
444
|
+
# Then
|
|
445
|
+
for beam in [1, 2]:
|
|
446
|
+
tags = [
|
|
447
|
+
CryonirspTag.intermediate(),
|
|
448
|
+
CryonirspTag.task_demodulation_matrices(),
|
|
449
|
+
CryonirspTag.beam(beam),
|
|
450
|
+
]
|
|
451
|
+
assert len(list(task.read(tags=tags))) == 1
|
|
452
|
+
|
|
453
|
+
quality_mocker.assert_any_call(
|
|
454
|
+
task,
|
|
455
|
+
polcal_fitter=ANY,
|
|
456
|
+
label=f"SP Beam {beam}",
|
|
457
|
+
bin_nums=[
|
|
458
|
+
task.parameters.polcal_num_spatial_bins,
|
|
459
|
+
task.parameters.polcal_num_spectral_bins,
|
|
460
|
+
],
|
|
461
|
+
bin_labels=["spatial", "spectral"],
|
|
462
|
+
skip_recording_constant_pars=beam == 2,
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def test_reshape_ci_demod_matrices(
|
|
467
|
+
ci_instrument_polarization_calibration_task_with_no_data,
|
|
468
|
+
multiple_demodulation_matrices,
|
|
469
|
+
full_beam_shape,
|
|
470
|
+
):
|
|
471
|
+
"""
|
|
472
|
+
Given: An InstrumentPolarizationCalibration task and a set of demodulation matrices sampled over the full FOV
|
|
473
|
+
When: Up-sampling the demodulation matrices
|
|
474
|
+
Then: The final set of demodulation matrices has the correct, full-FOV shape
|
|
475
|
+
"""
|
|
476
|
+
ci_instrument_polarization_calibration_task_with_no_data.single_beam_shape = full_beam_shape
|
|
477
|
+
result = ci_instrument_polarization_calibration_task_with_no_data.reshape_demod_matrices(
|
|
478
|
+
multiple_demodulation_matrices
|
|
479
|
+
)
|
|
480
|
+
assert result.shape == full_beam_shape + (4, 10)
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def test_reshape_sp_demod_matrices(
|
|
484
|
+
sp_instrument_polarization_calibration_task_with_no_data,
|
|
485
|
+
multiple_demodulation_matrices,
|
|
486
|
+
full_beam_shape,
|
|
487
|
+
):
|
|
488
|
+
"""
|
|
489
|
+
Given: An InstrumentPolarizationCalibration task and a set of demodulation matrices sampled over the full FOV
|
|
490
|
+
When: Up-sampling the demodulation matrices
|
|
491
|
+
Then: The final set of demodulation matrices has the correct, full-FOV shape
|
|
492
|
+
"""
|
|
493
|
+
sp_instrument_polarization_calibration_task_with_no_data.single_beam_shape = full_beam_shape
|
|
494
|
+
result = sp_instrument_polarization_calibration_task_with_no_data.reshape_demod_matrices(
|
|
495
|
+
multiple_demodulation_matrices
|
|
496
|
+
)
|
|
497
|
+
assert result.shape == full_beam_shape + (4, 10)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def test_reshape_single_ci_demod_matrix(
|
|
501
|
+
ci_instrument_polarization_calibration_task_with_no_data,
|
|
502
|
+
single_demodulation_matrix,
|
|
503
|
+
full_beam_shape,
|
|
504
|
+
):
|
|
505
|
+
"""
|
|
506
|
+
Given: An InstrumentPolarizationCalibration task and a single demodulation matrix for the whole FOV
|
|
507
|
+
When: Up-sampling the demodulation matrices
|
|
508
|
+
Then: The final set of demodulation matrices still only has a single matrix
|
|
509
|
+
"""
|
|
510
|
+
ci_instrument_polarization_calibration_task_with_no_data.single_beam_shape = full_beam_shape
|
|
511
|
+
result = ci_instrument_polarization_calibration_task_with_no_data.reshape_demod_matrices(
|
|
512
|
+
single_demodulation_matrix
|
|
513
|
+
)
|
|
514
|
+
assert result.shape == (4, 10)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def test_reshape_single_sp_demod_matrix(
|
|
518
|
+
sp_instrument_polarization_calibration_task_with_no_data,
|
|
519
|
+
single_demodulation_matrix,
|
|
520
|
+
full_beam_shape,
|
|
521
|
+
):
|
|
522
|
+
"""
|
|
523
|
+
Given: An InstrumentPolarizationCalibration task and a single demodulation matrix for the whole FOV
|
|
524
|
+
When: Up-sampling the demodulation matrices
|
|
525
|
+
Then: The final set of demodulation matrices still only has a single matrix
|
|
526
|
+
"""
|
|
527
|
+
sp_instrument_polarization_calibration_task_with_no_data.single_beam_shape = full_beam_shape
|
|
528
|
+
result = sp_instrument_polarization_calibration_task_with_no_data.reshape_demod_matrices(
|
|
529
|
+
single_demodulation_matrix
|
|
530
|
+
)
|
|
531
|
+
assert result.shape == (4, 10)
|