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,436 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pytest
|
|
6
|
+
from astropy.io import fits
|
|
7
|
+
from astropy.time import Time
|
|
8
|
+
from dkist_fits_specifications import __version__ as spec_version
|
|
9
|
+
from dkist_header_validator import spec214_validator
|
|
10
|
+
from dkist_processing_common.codecs.asdf import asdf_encoder
|
|
11
|
+
from dkist_processing_common.codecs.fits import fits_hdulist_encoder
|
|
12
|
+
from dkist_processing_common.tests.conftest import FakeGQLClient
|
|
13
|
+
|
|
14
|
+
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
15
|
+
from dkist_processing_cryonirsp.tasks.write_l1 import CIWriteL1Frame
|
|
16
|
+
from dkist_processing_cryonirsp.tasks.write_l1 import CryonirspWriteL1Frame
|
|
17
|
+
from dkist_processing_cryonirsp.tasks.write_l1 import SPWriteL1Frame
|
|
18
|
+
from dkist_processing_cryonirsp.tests.conftest import CryonirspConstantsDb
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.fixture(scope="function")
|
|
22
|
+
def write_l1_task(
|
|
23
|
+
recipe_run_id,
|
|
24
|
+
calibrated_ci_cryonirsp_headers,
|
|
25
|
+
calibrated_cryonirsp_headers,
|
|
26
|
+
init_cryonirsp_constants_db,
|
|
27
|
+
num_stokes_params,
|
|
28
|
+
num_map_scans,
|
|
29
|
+
num_meas,
|
|
30
|
+
arm_id,
|
|
31
|
+
):
|
|
32
|
+
if num_stokes_params == 1:
|
|
33
|
+
num_modstates = 1
|
|
34
|
+
else:
|
|
35
|
+
num_modstates = 2
|
|
36
|
+
num_scan_steps = 2
|
|
37
|
+
if arm_id == "CI":
|
|
38
|
+
axis_1_type = "HPLN-TAN"
|
|
39
|
+
axis_2_type = "HPLT-TAN"
|
|
40
|
+
axis_3_type = "AWAV"
|
|
41
|
+
write_l1_task = CIWriteL1Frame
|
|
42
|
+
calibrated_headers = calibrated_ci_cryonirsp_headers
|
|
43
|
+
else:
|
|
44
|
+
axis_1_type = "AWAV"
|
|
45
|
+
axis_2_type = "HPLT-TAN"
|
|
46
|
+
axis_3_type = "HPLN-TAN"
|
|
47
|
+
write_l1_task = SPWriteL1Frame
|
|
48
|
+
calibrated_headers = calibrated_cryonirsp_headers
|
|
49
|
+
|
|
50
|
+
constants_db = CryonirspConstantsDb(
|
|
51
|
+
AVERAGE_CADENCE=10,
|
|
52
|
+
MINIMUM_CADENCE=10,
|
|
53
|
+
MAXIMUM_CADENCE=10,
|
|
54
|
+
VARIANCE_CADENCE=0,
|
|
55
|
+
NUM_MAP_SCANS=num_map_scans,
|
|
56
|
+
NUM_SCAN_STEPS=num_scan_steps,
|
|
57
|
+
# Needed so self.correct_for_polarization is set to the right value
|
|
58
|
+
NUM_MODSTATES=num_modstates,
|
|
59
|
+
ARM_ID=arm_id,
|
|
60
|
+
AXIS_1_TYPE=axis_1_type,
|
|
61
|
+
AXIS_2_TYPE=axis_2_type,
|
|
62
|
+
AXIS_3_TYPE=axis_3_type,
|
|
63
|
+
NUM_MEAS=num_meas,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
init_cryonirsp_constants_db(recipe_run_id, constants_db)
|
|
67
|
+
with write_l1_task(
|
|
68
|
+
recipe_run_id=recipe_run_id,
|
|
69
|
+
workflow_name="workflow_name",
|
|
70
|
+
workflow_version="workflow_version",
|
|
71
|
+
) as task:
|
|
72
|
+
try: # This try... block is here to make sure the dbs get cleaned up if there's a failure in the fixture
|
|
73
|
+
if num_stokes_params == 1:
|
|
74
|
+
stokes_params = ["I"]
|
|
75
|
+
else:
|
|
76
|
+
stokes_params = ["I", "Q", "U", "V"]
|
|
77
|
+
# Random data needed so skew and kurtosis don't barf
|
|
78
|
+
header = calibrated_headers
|
|
79
|
+
hdu = fits.PrimaryHDU(
|
|
80
|
+
data=np.random.random((header["NAXIS3"], header["NAXIS2"], header["NAXIS1"]))
|
|
81
|
+
* 100.0,
|
|
82
|
+
header=calibrated_headers,
|
|
83
|
+
)
|
|
84
|
+
hdul = fits.HDUList([hdu])
|
|
85
|
+
hdul[0].header["CTYPE1"] = axis_1_type
|
|
86
|
+
hdul[0].header["CTYPE2"] = axis_2_type
|
|
87
|
+
hdul[0].header["CTYPE3"] = axis_3_type
|
|
88
|
+
hdul[0].header["CNNMAPS"] = num_map_scans
|
|
89
|
+
|
|
90
|
+
# Set CNMODNST and CNSPINMD so the correct schema is loaded for validation
|
|
91
|
+
hdul[0].header["CNMODNST"] = num_modstates
|
|
92
|
+
if num_stokes_params > 1:
|
|
93
|
+
hdul[0].header["CNSPINMD"] = "Continuous"
|
|
94
|
+
|
|
95
|
+
# These headers are added to polarimetric frames in the science task
|
|
96
|
+
hdul[0].header["POL_NOIS"] = 0.1
|
|
97
|
+
hdul[0].header["POL_SENS"] = 0.2
|
|
98
|
+
|
|
99
|
+
else:
|
|
100
|
+
hdul[0].header["CNSPINMD"] = "None"
|
|
101
|
+
|
|
102
|
+
if arm_id == "SP":
|
|
103
|
+
write_dummy_sp_dispersion_intermediate(task, hdul[0].header)
|
|
104
|
+
|
|
105
|
+
for map_scan in range(1, num_map_scans + 1):
|
|
106
|
+
for scan_step in range(1, num_scan_steps + 1):
|
|
107
|
+
for meas_num in range(1, num_meas + 1):
|
|
108
|
+
# all stokes files have the same date-beg
|
|
109
|
+
hdul[0].header["DATE-BEG"] = datetime.now().isoformat("T")
|
|
110
|
+
for stokes_param in stokes_params:
|
|
111
|
+
hdul[0].header["CNCMEAS"] = meas_num
|
|
112
|
+
hdul[0].header["CNMAP"] = map_scan
|
|
113
|
+
task.write(
|
|
114
|
+
data=hdul,
|
|
115
|
+
tags=[
|
|
116
|
+
CryonirspTag.calibrated(),
|
|
117
|
+
CryonirspTag.frame(),
|
|
118
|
+
CryonirspTag.stokes(stokes_param),
|
|
119
|
+
CryonirspTag.meas_num(meas_num),
|
|
120
|
+
CryonirspTag.map_scan(map_scan),
|
|
121
|
+
CryonirspTag.scan_step(scan_step),
|
|
122
|
+
],
|
|
123
|
+
encoder=fits_hdulist_encoder,
|
|
124
|
+
)
|
|
125
|
+
yield task, stokes_params, hdul[0].header
|
|
126
|
+
finally:
|
|
127
|
+
task._purge()
|
|
128
|
+
|
|
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
|
+
]
|
|
137
|
+
|
|
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()
|
|
143
|
+
|
|
144
|
+
task.write(
|
|
145
|
+
data=dummy_fit_solution,
|
|
146
|
+
tags=[CryonirspTag.intermediate(), CryonirspTag.task_spectral_fit()],
|
|
147
|
+
encoder=asdf_encoder,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@pytest.mark.parametrize(
|
|
152
|
+
"num_stokes_params",
|
|
153
|
+
[pytest.param(1, id="Stokes I"), pytest.param(4, id="Stokes IQUV")],
|
|
154
|
+
)
|
|
155
|
+
@pytest.mark.parametrize(
|
|
156
|
+
"num_meas",
|
|
157
|
+
[pytest.param(1, id="single meas"), pytest.param(2, id="multiple meas")],
|
|
158
|
+
)
|
|
159
|
+
@pytest.mark.parametrize(
|
|
160
|
+
"num_map_scans",
|
|
161
|
+
[pytest.param(1, id="single map"), pytest.param(2, id="multiple maps")],
|
|
162
|
+
)
|
|
163
|
+
@pytest.mark.parametrize(
|
|
164
|
+
"arm_id",
|
|
165
|
+
[pytest.param("CI", id="CI"), pytest.param("SP", id="SP")],
|
|
166
|
+
)
|
|
167
|
+
def test_write_l1_frame(write_l1_task, mocker, arm_id, num_stokes_params, num_map_scans, num_meas):
|
|
168
|
+
"""
|
|
169
|
+
:Given: a write L1 task
|
|
170
|
+
:When: running the task
|
|
171
|
+
:Then: the correct header keys are written
|
|
172
|
+
"""
|
|
173
|
+
mocker.patch(
|
|
174
|
+
"dkist_processing_common.tasks.mixin.metadata_store.GraphQLClient", new=FakeGQLClient
|
|
175
|
+
)
|
|
176
|
+
task, stokes_params, original_headers = write_l1_task
|
|
177
|
+
task()
|
|
178
|
+
|
|
179
|
+
for stokes_param in stokes_params:
|
|
180
|
+
common_tags = [
|
|
181
|
+
CryonirspTag.frame(),
|
|
182
|
+
CryonirspTag.stokes(stokes_param),
|
|
183
|
+
]
|
|
184
|
+
output_files = list(task.read(tags=common_tags + [CryonirspTag.output()]))
|
|
185
|
+
calibrated_files = list(task.read(tags=common_tags + [CryonirspTag.calibrated()]))
|
|
186
|
+
assert (
|
|
187
|
+
len(output_files)
|
|
188
|
+
== task.constants.num_map_scans
|
|
189
|
+
* task.constants.num_scan_steps
|
|
190
|
+
* task.constants.num_meas
|
|
191
|
+
)
|
|
192
|
+
preserve_date_tests(output_files, calibrated_files)
|
|
193
|
+
for output_file in output_files:
|
|
194
|
+
assert output_file.exists
|
|
195
|
+
assert output_file.name.startswith(f"CRYO-NIRSP_{arm_id}_")
|
|
196
|
+
assert spec214_validator.validate(output_file, extra=False)
|
|
197
|
+
hdu_list = fits.open(output_file)
|
|
198
|
+
header = hdu_list[1].header
|
|
199
|
+
assert len(hdu_list) == 2 # Primary, CompImage
|
|
200
|
+
assert type(hdu_list[0]) is fits.PrimaryHDU
|
|
201
|
+
assert type(hdu_list[1]) is fits.CompImageHDU
|
|
202
|
+
axis_num = 1
|
|
203
|
+
if arm_id == "CI":
|
|
204
|
+
longitude_axis_tests(axis_num, header)
|
|
205
|
+
ci_spatial_axis_correction_tests(axis_num, original_headers, header)
|
|
206
|
+
else:
|
|
207
|
+
spectral_axis_tests(axis_num, header)
|
|
208
|
+
sp_spatial_axis_correction_tests(axis_num, original_headers, header)
|
|
209
|
+
sp_spectral_axis_correction_tests(original_headers, header)
|
|
210
|
+
axis_num += 1
|
|
211
|
+
latitude_axis_tests(axis_num, arm_id, header)
|
|
212
|
+
axis_num += 1
|
|
213
|
+
if task.constants.num_meas > 1:
|
|
214
|
+
measurement_axis_tests(axis_num, header, task)
|
|
215
|
+
axis_num += 1
|
|
216
|
+
scan_step_axis_tests(axis_num, arm_id, header, task)
|
|
217
|
+
if task.constants.num_map_scans > 1:
|
|
218
|
+
axis_num += 1
|
|
219
|
+
map_scan_tests(axis_num, header, task)
|
|
220
|
+
if task.constants.correct_for_polarization:
|
|
221
|
+
axis_num += 1
|
|
222
|
+
stokes_axis_tests(axis_num, header)
|
|
223
|
+
|
|
224
|
+
# Other general tests
|
|
225
|
+
general_header_tests(axis_num, header, task, arm_id)
|
|
226
|
+
|
|
227
|
+
axis_flip_tests(original_headers, header, arm_id)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def sp_spatial_axis_correction_tests(
|
|
231
|
+
axis_num: int, original_header: fits.Header, header: fits.Header
|
|
232
|
+
):
|
|
233
|
+
# test that headers were actually updated
|
|
234
|
+
if axis_num == 1:
|
|
235
|
+
assert header[f"PC{axis_num}_1"] == 1.0
|
|
236
|
+
assert header[f"PC{axis_num}_1A"] == 1.0
|
|
237
|
+
assert header[f"PC{axis_num}_2"] == 0.0
|
|
238
|
+
assert header[f"PC{axis_num}_2A"] == 0.0
|
|
239
|
+
assert header[f"PC{axis_num}_3"] == 0.0
|
|
240
|
+
assert header[f"PC{axis_num}_3A"] == 0.0
|
|
241
|
+
elif axis_num == 2 or 3:
|
|
242
|
+
assert header[f"PC{axis_num}_1"] == 0.0
|
|
243
|
+
assert header[f"PC{axis_num}_1A"] == 0.0
|
|
244
|
+
assert header[f"PC{axis_num}_2"] != original_header[f"PC{axis_num}_2"]
|
|
245
|
+
assert header[f"PC{axis_num}_2A"] != original_header[f"PC{axis_num}_2A"]
|
|
246
|
+
assert header[f"PC{axis_num}_3"] != original_header[f"PC{axis_num}_3"]
|
|
247
|
+
assert header[f"PC{axis_num}_3A"] != original_header[f"PC{axis_num}_3A"]
|
|
248
|
+
assert header[f"CRPIX{axis_num}"] != original_header[f"CRPIX{axis_num}"]
|
|
249
|
+
assert header[f"CRPIX{axis_num}A"] != original_header[f"CRPIX{axis_num}A"]
|
|
250
|
+
assert header[f"CDELT{axis_num}"] != original_header[f"CDELT{axis_num}"]
|
|
251
|
+
assert header[f"CDELT{axis_num}A"] != original_header[f"CDELT{axis_num}A"]
|
|
252
|
+
|
|
253
|
+
assert header["SLITORI"]
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def ci_spatial_axis_correction_tests(
|
|
257
|
+
axis_num: int, original_header: fits.Header, header: fits.Header
|
|
258
|
+
):
|
|
259
|
+
if axis_num == 1 or 2:
|
|
260
|
+
assert header[f"PC{axis_num}_1"] != original_header[f"PC{axis_num}_1"]
|
|
261
|
+
assert header[f"PC{axis_num}_1A"] != original_header[f"PC{axis_num}_1A"]
|
|
262
|
+
assert header[f"PC{axis_num}_2"] != original_header[f"PC{axis_num}_2"]
|
|
263
|
+
assert header[f"PC{axis_num}_2A"] != original_header[f"PC{axis_num}_2A"]
|
|
264
|
+
assert header[f"PC{axis_num}_3"] == 0
|
|
265
|
+
assert header[f"PC{axis_num}_3A"] == 0
|
|
266
|
+
assert header[f"CRPIX{axis_num}"] != original_header[f"CRPIX{axis_num}"]
|
|
267
|
+
assert header[f"CRPIX{axis_num}A"] != original_header[f"CRPIX{axis_num}A"]
|
|
268
|
+
assert header[f"CDELT{axis_num}"] != original_header[f"CDELT{axis_num}"]
|
|
269
|
+
assert header[f"CDELT{axis_num}A"] != original_header[f"CDELT{axis_num}A"]
|
|
270
|
+
|
|
271
|
+
if axis_num == 3:
|
|
272
|
+
assert header[f"PC{axis_num}_1"] == 0
|
|
273
|
+
assert header[f"PC{axis_num}_2"] == 0
|
|
274
|
+
assert header[f"PC{axis_num}_3"] == 1
|
|
275
|
+
assert header[f"PC{axis_num}_1A"] == 0
|
|
276
|
+
assert header[f"PC{axis_num}_2A"] == 0
|
|
277
|
+
assert header[f"PC{axis_num}_3A"] == 1
|
|
278
|
+
|
|
279
|
+
assert header["SLITORI"]
|
|
280
|
+
assert header["CNM1BOFF"] == 8.0
|
|
281
|
+
assert header["CNM1OFF"] == -2.75
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def sp_spectral_axis_correction_tests(original_headers: fits.Header, header: fits.Header):
|
|
285
|
+
# CRPIX gets tested in `axis_flip_tests`
|
|
286
|
+
assert header["CRVAL1"] != original_headers["CRVAL1"]
|
|
287
|
+
assert header["CRVAL1A"] != original_headers["CRVAL1A"]
|
|
288
|
+
assert header["CDELT1"] != original_headers["CDELT1"]
|
|
289
|
+
assert header["CDELT1A"] != original_headers["CDELT1A"]
|
|
290
|
+
assert header["CTYPE1"] == "AWAV-GRA"
|
|
291
|
+
assert header["CUNIT1"] == "nm"
|
|
292
|
+
assert header["CTYPE1A"] == "AWAV-GRA"
|
|
293
|
+
assert header["CUNIT1A"] == "nm"
|
|
294
|
+
assert "PV1_0" in header
|
|
295
|
+
assert "PV1_2" in header
|
|
296
|
+
assert "PV1_1" in header
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def longitude_axis_tests(axis_num: int, header: fits.Header):
|
|
300
|
+
assert header[f"DNAXIS{axis_num}"] == header[f"NAXIS{axis_num}"]
|
|
301
|
+
assert header[f"DTYPE{axis_num}"] == "SPATIAL"
|
|
302
|
+
assert header[f"DWNAME{axis_num}"] == "helioprojective longitude"
|
|
303
|
+
assert header[f"DUNIT{axis_num}"] == header[f"CUNIT{axis_num}"]
|
|
304
|
+
assert header[f"DPNAME{axis_num}"] == "detector y axis"
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def spectral_axis_tests(axis_num: int, header: fits.Header):
|
|
308
|
+
assert header[f"DNAXIS{axis_num}"] == header[f"NAXIS{axis_num}"]
|
|
309
|
+
assert header[f"DTYPE{axis_num}"] == "SPECTRAL"
|
|
310
|
+
assert header[f"DPNAME{axis_num}"] == "dispersion axis"
|
|
311
|
+
assert header[f"DWNAME{axis_num}"] == "wavelength"
|
|
312
|
+
assert header[f"DUNIT{axis_num}"] == header[f"CUNIT{axis_num}"]
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def latitude_axis_tests(axis_num: int, arm_id: str, header: fits.Header):
|
|
316
|
+
if arm_id == "CI":
|
|
317
|
+
latitude_dp_name = "detector x axis"
|
|
318
|
+
else:
|
|
319
|
+
latitude_dp_name = "spatial along slit"
|
|
320
|
+
assert header[f"DNAXIS{axis_num}"] == header[f"NAXIS{axis_num}"]
|
|
321
|
+
assert header[f"DTYPE{axis_num}"] == "SPATIAL"
|
|
322
|
+
assert header[f"DPNAME{axis_num}"] == latitude_dp_name
|
|
323
|
+
assert header[f"DWNAME{axis_num}"] == "helioprojective latitude"
|
|
324
|
+
assert header[f"DUNIT{axis_num}"] == header[f"CUNIT{axis_num}"]
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def measurement_axis_tests(axis_num: int, header: fits.Header, task: CryonirspWriteL1Frame):
|
|
328
|
+
assert header[f"DNAXIS{axis_num}"] == task.constants.num_meas
|
|
329
|
+
assert header[f"DTYPE{axis_num}"] == "TEMPORAL"
|
|
330
|
+
assert header[f"DPNAME{axis_num}"] == "measurement number"
|
|
331
|
+
assert header[f"DWNAME{axis_num}"] == "time"
|
|
332
|
+
assert header[f"DUNIT{axis_num}"] == "s"
|
|
333
|
+
assert header[f"DINDEX{axis_num}"] == header["CNCMEAS"]
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def scan_step_axis_tests(
|
|
337
|
+
axis_num: int, arm_id: str, header: fits.Header, task: CryonirspWriteL1Frame
|
|
338
|
+
):
|
|
339
|
+
if arm_id == "CI":
|
|
340
|
+
scan_step_value = "TEMPORAL"
|
|
341
|
+
scan_step_dwname = "time"
|
|
342
|
+
scan_step_dunit = "s"
|
|
343
|
+
else:
|
|
344
|
+
scan_step_value = "SPATIAL"
|
|
345
|
+
scan_step_dwname = "helioprojective longitude"
|
|
346
|
+
scan_step_dunit = header[f"CUNIT3"]
|
|
347
|
+
|
|
348
|
+
assert header[f"DNAXIS{axis_num}"] == task.constants.num_scan_steps
|
|
349
|
+
assert header[f"DTYPE{axis_num}"] == scan_step_value
|
|
350
|
+
assert header[f"DPNAME{axis_num}"] == "scan step number"
|
|
351
|
+
assert header[f"DWNAME{axis_num}"] == scan_step_dwname
|
|
352
|
+
assert header[f"DUNIT{axis_num}"] == scan_step_dunit
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def map_scan_tests(axis_num: int, header: fits.Header, task: CryonirspWriteL1Frame):
|
|
356
|
+
assert header["CNNMAPS"] == task.constants.num_map_scans
|
|
357
|
+
assert header[f"DNAXIS{axis_num}"] == task.constants.num_map_scans
|
|
358
|
+
assert header[f"DTYPE{axis_num}"] == "TEMPORAL"
|
|
359
|
+
assert header[f"DPNAME{axis_num}"] == "map scan number"
|
|
360
|
+
assert header[f"DWNAME{axis_num}"] == "time"
|
|
361
|
+
assert header[f"DUNIT{axis_num}"] == "s"
|
|
362
|
+
assert header[f"DINDEX{axis_num}"] == header["CNMAP"]
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def stokes_axis_tests(axis_num: int, header: fits.Header):
|
|
366
|
+
assert header[f"DNAXIS{axis_num}"] == 4
|
|
367
|
+
assert header[f"DTYPE{axis_num}"] == "STOKES"
|
|
368
|
+
assert header[f"DPNAME{axis_num}"] == "polarization state"
|
|
369
|
+
assert header[f"DWNAME{axis_num}"] == "polarization state"
|
|
370
|
+
assert header[f"DUNIT{axis_num}"] == ""
|
|
371
|
+
assert header[f"DINDEX{axis_num}"] in range(1, 5)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def axis_flip_tests(original_header: fits.Header, header: fits.Header, arm_id: str):
|
|
375
|
+
if arm_id == "SP":
|
|
376
|
+
axis_length = original_header["NAXIS1"]
|
|
377
|
+
ref_pix = original_header["CRPIX1"]
|
|
378
|
+
assert header["CDELT1"] > 0
|
|
379
|
+
assert header["CRPIX1"] == axis_length - ref_pix
|
|
380
|
+
if arm_id == "CI":
|
|
381
|
+
pass
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def preserve_date_tests(output_files: list[Path], calibrated_files: list[Path]) -> None:
|
|
385
|
+
# Make sure we didn't overwrite pre-computed DATE-BEG and DATE-END keys
|
|
386
|
+
cal_headers = [fits.getheader(f) for f in calibrated_files]
|
|
387
|
+
output_headers = [fits.getheader(f, ext=1) for f in output_files]
|
|
388
|
+
|
|
389
|
+
assert sorted([h["DATE-BEG"] for h in cal_headers]) == sorted(
|
|
390
|
+
[h["DATE-BEG"] for h in output_headers]
|
|
391
|
+
)
|
|
392
|
+
assert sorted([h["DATE-END"] for h in cal_headers]) == sorted(
|
|
393
|
+
[h["DATE-END"] for h in output_headers]
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def general_header_tests(
|
|
398
|
+
axis_num: int,
|
|
399
|
+
header: fits.Header,
|
|
400
|
+
task: CryonirspWriteL1Frame,
|
|
401
|
+
arm_id: str,
|
|
402
|
+
):
|
|
403
|
+
# Other general tests
|
|
404
|
+
assert header["DAAXES"] == 2
|
|
405
|
+
assert header["DNAXIS"] == axis_num
|
|
406
|
+
assert header["DEAXES"] == axis_num - 2
|
|
407
|
+
assert f"DNAXIS{axis_num + 1}" not in header
|
|
408
|
+
|
|
409
|
+
assert header["INFO_URL"] == task.docs_base_url
|
|
410
|
+
assert header["HEADVERS"] == spec_version
|
|
411
|
+
assert header["HEAD_URL"] == f"{task.docs_base_url}/projects/data-products/en/v{spec_version}"
|
|
412
|
+
calvers = task.version_from_module_name()
|
|
413
|
+
assert header["CALVERS"] == calvers
|
|
414
|
+
assert (
|
|
415
|
+
header["CAL_URL"]
|
|
416
|
+
== f"{task.docs_base_url}/projects/{task.constants.instrument.lower()}/en/v{calvers}/{task.workflow_name}.html"
|
|
417
|
+
)
|
|
418
|
+
date_avg = (
|
|
419
|
+
(Time(header["DATE-END"], precision=6) - Time(header["DATE-BEG"], precision=6)) / 2
|
|
420
|
+
+ Time(header["DATE-BEG"], precision=6)
|
|
421
|
+
).isot
|
|
422
|
+
assert header["DATE-AVG"] == date_avg
|
|
423
|
+
assert isinstance(header["HLSVERS"], str)
|
|
424
|
+
assert header["NSPECLNS"] == 1
|
|
425
|
+
assert header["WAVEBAND"] == "He I (1083.0 nm)"
|
|
426
|
+
assert header["SPECLN01"] == "He I (1083.0 nm)"
|
|
427
|
+
with pytest.raises(KeyError):
|
|
428
|
+
header["SPECLN02"]
|
|
429
|
+
|
|
430
|
+
# wavelength range tests
|
|
431
|
+
if arm_id == "SP":
|
|
432
|
+
assert round(header["WAVEMIN"], 2) == 1082
|
|
433
|
+
assert round(header["WAVEMAX"], 2) == 1084
|
|
434
|
+
if arm_id == "CI":
|
|
435
|
+
assert header["WAVEMIN"] == 1082.5
|
|
436
|
+
assert header["WAVEMAX"] == 1083.5
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Cryo CI raw data processing workflow."""
|
|
2
|
+
from dkist_processing_common.tasks import PublishCatalogAndQualityMessages
|
|
3
|
+
from dkist_processing_common.tasks import QualityL1Metrics
|
|
4
|
+
from dkist_processing_common.tasks import SubmitDatasetMetadata
|
|
5
|
+
from dkist_processing_common.tasks import Teardown
|
|
6
|
+
from dkist_processing_common.tasks import TransferL0Data
|
|
7
|
+
from dkist_processing_common.tasks import TransferL1Data
|
|
8
|
+
from dkist_processing_core import ResourceQueue
|
|
9
|
+
from dkist_processing_core import Workflow
|
|
10
|
+
|
|
11
|
+
from dkist_processing_cryonirsp.tasks import AssembleCryonirspMovie
|
|
12
|
+
from dkist_processing_cryonirsp.tasks import BadPixelMapCalibration
|
|
13
|
+
from dkist_processing_cryonirsp.tasks import CIBeamBoundariesCalibration
|
|
14
|
+
from dkist_processing_cryonirsp.tasks import (
|
|
15
|
+
CIInstrumentPolarizationCalibration,
|
|
16
|
+
)
|
|
17
|
+
from dkist_processing_cryonirsp.tasks import CIScienceCalibration
|
|
18
|
+
from dkist_processing_cryonirsp.tasks import CISolarGainCalibration
|
|
19
|
+
from dkist_processing_cryonirsp.tasks import CIWriteL1Frame
|
|
20
|
+
from dkist_processing_cryonirsp.tasks import CryonirspL0QualityMetrics
|
|
21
|
+
from dkist_processing_cryonirsp.tasks import CryonirspL1QualityMetrics
|
|
22
|
+
from dkist_processing_cryonirsp.tasks import DarkCalibration
|
|
23
|
+
from dkist_processing_cryonirsp.tasks import LampGainCalibration
|
|
24
|
+
from dkist_processing_cryonirsp.tasks import LinearityCorrection
|
|
25
|
+
from dkist_processing_cryonirsp.tasks import MakeCryonirspMovieFrames
|
|
26
|
+
from dkist_processing_cryonirsp.tasks import ParseL0CryonirspRampData
|
|
27
|
+
from dkist_processing_cryonirsp.tasks.l1_output_data import CIAssembleQualityData
|
|
28
|
+
from dkist_processing_cryonirsp.tasks.parse import ParseL0CryonirspCILinearizedData
|
|
29
|
+
|
|
30
|
+
l0_pipeline = Workflow(
|
|
31
|
+
category="cryonirsp",
|
|
32
|
+
input_data="l0",
|
|
33
|
+
output_data="l1",
|
|
34
|
+
detail="ci",
|
|
35
|
+
workflow_package=__package__,
|
|
36
|
+
)
|
|
37
|
+
l0_pipeline.add_node(task=TransferL0Data, upstreams=None)
|
|
38
|
+
|
|
39
|
+
# Science flow
|
|
40
|
+
l0_pipeline.add_node(task=ParseL0CryonirspRampData, upstreams=TransferL0Data)
|
|
41
|
+
l0_pipeline.add_node(
|
|
42
|
+
task=LinearityCorrection,
|
|
43
|
+
resource_queue=ResourceQueue.HIGH_MEMORY,
|
|
44
|
+
upstreams=ParseL0CryonirspRampData,
|
|
45
|
+
)
|
|
46
|
+
l0_pipeline.add_node(task=ParseL0CryonirspCILinearizedData, upstreams=LinearityCorrection)
|
|
47
|
+
l0_pipeline.add_node(task=BadPixelMapCalibration, upstreams=ParseL0CryonirspCILinearizedData)
|
|
48
|
+
l0_pipeline.add_node(task=CIBeamBoundariesCalibration, upstreams=BadPixelMapCalibration)
|
|
49
|
+
l0_pipeline.add_node(task=DarkCalibration, upstreams=CIBeamBoundariesCalibration)
|
|
50
|
+
l0_pipeline.add_node(task=LampGainCalibration, upstreams=DarkCalibration)
|
|
51
|
+
l0_pipeline.add_node(task=CISolarGainCalibration, upstreams=LampGainCalibration)
|
|
52
|
+
l0_pipeline.add_node(task=CIInstrumentPolarizationCalibration, upstreams=CISolarGainCalibration)
|
|
53
|
+
l0_pipeline.add_node(task=CIScienceCalibration, upstreams=CIInstrumentPolarizationCalibration)
|
|
54
|
+
l0_pipeline.add_node(task=CIWriteL1Frame, upstreams=CIScienceCalibration)
|
|
55
|
+
|
|
56
|
+
# Movie flow
|
|
57
|
+
l0_pipeline.add_node(task=MakeCryonirspMovieFrames, upstreams=CIScienceCalibration)
|
|
58
|
+
l0_pipeline.add_node(task=AssembleCryonirspMovie, upstreams=MakeCryonirspMovieFrames)
|
|
59
|
+
|
|
60
|
+
# Quality flow
|
|
61
|
+
l0_pipeline.add_node(task=CryonirspL0QualityMetrics, upstreams=ParseL0CryonirspCILinearizedData)
|
|
62
|
+
l0_pipeline.add_node(task=QualityL1Metrics, upstreams=CIScienceCalibration)
|
|
63
|
+
l0_pipeline.add_node(task=CryonirspL1QualityMetrics, upstreams=CIScienceCalibration)
|
|
64
|
+
l0_pipeline.add_node(
|
|
65
|
+
task=CIAssembleQualityData,
|
|
66
|
+
upstreams=[CryonirspL0QualityMetrics, QualityL1Metrics, CryonirspL1QualityMetrics],
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Output flow
|
|
70
|
+
l0_pipeline.add_node(task=SubmitDatasetMetadata, upstreams=[CIWriteL1Frame, CIAssembleQualityData])
|
|
71
|
+
l0_pipeline.add_node(task=TransferL1Data, upstreams=[CIWriteL1Frame, AssembleCryonirspMovie])
|
|
72
|
+
l0_pipeline.add_node(
|
|
73
|
+
task=PublishCatalogAndQualityMessages, upstreams=[SubmitDatasetMetadata, TransferL1Data]
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# goodbye
|
|
77
|
+
l0_pipeline.add_node(task=Teardown, upstreams=PublishCatalogAndQualityMessages)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Cryo SP raw data processing workflow."""
|
|
2
|
+
from dkist_processing_common.tasks import PublishCatalogAndQualityMessages
|
|
3
|
+
from dkist_processing_common.tasks import QualityL1Metrics
|
|
4
|
+
from dkist_processing_common.tasks import SubmitDatasetMetadata
|
|
5
|
+
from dkist_processing_common.tasks import Teardown
|
|
6
|
+
from dkist_processing_common.tasks import TransferL0Data
|
|
7
|
+
from dkist_processing_common.tasks import TransferL1Data
|
|
8
|
+
from dkist_processing_core import ResourceQueue
|
|
9
|
+
from dkist_processing_core import Workflow
|
|
10
|
+
|
|
11
|
+
from dkist_processing_cryonirsp.tasks import AssembleCryonirspMovie
|
|
12
|
+
from dkist_processing_cryonirsp.tasks import BadPixelMapCalibration
|
|
13
|
+
from dkist_processing_cryonirsp.tasks import CryonirspL0QualityMetrics
|
|
14
|
+
from dkist_processing_cryonirsp.tasks import CryonirspL1QualityMetrics
|
|
15
|
+
from dkist_processing_cryonirsp.tasks import DarkCalibration
|
|
16
|
+
from dkist_processing_cryonirsp.tasks import LampGainCalibration
|
|
17
|
+
from dkist_processing_cryonirsp.tasks import LinearityCorrection
|
|
18
|
+
from dkist_processing_cryonirsp.tasks import MakeCryonirspMovieFrames
|
|
19
|
+
from dkist_processing_cryonirsp.tasks import ParseL0CryonirspRampData
|
|
20
|
+
from dkist_processing_cryonirsp.tasks import SPBeamBoundariesCalibration
|
|
21
|
+
from dkist_processing_cryonirsp.tasks import SPDispersionAxisCorrection
|
|
22
|
+
from dkist_processing_cryonirsp.tasks import SPGeometricCalibration
|
|
23
|
+
from dkist_processing_cryonirsp.tasks import (
|
|
24
|
+
SPInstrumentPolarizationCalibration,
|
|
25
|
+
)
|
|
26
|
+
from dkist_processing_cryonirsp.tasks import SPScienceCalibration
|
|
27
|
+
from dkist_processing_cryonirsp.tasks import SPSolarGainCalibration
|
|
28
|
+
from dkist_processing_cryonirsp.tasks import SPWriteL1Frame
|
|
29
|
+
from dkist_processing_cryonirsp.tasks.l1_output_data import SPAssembleQualityData
|
|
30
|
+
from dkist_processing_cryonirsp.tasks.parse import ParseL0CryonirspSPLinearizedData
|
|
31
|
+
|
|
32
|
+
l0_pipeline = Workflow(
|
|
33
|
+
category="cryonirsp",
|
|
34
|
+
input_data="l0",
|
|
35
|
+
output_data="l1",
|
|
36
|
+
detail="sp",
|
|
37
|
+
workflow_package=__package__,
|
|
38
|
+
)
|
|
39
|
+
l0_pipeline.add_node(task=TransferL0Data, upstreams=None)
|
|
40
|
+
|
|
41
|
+
# Science flow
|
|
42
|
+
l0_pipeline.add_node(task=ParseL0CryonirspRampData, upstreams=TransferL0Data)
|
|
43
|
+
l0_pipeline.add_node(
|
|
44
|
+
task=LinearityCorrection,
|
|
45
|
+
resource_queue=ResourceQueue.HIGH_MEMORY,
|
|
46
|
+
upstreams=ParseL0CryonirspRampData,
|
|
47
|
+
)
|
|
48
|
+
l0_pipeline.add_node(task=ParseL0CryonirspSPLinearizedData, upstreams=LinearityCorrection)
|
|
49
|
+
l0_pipeline.add_node(task=BadPixelMapCalibration, upstreams=ParseL0CryonirspSPLinearizedData)
|
|
50
|
+
l0_pipeline.add_node(task=SPBeamBoundariesCalibration, upstreams=BadPixelMapCalibration)
|
|
51
|
+
l0_pipeline.add_node(task=DarkCalibration, upstreams=SPBeamBoundariesCalibration)
|
|
52
|
+
l0_pipeline.add_node(task=LampGainCalibration, upstreams=DarkCalibration)
|
|
53
|
+
l0_pipeline.add_node(task=SPGeometricCalibration, upstreams=LampGainCalibration)
|
|
54
|
+
l0_pipeline.add_node(task=SPSolarGainCalibration, upstreams=SPGeometricCalibration)
|
|
55
|
+
l0_pipeline.add_node(task=SPDispersionAxisCorrection, upstreams=SPSolarGainCalibration)
|
|
56
|
+
l0_pipeline.add_node(task=SPInstrumentPolarizationCalibration, upstreams=SPSolarGainCalibration)
|
|
57
|
+
l0_pipeline.add_node(
|
|
58
|
+
task=SPScienceCalibration,
|
|
59
|
+
upstreams=[SPInstrumentPolarizationCalibration, SPDispersionAxisCorrection],
|
|
60
|
+
)
|
|
61
|
+
l0_pipeline.add_node(task=SPWriteL1Frame, upstreams=SPScienceCalibration)
|
|
62
|
+
|
|
63
|
+
# Movie flow
|
|
64
|
+
l0_pipeline.add_node(task=MakeCryonirspMovieFrames, upstreams=SPScienceCalibration)
|
|
65
|
+
l0_pipeline.add_node(task=AssembleCryonirspMovie, upstreams=MakeCryonirspMovieFrames)
|
|
66
|
+
|
|
67
|
+
# Quality flow
|
|
68
|
+
l0_pipeline.add_node(task=CryonirspL0QualityMetrics, upstreams=ParseL0CryonirspSPLinearizedData)
|
|
69
|
+
l0_pipeline.add_node(task=QualityL1Metrics, upstreams=SPScienceCalibration)
|
|
70
|
+
l0_pipeline.add_node(task=CryonirspL1QualityMetrics, upstreams=SPScienceCalibration)
|
|
71
|
+
l0_pipeline.add_node(
|
|
72
|
+
task=SPAssembleQualityData,
|
|
73
|
+
upstreams=[CryonirspL0QualityMetrics, QualityL1Metrics, CryonirspL1QualityMetrics],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Output flow
|
|
77
|
+
l0_pipeline.add_node(task=SubmitDatasetMetadata, upstreams=[SPWriteL1Frame, SPAssembleQualityData])
|
|
78
|
+
l0_pipeline.add_node(task=TransferL1Data, upstreams=[SPWriteL1Frame, AssembleCryonirspMovie])
|
|
79
|
+
l0_pipeline.add_node(
|
|
80
|
+
task=PublishCatalogAndQualityMessages, upstreams=[SubmitDatasetMetadata, TransferL1Data]
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# goodbye
|
|
84
|
+
l0_pipeline.add_node(task=Teardown, upstreams=PublishCatalogAndQualityMessages)
|