dkist-processing-dlnirsp 0.32.8__py3-none-any.whl → 0.33.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.
- dkist_processing_dlnirsp/models/constants.py +6 -0
- dkist_processing_dlnirsp/models/parameters.py +33 -3
- dkist_processing_dlnirsp/parsers/task.py +2 -25
- dkist_processing_dlnirsp/parsers/time.py +2 -2
- dkist_processing_dlnirsp/tasks/__init__.py +1 -2
- dkist_processing_dlnirsp/tasks/movie.py +1121 -0
- dkist_processing_dlnirsp/tasks/parse.py +13 -8
- dkist_processing_dlnirsp/tasks/solar.py +129 -30
- dkist_processing_dlnirsp/tests/conftest.py +46 -7
- dkist_processing_dlnirsp/tests/local_trial_workflows/l0_polcals_as_science.py +21 -18
- dkist_processing_dlnirsp/tests/local_trial_workflows/l0_solar_gain_as_science.py +21 -18
- dkist_processing_dlnirsp/tests/local_trial_workflows/l0_to_l1.py +21 -18
- dkist_processing_dlnirsp/tests/local_trial_workflows/local_trial_dev_mockers.py +1 -1
- dkist_processing_dlnirsp/tests/test_dlnirsp_constants.py +2 -0
- dkist_processing_dlnirsp/tests/test_movie.py +141 -0
- dkist_processing_dlnirsp/tests/test_parameters.py +8 -0
- dkist_processing_dlnirsp/tests/test_parse.py +10 -0
- dkist_processing_dlnirsp/tests/test_science.py +0 -9
- dkist_processing_dlnirsp/tests/test_solar.py +114 -17
- dkist_processing_dlnirsp/tests/test_wavelength_calibration.py +4 -1
- dkist_processing_dlnirsp/workflows/l0_processing.py +6 -8
- dkist_processing_dlnirsp/workflows/trial_workflow.py +7 -7
- {dkist_processing_dlnirsp-0.32.8.dist-info → dkist_processing_dlnirsp-0.33.0.dist-info}/METADATA +52 -35
- {dkist_processing_dlnirsp-0.32.8.dist-info → dkist_processing_dlnirsp-0.33.0.dist-info}/RECORD +28 -30
- docs/gain.rst +7 -3
- dkist_processing_dlnirsp/tasks/assemble_movie.py +0 -150
- dkist_processing_dlnirsp/tasks/make_movie_frames.py +0 -156
- dkist_processing_dlnirsp/tests/test_assemble_movie.py +0 -169
- dkist_processing_dlnirsp/tests/test_make_movie_frames.py +0 -98
- {dkist_processing_dlnirsp-0.32.8.dist-info → dkist_processing_dlnirsp-0.33.0.dist-info}/WHEEL +0 -0
- {dkist_processing_dlnirsp-0.32.8.dist-info → dkist_processing_dlnirsp-0.33.0.dist-info}/entry_points.txt +0 -0
- {dkist_processing_dlnirsp-0.32.8.dist-info → dkist_processing_dlnirsp-0.33.0.dist-info}/top_level.txt +0 -0
|
@@ -13,6 +13,7 @@ from dkist_processing_common.parsers.single_value_single_key_flower import (
|
|
|
13
13
|
SingleValueSingleKeyFlower,
|
|
14
14
|
)
|
|
15
15
|
from dkist_processing_common.parsers.task import PolcalTaskFlower
|
|
16
|
+
from dkist_processing_common.parsers.task import parse_header_ip_task_with_gains
|
|
16
17
|
from dkist_processing_common.parsers.time import ExposureTimeFlower
|
|
17
18
|
from dkist_processing_common.parsers.time import ObsIpStartTimeBud
|
|
18
19
|
from dkist_processing_common.parsers.time import TaskExposureTimesBud
|
|
@@ -36,7 +37,6 @@ from dkist_processing_dlnirsp.parsers.mosaic import NumMosaicRepeatsBud
|
|
|
36
37
|
from dkist_processing_dlnirsp.parsers.mosaic import NumMosaicXTilesBud
|
|
37
38
|
from dkist_processing_dlnirsp.parsers.mosaic import NumMosaicYTilesBud
|
|
38
39
|
from dkist_processing_dlnirsp.parsers.task import DlnirspTaskTypeFlower
|
|
39
|
-
from dkist_processing_dlnirsp.parsers.task import parse_header_ip_task
|
|
40
40
|
from dkist_processing_dlnirsp.parsers.time import DLnirspSolarGainIpStartTimeBud
|
|
41
41
|
from dkist_processing_dlnirsp.parsers.time import DlnirspTimeObsBud
|
|
42
42
|
from dkist_processing_dlnirsp.parsers.wavelength import ObserveWavelengthBud
|
|
@@ -145,6 +145,11 @@ class ParseL0DlnirspLinearizedData(ParseDataBase):
|
|
|
145
145
|
"""Add DLNIRSP specific constants to common constants."""
|
|
146
146
|
return default_constant_bud_factory() + [
|
|
147
147
|
ObserveWavelengthBud(),
|
|
148
|
+
TaskUniqueBud(
|
|
149
|
+
constant_name=DlnirspBudName.obs_ip_end_time.value,
|
|
150
|
+
metadata_key=MetadataKey.ip_end_time,
|
|
151
|
+
ip_task_types=TaskName.observe,
|
|
152
|
+
),
|
|
148
153
|
DLnirspSolarGainIpStartTimeBud(),
|
|
149
154
|
NumCSStepBud(max_cs_step_time_sec=self.parameters.max_cs_step_time_sec),
|
|
150
155
|
UniqueBud(
|
|
@@ -175,42 +180,42 @@ class ParseL0DlnirspLinearizedData(ParseDataBase):
|
|
|
175
180
|
TaskExposureTimesBud(
|
|
176
181
|
stem_name=DlnirspBudName.lamp_gain_exposure_times.value,
|
|
177
182
|
ip_task_types=TaskName.lamp_gain.value,
|
|
178
|
-
header_task_parsing_func=
|
|
183
|
+
header_task_parsing_func=parse_header_ip_task_with_gains,
|
|
179
184
|
),
|
|
180
185
|
TaskExposureTimesBud(
|
|
181
186
|
stem_name=DlnirspBudName.solar_gain_exposure_times.value,
|
|
182
187
|
ip_task_types=TaskName.solar_gain.value,
|
|
183
|
-
header_task_parsing_func=
|
|
188
|
+
header_task_parsing_func=parse_header_ip_task_with_gains,
|
|
184
189
|
),
|
|
185
190
|
TaskExposureTimesBud(
|
|
186
191
|
stem_name=DlnirspBudName.observe_exposure_times.value,
|
|
187
192
|
ip_task_types=TaskName.observe.value,
|
|
188
|
-
header_task_parsing_func=
|
|
193
|
+
header_task_parsing_func=parse_header_ip_task_with_gains,
|
|
189
194
|
),
|
|
190
195
|
TaskExposureTimesBud(
|
|
191
196
|
stem_name=DlnirspBudName.polcal_exposure_times.value,
|
|
192
197
|
ip_task_types=TaskName.polcal.value,
|
|
193
|
-
header_task_parsing_func=
|
|
198
|
+
header_task_parsing_func=parse_header_ip_task_with_gains,
|
|
194
199
|
),
|
|
195
200
|
TaskNearFloatBud(
|
|
196
201
|
constant_name=DlnirspBudName.arm_position_mm.value,
|
|
197
202
|
metadata_key=DlnirspMetadataKey.arm_position_mm,
|
|
198
203
|
ip_task_types=[TaskName.solar_gain.value, TaskName.observe.value],
|
|
199
204
|
tolerance=0.01,
|
|
200
|
-
task_type_parsing_function=
|
|
205
|
+
task_type_parsing_function=parse_header_ip_task_with_gains,
|
|
201
206
|
),
|
|
202
207
|
TaskUniqueBud(
|
|
203
208
|
constant_name=DlnirspBudName.grating_constant_inverse_mm.value,
|
|
204
209
|
metadata_key=DlnirspMetadataKey.grating_constant_inverse_mm,
|
|
205
210
|
ip_task_types=[TaskName.solar_gain.value, TaskName.observe.value],
|
|
206
|
-
task_type_parsing_function=
|
|
211
|
+
task_type_parsing_function=parse_header_ip_task_with_gains,
|
|
207
212
|
),
|
|
208
213
|
TaskNearFloatBud(
|
|
209
214
|
constant_name=DlnirspBudName.grating_position_deg.value,
|
|
210
215
|
metadata_key=DlnirspMetadataKey.grating_position_deg,
|
|
211
216
|
ip_task_types=[TaskName.solar_gain.value, TaskName.observe.value],
|
|
212
217
|
tolerance=0.01,
|
|
213
|
-
task_type_parsing_function=
|
|
218
|
+
task_type_parsing_function=parse_header_ip_task_with_gains,
|
|
214
219
|
),
|
|
215
220
|
]
|
|
216
221
|
|
|
@@ -8,6 +8,7 @@ from dkist_processing_common.models.task_name import TaskName
|
|
|
8
8
|
from dkist_processing_common.tasks.mixin.quality import QualityMixin
|
|
9
9
|
from dkist_processing_math.arithmetic import divide_arrays_by_array
|
|
10
10
|
from dkist_processing_math.arithmetic import subtract_array_from_arrays
|
|
11
|
+
from dkist_processing_math.linear_algebra import nd_left_matrix_multiply
|
|
11
12
|
from dkist_processing_math.statistics import average_numpy_arrays
|
|
12
13
|
from dkist_service_configuration.logging import logger
|
|
13
14
|
|
|
@@ -17,8 +18,10 @@ from dkist_processing_dlnirsp.tasks.mixin.corrections import CorrectionsMixin
|
|
|
17
18
|
|
|
18
19
|
__all__ = ["SolarCalibration"]
|
|
19
20
|
|
|
21
|
+
from dkist_processing_dlnirsp.tasks.mixin.group_id import GroupIdMixin
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
|
|
24
|
+
class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin, GroupIdMixin):
|
|
22
25
|
"""
|
|
23
26
|
Task for computing an intermediate solar gain image.
|
|
24
27
|
|
|
@@ -33,21 +36,23 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
33
36
|
"""
|
|
34
37
|
Compute a solar gain image with the solar spectrum removed.
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
2. Compute a single characteristic spectrum across all slitbeams and place into the full array
|
|
39
|
-
|
|
40
|
-
3. Re-apply the geometric calibration (spectral shifts and scales) to the characteristic spectra
|
|
41
|
-
|
|
42
|
-
4. Remove the characteristic solar spectra from the dark-corrected solar gain image
|
|
39
|
+
#. Compute dark-only and fully (additional lamp and geometric) corrected solar gain data.
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
a. For polarimetric data, compute a separate average for each modstate and then demodulate and use the Stokes I data
|
|
42
|
+
#. For intensity data, use the average over all modstates (there should be only one).
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
#. Compute a single characteristic spectrum across all slitbeams and place into the full array
|
|
45
|
+
#. Re-apply the geometric calibration (spectral shifts and scales) to the characteristic spectra
|
|
46
|
+
#. Remove the characteristic solar spectra from the dark-corrected solar gain image
|
|
47
|
+
#. Rescale each slitbeam to have the same average value as the raw, dark corrected solar gain image
|
|
48
|
+
#. Write the final, solar-spectrum-removed solar gain image.
|
|
47
49
|
"""
|
|
48
50
|
with self.telemetry_span("Apply dark and lamp corrections"):
|
|
49
51
|
logger.info("Computing average dark/lamp corrected gains")
|
|
50
|
-
self.
|
|
52
|
+
if self.constants.correct_for_polarization:
|
|
53
|
+
self.compute_demodulated_I_gains()
|
|
54
|
+
else:
|
|
55
|
+
self.compute_intensity_only_avg_gains()
|
|
51
56
|
|
|
52
57
|
with self.telemetry_span("Compute characteristic spectra"):
|
|
53
58
|
logger.info("Computing characteristic spectra")
|
|
@@ -81,9 +86,12 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
81
86
|
|
|
82
87
|
with self.telemetry_span("Write solar flat calibration"):
|
|
83
88
|
logger.info("Writing solar flat calibration")
|
|
89
|
+
tags = [DlnirspTag.intermediate_frame(), DlnirspTag.task_solar_gain()]
|
|
90
|
+
if self.constants.correct_for_polarization:
|
|
91
|
+
tags.append(DlnirspTag.stokes("I"))
|
|
84
92
|
self.write(
|
|
85
93
|
data=cleaned_gain,
|
|
86
|
-
tags=
|
|
94
|
+
tags=tags,
|
|
87
95
|
encoder=fits_array_encoder,
|
|
88
96
|
)
|
|
89
97
|
|
|
@@ -96,13 +104,110 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
96
104
|
task_type=TaskName.solar_gain.value, total_frames=no_of_raw_solar_frames
|
|
97
105
|
)
|
|
98
106
|
|
|
99
|
-
def
|
|
107
|
+
def compute_intensity_only_avg_gains(self):
|
|
108
|
+
"""
|
|
109
|
+
Compute dark-only and fully-corrected average solar gains for intensity mode data.
|
|
110
|
+
|
|
111
|
+
The raw solar gain frames are averaged over all modstates (of which there should only be one anyway).
|
|
112
|
+
The lamp-corrected data also have geometric corrections applied prior to saving.
|
|
113
|
+
"""
|
|
114
|
+
dark_corr, lamp_corr = self.compute_average_corrected_gain_for_modstate(modstate=None)
|
|
115
|
+
|
|
116
|
+
# This is the array we remove the characteristic solar spectrum from to produce the final gain array
|
|
117
|
+
self.write(
|
|
118
|
+
data=dark_corr,
|
|
119
|
+
tags=[DlnirspTag.intermediate_frame(), DlnirspTag.task("SC_DARK_ONLY")],
|
|
120
|
+
encoder=fits_array_encoder,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
geo_corr_gain = self.apply_geometric_correction(lamp_corr)
|
|
124
|
+
|
|
125
|
+
self.write(
|
|
126
|
+
data=geo_corr_gain,
|
|
127
|
+
tags=[DlnirspTag.intermediate_frame(), DlnirspTag.task("SC_FULL_CORR")],
|
|
128
|
+
encoder=fits_array_encoder,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def compute_demodulated_I_gains(self):
|
|
132
|
+
"""
|
|
133
|
+
Compute demodulated dark-only and fully-corrected solar gain data.
|
|
134
|
+
|
|
135
|
+
The raw solar gains are averaged once for each modstate before having dark and lamp corrections applied.
|
|
136
|
+
These two sets of arrays (dark-only and dark + lamp) are then demodulated. The resulting Stokes I are then saved
|
|
137
|
+
to disk for later use. The lamp-corrected data have a geometric correction applied prior to saving.
|
|
138
|
+
"""
|
|
139
|
+
dark_corr_modstate_stack = np.empty(
|
|
140
|
+
self.unrectified_array_shape + (self.constants.num_modstates,)
|
|
141
|
+
)
|
|
142
|
+
lamp_corr_modstate_stack = np.empty_like(dark_corr_modstate_stack)
|
|
143
|
+
for modstate in range(1, self.constants.num_modstates + 1):
|
|
144
|
+
dark_corr, lamp_corr = self.compute_average_corrected_gain_for_modstate(modstate)
|
|
145
|
+
dark_corr_modstate_stack[:, :, modstate - 1] = dark_corr
|
|
146
|
+
lamp_corr_modstate_stack[:, :, modstate - 1] = lamp_corr
|
|
147
|
+
|
|
148
|
+
logger.info("Loading demodulation matrices")
|
|
149
|
+
demod_matrices = next(
|
|
150
|
+
self.read(
|
|
151
|
+
tags=[DlnirspTag.intermediate_frame(), DlnirspTag.task_demodulation_matrices()],
|
|
152
|
+
decoder=fits_array_decoder,
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
demodulated_dark_corr_gain = nd_left_matrix_multiply(
|
|
157
|
+
vector_stack=dark_corr_modstate_stack, matrix_stack=demod_matrices
|
|
158
|
+
)
|
|
159
|
+
demodulated_lamp_corr_gain = nd_left_matrix_multiply(
|
|
160
|
+
vector_stack=lamp_corr_modstate_stack, matrix_stack=demod_matrices
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
dark_corr_I = demodulated_dark_corr_gain[:, :, 0]
|
|
164
|
+
lamp_corr_I = demodulated_lamp_corr_gain[:, :, 0]
|
|
165
|
+
|
|
166
|
+
# This is the array we remove the characteristic solar spectrum from to produce the final gain array
|
|
167
|
+
self.write(
|
|
168
|
+
data=dark_corr_I,
|
|
169
|
+
tags=[
|
|
170
|
+
DlnirspTag.intermediate_frame(),
|
|
171
|
+
DlnirspTag.task("SC_DARK_ONLY"),
|
|
172
|
+
DlnirspTag.stokes("I"),
|
|
173
|
+
],
|
|
174
|
+
encoder=fits_array_encoder,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
geo_corr_gain = self.apply_geometric_correction(lamp_corr_I)
|
|
178
|
+
|
|
179
|
+
self.write(
|
|
180
|
+
data=geo_corr_gain,
|
|
181
|
+
tags=[
|
|
182
|
+
DlnirspTag.intermediate_frame(),
|
|
183
|
+
DlnirspTag.task("SC_FULL_CORR"),
|
|
184
|
+
DlnirspTag.stokes("I"),
|
|
185
|
+
],
|
|
186
|
+
encoder=fits_array_encoder,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
def compute_average_corrected_gain_for_modstate(
|
|
190
|
+
self, modstate: int | None
|
|
191
|
+
) -> tuple[np.ndarray, np.ndarray]:
|
|
100
192
|
"""
|
|
101
|
-
Compute a single, averaged frame from all linearized solar gain frames.
|
|
193
|
+
Compute a single, averaged frame from all linearized solar gain frames for a given modstate.
|
|
102
194
|
|
|
103
|
-
Also apply dark
|
|
195
|
+
Also apply dark and lamp corrections. If there are multiple exposure times present in the solar
|
|
104
196
|
gain images, all frames for a single exposure time are averged prior to dark correction. Then all averaged
|
|
105
197
|
exposure time frames are averaged again into a single frame.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
modstate
|
|
202
|
+
The modstate to average over. If `None` then the average is performed over all modstates.
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
dark_corrected
|
|
207
|
+
The average solar gains with only a dark correction applied
|
|
208
|
+
|
|
209
|
+
lamp_corrected
|
|
210
|
+
The average solar gains with both dark and lamp corrections applied
|
|
106
211
|
"""
|
|
107
212
|
all_exp_times = []
|
|
108
213
|
for exp_time in self.constants.solar_gain_exposure_times:
|
|
@@ -114,12 +219,14 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
114
219
|
)
|
|
115
220
|
)
|
|
116
221
|
|
|
117
|
-
logger.info(f"Loading solar gain frames for {exp_time = }")
|
|
222
|
+
logger.info(f"Loading solar gain frames for {modstate = } and {exp_time = }")
|
|
118
223
|
tags = [
|
|
119
224
|
DlnirspTag.linearized_frame(),
|
|
120
225
|
DlnirspTag.task_solar_gain(),
|
|
121
226
|
DlnirspTag.exposure_time(exp_time),
|
|
122
227
|
]
|
|
228
|
+
if modstate is not None:
|
|
229
|
+
tags.append(DlnirspTag.modstate(modstate))
|
|
123
230
|
gain_arrays = self.read(tags=tags, decoder=fits_array_decoder)
|
|
124
231
|
|
|
125
232
|
logger.info("Averaging solar gain frames")
|
|
@@ -135,13 +242,6 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
135
242
|
logger.info(f"Computing final average gain array for {len(all_exp_times)} exposure times")
|
|
136
243
|
avg_gain_array = average_numpy_arrays(all_exp_times)
|
|
137
244
|
|
|
138
|
-
# This is the array we remove the characteristic solar spectrum from to produce the final gain array
|
|
139
|
-
self.write(
|
|
140
|
-
data=avg_gain_array,
|
|
141
|
-
tags=[DlnirspTag.intermediate_frame(), DlnirspTag.task("SC_DARK_ONLY")],
|
|
142
|
-
encoder=fits_array_encoder,
|
|
143
|
-
)
|
|
144
|
-
|
|
145
245
|
logger.info("Loading lamp calibration")
|
|
146
246
|
lamp_array = next(
|
|
147
247
|
self.read(
|
|
@@ -155,8 +255,11 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
155
255
|
divide_arrays_by_array(arrays=avg_gain_array, array_to_divide_by=lamp_array)
|
|
156
256
|
)
|
|
157
257
|
|
|
158
|
-
|
|
258
|
+
return avg_gain_array, lamp_corrected_array
|
|
159
259
|
|
|
260
|
+
def apply_geometric_correction(self, array: np.ndarray) -> np.ndarray:
|
|
261
|
+
"""Apply the geometric correction to an array."""
|
|
262
|
+
logger.info("Loading geometric calibration")
|
|
160
263
|
geometric_correction = next(
|
|
161
264
|
self.read(
|
|
162
265
|
tags=[DlnirspTag.intermediate(), DlnirspTag.task_geometric()], decoder=asdf_decoder
|
|
@@ -169,7 +272,7 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
169
272
|
logger.info("Applying geometric calibration")
|
|
170
273
|
final_gain_array = next(
|
|
171
274
|
self.corrections_remove_spec_geometry(
|
|
172
|
-
arrays=
|
|
275
|
+
arrays=array,
|
|
173
276
|
shift_dict=shifts,
|
|
174
277
|
scale_dict=scales,
|
|
175
278
|
reference_wavelength_axis=reference_wavelength_axis,
|
|
@@ -177,11 +280,7 @@ class SolarCalibration(DlnirspTaskBase, CorrectionsMixin, QualityMixin):
|
|
|
177
280
|
)
|
|
178
281
|
)
|
|
179
282
|
|
|
180
|
-
|
|
181
|
-
data=final_gain_array,
|
|
182
|
-
tags=[DlnirspTag.intermediate_frame(), DlnirspTag.task("SC_FULL_CORR")],
|
|
183
|
-
encoder=fits_array_encoder,
|
|
184
|
-
)
|
|
283
|
+
return final_gain_array
|
|
185
284
|
|
|
186
285
|
def compute_characteristic_spectra(self) -> np.ndarray:
|
|
187
286
|
"""
|
|
@@ -132,7 +132,7 @@ class DlnirspTestingParameters:
|
|
|
132
132
|
dlnirsp_geo_reference_wave_min_nonnan_frac: float = 0.05
|
|
133
133
|
dlnirsp_wavecal_atlas_download_config: dict[str, str] = field(
|
|
134
134
|
default_factory=lambda: {
|
|
135
|
-
"base_url": "
|
|
135
|
+
"base_url": "https://g-a36282.cd214.a567.data.globus.org/atlas/",
|
|
136
136
|
"telluric_reference_atlas_file_name": "telluric_reference_atlas.npy",
|
|
137
137
|
"telluric_reference_atlas_hash_id": "md5:8db5e12508b293bca3495d81a0747447",
|
|
138
138
|
"solar_reference_atlas_file_name": "solar_reference_atlas.npy",
|
|
@@ -170,12 +170,25 @@ class DlnirspTestingParameters:
|
|
|
170
170
|
dlnirsp_bad_pixel_correction_interpolation_kernel_shape: tuple[int, int] = (10, 3)
|
|
171
171
|
dlnirsp_wcs_pc_correction_matrix: tuple[tuple[int]] = ((1, 0), (0, -1))
|
|
172
172
|
dlnirsp_wcs_crpix_correction_method: str = "swap_then_flip_crpix2"
|
|
173
|
+
dlnirsp_movie_core_wave_value_nm_vis: float = 853.98
|
|
174
|
+
dlnirsp_movie_core_wave_value_nm_jband: float = 1083.0
|
|
175
|
+
dlnirsp_movie_core_wave_value_nm_hband: float = 1564.8
|
|
176
|
+
dlnirsp_movie_cont_wave_value_nm_vis: float = 854.23
|
|
177
|
+
dlnirsp_movie_cont_wave_value_nm_jband: float = 1083.268
|
|
178
|
+
dlnirsp_movie_cont_wave_value_nm_hband: float = 1565.06
|
|
179
|
+
dlnirsp_movie_vertical_nan_slices: tuple[tuple[int | None, int | None]] = (
|
|
180
|
+
(None, 1),
|
|
181
|
+
(31, 34),
|
|
182
|
+
(-2, None),
|
|
183
|
+
)
|
|
184
|
+
dlnirsp_movie_nan_replacement_kernel_shape: tuple[int, int] = (5, 5)
|
|
173
185
|
|
|
174
186
|
|
|
175
187
|
@dataclass
|
|
176
188
|
class DlnirspTestingConstants:
|
|
177
189
|
INSTRUMENT: str = "DLNIRSP"
|
|
178
|
-
OBS_IP_START_TIME: str = "2024-06-
|
|
190
|
+
OBS_IP_START_TIME: str = "2024-06-06T00:00:00"
|
|
191
|
+
OBS_IP_END_TIME: str = "2024-06-06T00:10:00"
|
|
179
192
|
ARM_ID: str = "HBand"
|
|
180
193
|
NUM_MODSTATES: int = 8
|
|
181
194
|
NUM_MOSAIC_TILES_X: int = 2
|
|
@@ -204,6 +217,7 @@ class DlnirspTestingConstants:
|
|
|
204
217
|
"EXPERID2",
|
|
205
218
|
"EXPERID3",
|
|
206
219
|
)
|
|
220
|
+
EXPERIMENT_ID: str = "eid_6_28"
|
|
207
221
|
ARM_POSITION_MM: float = -4.2
|
|
208
222
|
GRATING_CONSTANT_INVERSE_MM: float = 20.0
|
|
209
223
|
GRATING_POSITION_DEG: float = 87.4
|
|
@@ -1229,6 +1243,8 @@ class CalibratedHeaders(ModulatedObserveHeaders):
|
|
|
1229
1243
|
is_polarimetric: bool,
|
|
1230
1244
|
dither_mode_on: bool = False,
|
|
1231
1245
|
array_shape: tuple[int, int, int] = (3, 4, 5),
|
|
1246
|
+
crpix1_step_delta: float = 40.0,
|
|
1247
|
+
crpix2_step_delta: float = 30.0,
|
|
1232
1248
|
):
|
|
1233
1249
|
|
|
1234
1250
|
# Use the data_cycles loop to represent Stokes parameters
|
|
@@ -1246,6 +1262,8 @@ class CalibratedHeaders(ModulatedObserveHeaders):
|
|
|
1246
1262
|
allow_3D_arrays=True,
|
|
1247
1263
|
)
|
|
1248
1264
|
|
|
1265
|
+
self.crpix1_step_delta = crpix1_step_delta
|
|
1266
|
+
self.crpix2_step_delta = crpix2_step_delta
|
|
1249
1267
|
self.stokes_name_list = ["I", "Q", "U", "V"]
|
|
1250
1268
|
self.add_constant_key("DLN__014", 8 if is_polarimetric else 1)
|
|
1251
1269
|
self.add_constant_key("DLN__008", "Full Stokes" if is_polarimetric else "Stokes I")
|
|
@@ -1263,12 +1281,21 @@ class CalibratedHeaders(ModulatedObserveHeaders):
|
|
|
1263
1281
|
) # -1 b/c data cycles are indexed from 1
|
|
1264
1282
|
return self.stokes_name_list[stokes_axis_id]
|
|
1265
1283
|
|
|
1284
|
+
@property
|
|
1285
|
+
def current_crpix1(self) -> float:
|
|
1286
|
+
return self.array_shape[2] / 2 - self.crpix1_step_delta * self.current_MINDEX1_value
|
|
1287
|
+
|
|
1288
|
+
@property
|
|
1289
|
+
def current_crpix2(self) -> float:
|
|
1290
|
+
return self.array_shape[1] / 2 - self.crpix2_step_delta * self.current_MINDEX2_value
|
|
1291
|
+
|
|
1266
1292
|
@property
|
|
1267
1293
|
def fits_wcs(self):
|
|
1294
|
+
# Taken from real data from eid_2_24
|
|
1268
1295
|
w = WCS(naxis=3)
|
|
1269
|
-
w.wcs.crpix = self.
|
|
1270
|
-
w.wcs.crval =
|
|
1271
|
-
w.wcs.cdelt =
|
|
1296
|
+
w.wcs.crpix = self.current_crpix1, self.current_crpix2, self.array_shape[0] / 2
|
|
1297
|
+
w.wcs.crval = 176.118, -289.575, 1565.0
|
|
1298
|
+
w.wcs.cdelt = 0.031, 0.031, 0.2
|
|
1272
1299
|
w.wcs.cunit = "arcsec", "arcsec", "nm"
|
|
1273
1300
|
w.wcs.ctype = "HPLN-TAN", "HPLT-TAN", "AWAV"
|
|
1274
1301
|
w.wcs.pc = np.identity(self.array_ndim)
|
|
@@ -1342,6 +1369,15 @@ def make_cs_data(
|
|
|
1342
1369
|
return data
|
|
1343
1370
|
|
|
1344
1371
|
|
|
1372
|
+
@pytest.fixture
|
|
1373
|
+
def make_full_demodulation_matrix(demodulation_matrix):
|
|
1374
|
+
def make_array(frame: Spec122Dataset):
|
|
1375
|
+
array_shape = frame.array_shape[1:]
|
|
1376
|
+
return np.ones(array_shape + demodulation_matrix.shape) * demodulation_matrix
|
|
1377
|
+
|
|
1378
|
+
return make_array
|
|
1379
|
+
|
|
1380
|
+
|
|
1345
1381
|
def tag_on_modstate(frame: Spec122Dataset) -> list[str]:
|
|
1346
1382
|
modstate = frame.header()["DLN__015"]
|
|
1347
1383
|
return [DlnirspTag.modstate(modstate)]
|
|
@@ -1631,11 +1667,12 @@ def write_observe_frames_to_task(
|
|
|
1631
1667
|
array_shape: tuple[int, int] = (10, 10),
|
|
1632
1668
|
crpix_delta: tuple[float, float] = (80.3, 20.7),
|
|
1633
1669
|
swap_crpix_values: bool = False,
|
|
1670
|
+
start_date: str = "2023-01-01T01:23:45",
|
|
1671
|
+
modstate_length_sec: float = 0.5,
|
|
1634
1672
|
data_func: callable = make_random_data,
|
|
1635
1673
|
tags: list[str] | None = None,
|
|
1636
1674
|
tag_func: callable = lambda x: [],
|
|
1637
1675
|
) -> int:
|
|
1638
|
-
|
|
1639
1676
|
frame_generator = ModulatedObserveHeaders(
|
|
1640
1677
|
num_modstates=num_modstates,
|
|
1641
1678
|
num_X_tiles=num_X_tiles,
|
|
@@ -1650,6 +1687,8 @@ def write_observe_frames_to_task(
|
|
|
1650
1687
|
grating_angle=grating_angle,
|
|
1651
1688
|
crpix_delta=crpix_delta,
|
|
1652
1689
|
swap_crpix_values=swap_crpix_values,
|
|
1690
|
+
start_date=start_date,
|
|
1691
|
+
modstate_length_sec=modstate_length_sec,
|
|
1653
1692
|
)
|
|
1654
1693
|
|
|
1655
1694
|
num_frames = write_frames_to_task(
|
|
@@ -1700,7 +1739,7 @@ def write_calibrated_frames_to_task(
|
|
|
1700
1739
|
is_polarimetric: bool,
|
|
1701
1740
|
array_shape: tuple[int, int, int],
|
|
1702
1741
|
dither_mode_on: bool = False,
|
|
1703
|
-
data_func:
|
|
1742
|
+
data_func: Callable = make_3D_random_data,
|
|
1704
1743
|
):
|
|
1705
1744
|
dataset = CalibratedHeaders(
|
|
1706
1745
|
num_mosaics=num_mosaics,
|
|
@@ -13,11 +13,10 @@ from dkist_processing_common.tasks import WorkflowTaskBase
|
|
|
13
13
|
from dkist_service_configuration.logging import logger
|
|
14
14
|
|
|
15
15
|
from dkist_processing_dlnirsp.models.tags import DlnirspTag
|
|
16
|
-
from dkist_processing_dlnirsp.tasks import AssembleDlnirspMovie
|
|
17
16
|
from dkist_processing_dlnirsp.tasks import DlnirspAssembleQualityData
|
|
18
17
|
from dkist_processing_dlnirsp.tasks import DlnirspL0QualityMetrics
|
|
19
18
|
from dkist_processing_dlnirsp.tasks import DlnirspL1QualityMetrics
|
|
20
|
-
from dkist_processing_dlnirsp.tasks import
|
|
19
|
+
from dkist_processing_dlnirsp.tasks import MakeDlnirspMovie
|
|
21
20
|
from dkist_processing_dlnirsp.tasks.bad_pixel_map import BadPixelCalibration
|
|
22
21
|
from dkist_processing_dlnirsp.tasks.dark import DarkCalibration
|
|
23
22
|
from dkist_processing_dlnirsp.tasks.geometric import GeometricCalibration
|
|
@@ -197,10 +196,11 @@ def main(
|
|
|
197
196
|
load_bad_pixel: bool = False,
|
|
198
197
|
load_geometric: bool = False,
|
|
199
198
|
load_wavelength_calibration: bool = False,
|
|
200
|
-
load_solar: bool = False,
|
|
201
199
|
load_inst_polcal: bool = False,
|
|
200
|
+
load_solar: bool = False,
|
|
202
201
|
load_polcals_as_science: bool = False,
|
|
203
202
|
load_calibrated_data: bool = False,
|
|
203
|
+
skip_movie: bool = False,
|
|
204
204
|
transfer_trial_data: str | None = None,
|
|
205
205
|
):
|
|
206
206
|
with ManualProcessing(
|
|
@@ -298,18 +298,18 @@ def main(
|
|
|
298
298
|
manual_processing_run.run_task(task=WavelengthCalibration)
|
|
299
299
|
manual_processing_run.run_task(task=SaveWavelengthCal)
|
|
300
300
|
|
|
301
|
-
if load_solar:
|
|
302
|
-
manual_processing_run.run_task(task=LoadSolarCal)
|
|
303
|
-
else:
|
|
304
|
-
manual_processing_run.run_task(task=SolarCalibration)
|
|
305
|
-
manual_processing_run.run_task(task=SaveSolarCal)
|
|
306
|
-
|
|
307
301
|
if load_inst_polcal:
|
|
308
302
|
manual_processing_run.run_task(task=LoadInstPolCal)
|
|
309
303
|
else:
|
|
310
304
|
manual_processing_run.run_task(task=InstrumentPolarizationCalibration)
|
|
311
305
|
manual_processing_run.run_task(task=SaveInstPolCal)
|
|
312
306
|
|
|
307
|
+
if load_solar:
|
|
308
|
+
manual_processing_run.run_task(task=LoadSolarCal)
|
|
309
|
+
else:
|
|
310
|
+
manual_processing_run.run_task(task=SolarCalibration)
|
|
311
|
+
manual_processing_run.run_task(task=SaveSolarCal)
|
|
312
|
+
|
|
313
313
|
if load_polcals_as_science:
|
|
314
314
|
manual_processing_run.run_task(task=LoadPolCalAsScience)
|
|
315
315
|
else:
|
|
@@ -324,8 +324,6 @@ def main(
|
|
|
324
324
|
|
|
325
325
|
manual_processing_run.run_task(task=permissive_write_l1_task(force_intensity_only=False))
|
|
326
326
|
manual_processing_run.run_task(task=ValidateL1Output)
|
|
327
|
-
manual_processing_run.run_task(task=MakeDlnirspMovieFrames)
|
|
328
|
-
manual_processing_run.run_task(task=AssembleDlnirspMovie)
|
|
329
327
|
|
|
330
328
|
manual_processing_run.run_task(task=DlnirspL0QualityMetrics)
|
|
331
329
|
manual_processing_run.run_task(task=DlnirspL1QualityMetrics)
|
|
@@ -334,6 +332,9 @@ def main(
|
|
|
334
332
|
|
|
335
333
|
manual_processing_run.run_task(task=CreateTrialQualityReport)
|
|
336
334
|
|
|
335
|
+
if not skip_movie:
|
|
336
|
+
manual_processing_run.run_task(task=MakeDlnirspMovie)
|
|
337
|
+
|
|
337
338
|
if transfer_trial_data:
|
|
338
339
|
transfer_trial_data_locally(
|
|
339
340
|
trial_output_location=transfer_trial_data, processing_run=manual_processing_run
|
|
@@ -425,18 +426,18 @@ if __name__ == "__main__":
|
|
|
425
426
|
help="Load wavelength calibration solution from previously saved run",
|
|
426
427
|
action="store_true",
|
|
427
428
|
)
|
|
428
|
-
parser.add_argument(
|
|
429
|
-
"-S",
|
|
430
|
-
"--load-solar",
|
|
431
|
-
help="Load solar calibration from previously saved run",
|
|
432
|
-
action="store_true",
|
|
433
|
-
)
|
|
434
429
|
parser.add_argument(
|
|
435
430
|
"-P",
|
|
436
431
|
"--load-inst-polcal",
|
|
437
432
|
help="Load instrument polarization calibration from previously saved run",
|
|
438
433
|
action="store_true",
|
|
439
434
|
)
|
|
435
|
+
parser.add_argument(
|
|
436
|
+
"-S",
|
|
437
|
+
"--load-solar",
|
|
438
|
+
help="Load solar calibration from previously saved run",
|
|
439
|
+
action="store_true",
|
|
440
|
+
)
|
|
440
441
|
parser.add_argument(
|
|
441
442
|
"-O",
|
|
442
443
|
"--load-polcals-as-science",
|
|
@@ -446,6 +447,7 @@ if __name__ == "__main__":
|
|
|
446
447
|
parser.add_argument(
|
|
447
448
|
"-C", "--load-calibrated-data", help="Load CALIBRATED 'science' frames", action="store_true"
|
|
448
449
|
)
|
|
450
|
+
parser.add_argument("-V", "--skip-movie", help="Don't make a browse movie", action="store_true")
|
|
449
451
|
parser.add_argument(
|
|
450
452
|
"-p",
|
|
451
453
|
"--param-dir",
|
|
@@ -472,10 +474,11 @@ if __name__ == "__main__":
|
|
|
472
474
|
load_bad_pixel=args.load_bad_pixel,
|
|
473
475
|
load_geometric=args.load_geometric,
|
|
474
476
|
load_wavelength_calibration=args.load_wavelength_calibration,
|
|
475
|
-
load_solar=args.load_solar,
|
|
476
477
|
load_inst_polcal=args.load_inst_polcal,
|
|
478
|
+
load_solar=args.load_solar,
|
|
477
479
|
load_polcals_as_science=args.load_polcals_as_science,
|
|
478
480
|
load_calibrated_data=args.load_calibrated_data,
|
|
481
|
+
skip_movie=args.skip_movie,
|
|
479
482
|
transfer_trial_data=args.transfer_trial_data,
|
|
480
483
|
)
|
|
481
484
|
)
|