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
changelog/.gitempty
ADDED
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Init."""
|
|
2
|
+
from importlib.metadata import PackageNotFoundError
|
|
3
|
+
from importlib.metadata import version
|
|
4
|
+
|
|
5
|
+
from dkist_service_configuration.logging import logger # first import to set logging.BasicConfig
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
__version__ = version(distribution_name=__name__)
|
|
9
|
+
except PackageNotFoundError:
|
|
10
|
+
# package is not installed
|
|
11
|
+
__version__ = "unknown"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Configuration for the dkist-processing-cryonirsp package and the logging thereof."""
|
|
2
|
+
from dkist_processing_common.config import DKISTProcessingCommonConfiguration
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DKISTProcessingCryoNIRSPConfigurations(DKISTProcessingCommonConfiguration):
|
|
6
|
+
"""Configurations custom to the dkist-processing-cryonirsp package."""
|
|
7
|
+
|
|
8
|
+
pass # nothing custom yet
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
dkist_processing_cryonirsp_configurations = DKISTProcessingCryoNIRSPConfigurations()
|
|
12
|
+
dkist_processing_cryonirsp_configurations.log_configurations()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Init."""
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""CryoNIRSP additions to common constants."""
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from enum import unique
|
|
4
|
+
|
|
5
|
+
from dkist_processing_common.models.constants import BudName
|
|
6
|
+
from dkist_processing_common.models.constants import ConstantsBase
|
|
7
|
+
|
|
8
|
+
from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@unique
|
|
12
|
+
class CryonirspBudName(Enum):
|
|
13
|
+
"""Names to be used for CryoNIRSP buds."""
|
|
14
|
+
|
|
15
|
+
arm_id = "ARM_ID"
|
|
16
|
+
num_beams = "NUM_BEAMS"
|
|
17
|
+
num_scan_steps = "NUM_SCAN_STEPS"
|
|
18
|
+
num_map_scans = "NUM_MAP_SCANS"
|
|
19
|
+
num_modstates = "NUM_MODSTATES"
|
|
20
|
+
wavelength = "WAVELENGTH"
|
|
21
|
+
wave_min = "WAVE_MIN"
|
|
22
|
+
wave_max = "WAVE_MAX"
|
|
23
|
+
grating_position_deg = "GRATING_POSITION_DEG"
|
|
24
|
+
grating_littrow_angle_deg = "GRATING_LITTROW_ANGLE_DEG"
|
|
25
|
+
grating_constant = "GRATING_CONSTANT"
|
|
26
|
+
camera_readout_mode = "CAM_READOUT_MODE"
|
|
27
|
+
num_meas = "NUM_MEAS"
|
|
28
|
+
time_obs_list = "TIME_OBS_LIST"
|
|
29
|
+
exposure_conditions_list = "EXPOSURE_CONDITIONS_LIST"
|
|
30
|
+
dark_frame_exposure_conditions_list = "DARK_FRAME_EXPOSURE_CONDITIONS_LIST"
|
|
31
|
+
lamp_gain_exposure_conditions_list = "LAMP_GAIN_EXPOSURE_CONDITIONS_LIST"
|
|
32
|
+
solar_gain_exposure_conditions_list = "SOLAR_GAIN_EXPOSURE_CONDITIONS_LIST"
|
|
33
|
+
polcal_exposure_conditions_list = "POLCAL_EXPOSURE_CONDITIONS_LIST"
|
|
34
|
+
observe_exposure_conditions_list = "OBSERVE_EXPOSURE_CONDITIONS_LIST"
|
|
35
|
+
non_dark_and_non_polcal_task_exposure_conditions_list = (
|
|
36
|
+
"NON_DARK_AND_NON_POLCAL_TASK_EXPOSURE_CONDITIONS_LIST"
|
|
37
|
+
)
|
|
38
|
+
picky_dark_exposure_conditions_list = "PICKY_DARK_EXPOSURE_CONDITIONS_LIST"
|
|
39
|
+
modulator_spin_mode = "MODULATOR_SPIN_MODE"
|
|
40
|
+
axis_1_type = "AXIS_1_TYPE"
|
|
41
|
+
axis_2_type = "AXIS_2_TYPE"
|
|
42
|
+
axis_3_type = "AXIS_3_TYPE"
|
|
43
|
+
roi_1_origin_x = "ROI_1_ORIGIN_X"
|
|
44
|
+
roi_1_origin_y = "ROI_1_ORIGIN_Y"
|
|
45
|
+
roi_1_size_x = "ROI_1_SIZE_X"
|
|
46
|
+
roi_1_size_y = "ROI_1_SIZE_Y"
|
|
47
|
+
optical_density_filter_picky_bud = "OPTICAL_DENSITY_FILTER_PICKY_BUD"
|
|
48
|
+
solar_gain_ip_start_time = "SOLAR_GAIN_IP_START_TIME"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CryonirspConstants(ConstantsBase):
|
|
52
|
+
"""CryoNIRSP specific constants to add to the common constants."""
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def arm_id(self) -> str:
|
|
56
|
+
"""Arm used to record the data, SP or CI."""
|
|
57
|
+
return self._db_dict[CryonirspBudName.arm_id.value]
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def num_beams(self) -> int:
|
|
61
|
+
"""Determine the number of beams present in the data."""
|
|
62
|
+
if self.arm_id == "SP":
|
|
63
|
+
return 2
|
|
64
|
+
else:
|
|
65
|
+
return 1
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def num_scan_steps(self) -> int:
|
|
69
|
+
"""Determine the number of scan steps."""
|
|
70
|
+
return self._db_dict[CryonirspBudName.num_scan_steps.value]
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def num_map_scans(self) -> int:
|
|
74
|
+
"""Determine the number of scan steps."""
|
|
75
|
+
return self._db_dict[CryonirspBudName.num_map_scans.value]
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def wavelength(self) -> float:
|
|
79
|
+
"""Wavelength."""
|
|
80
|
+
return self._db_dict[CryonirspBudName.wavelength.value]
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def wave_min(self) -> float:
|
|
84
|
+
"""Wavelength minimum."""
|
|
85
|
+
return self._db_dict[CryonirspBudName.wave_min.value]
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def wave_max(self) -> float:
|
|
89
|
+
"""Wavelength maximum."""
|
|
90
|
+
return self._db_dict[CryonirspBudName.wave_max.value]
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def solar_gain_ip_start_time(self) -> str:
|
|
94
|
+
"""Solar gain IP start time."""
|
|
95
|
+
return self._db_dict[CryonirspBudName.solar_gain_ip_start_time.value]
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def grating_position_deg(self) -> float:
|
|
99
|
+
"""Grating position angle (deg)."""
|
|
100
|
+
return self._db_dict[CryonirspBudName.grating_position_deg.value]
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def grating_littrow_angle_deg(self) -> float:
|
|
104
|
+
"""Grating littrow angle (deg)."""
|
|
105
|
+
return self._db_dict[CryonirspBudName.grating_littrow_angle_deg.value]
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def grating_constant(self) -> float:
|
|
109
|
+
"""Grating constant."""
|
|
110
|
+
return self._db_dict[CryonirspBudName.grating_constant.value]
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def camera_readout_mode(self) -> str:
|
|
114
|
+
"""Determine the readout mode of the camera."""
|
|
115
|
+
return self._db_dict[CryonirspBudName.camera_readout_mode.value]
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def num_meas(self) -> int:
|
|
119
|
+
"""Determine the number of measurements in dataset."""
|
|
120
|
+
return self._db_dict[CryonirspBudName.num_meas.value]
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def time_obs_list(self) -> tuple[str]:
|
|
124
|
+
"""Construct a sorted tuple of all the dateobs for this dataset."""
|
|
125
|
+
return self._db_dict[CryonirspBudName.time_obs_list.value]
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def exposure_conditions_list(self) -> [ExposureConditions]:
|
|
129
|
+
"""Construct a list of ExposureConditions tuples for the dataset."""
|
|
130
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
131
|
+
CryonirspBudName.exposure_conditions.value
|
|
132
|
+
]
|
|
133
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
134
|
+
return conditions
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def dark_exposure_conditions_list(self) -> [ExposureConditions]:
|
|
138
|
+
"""Construct a list of dark frame ExposureConditions tuples for the dataset."""
|
|
139
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
140
|
+
CryonirspBudName.dark_frame_exposure_conditions_list.value
|
|
141
|
+
]
|
|
142
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
143
|
+
return conditions
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def lamp_gain_exposure_conditions_list(self) -> [ExposureConditions]:
|
|
147
|
+
"""Construct a list of lamp gain ExposureConditions tuples for the dataset."""
|
|
148
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
149
|
+
CryonirspBudName.lamp_gain_exposure_conditions_list.value
|
|
150
|
+
]
|
|
151
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
152
|
+
return conditions
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def solar_gain_exposure_conditions_list(self) -> [ExposureConditions]:
|
|
156
|
+
"""Construct a list of solar gain ExposureConditions tuples for the dataset."""
|
|
157
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
158
|
+
CryonirspBudName.solar_gain_exposure_conditions_list.value
|
|
159
|
+
]
|
|
160
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
161
|
+
return conditions
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def observe_exposure_conditions_list(self) -> [ExposureConditions]:
|
|
165
|
+
"""Construct a list of observe ExposureConditions tuples for the dataset."""
|
|
166
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
167
|
+
CryonirspBudName.observe_exposure_conditions_list.value
|
|
168
|
+
]
|
|
169
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
170
|
+
return conditions
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def polcal_exposure_conditions_list(self) -> [ExposureConditions]:
|
|
174
|
+
"""Construct a list of polcal ExposureConditions tuples for the dataset."""
|
|
175
|
+
if self.correct_for_polarization:
|
|
176
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
177
|
+
CryonirspBudName.polcal_exposure_conditions_list.value
|
|
178
|
+
]
|
|
179
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
180
|
+
return conditions
|
|
181
|
+
else:
|
|
182
|
+
return []
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def non_dark_and_non_polcal_task_exposure_conditions_list(self) -> [ExposureConditions]:
|
|
186
|
+
"""Return a list of all exposure times required for all tasks other than dark and polcal."""
|
|
187
|
+
raw_conditions: list[list[int, str]] = self._db_dict[
|
|
188
|
+
CryonirspBudName.non_dark_and_non_polcal_task_exposure_conditions_list.value
|
|
189
|
+
]
|
|
190
|
+
conditions = [ExposureConditions(*item) for item in raw_conditions]
|
|
191
|
+
return conditions
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def num_modstates(self) -> int:
|
|
195
|
+
"""Find the number of modulation states."""
|
|
196
|
+
return self._db_dict[CryonirspBudName.num_modstates.value]
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def num_cs_steps(self) -> int:
|
|
200
|
+
"""Find the number of calibration sequence steps."""
|
|
201
|
+
return self._db_dict[BudName.num_cs_steps.value]
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def stokes_I_list(self) -> [str]:
|
|
205
|
+
"""List containing only the Stokes-I parameter."""
|
|
206
|
+
return ["I"]
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def correct_for_polarization(self) -> bool:
|
|
210
|
+
"""Correct for polarization."""
|
|
211
|
+
return self.num_modstates > 1 and self._db_dict[
|
|
212
|
+
CryonirspBudName.modulator_spin_mode.value
|
|
213
|
+
] in ["Continuous", "Stepped"]
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def axis_1_type(self) -> str:
|
|
217
|
+
"""Find the type of the first array axis."""
|
|
218
|
+
return self._db_dict[CryonirspBudName.axis_1_type.value]
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def axis_2_type(self) -> str:
|
|
222
|
+
"""Find the type of the second array axis."""
|
|
223
|
+
return self._db_dict[CryonirspBudName.axis_2_type.value]
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def axis_3_type(self) -> str:
|
|
227
|
+
"""Find the type of the third array axis."""
|
|
228
|
+
return self._db_dict[CryonirspBudName.axis_3_type.value]
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def roi_1_origin_x(self) -> int:
|
|
232
|
+
"""Get the ROI #1 x origin."""
|
|
233
|
+
return self._db_dict[CryonirspBudName.roi_1_origin_x.value]
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def roi_1_origin_y(self) -> int:
|
|
237
|
+
"""Get the ROI #1 y origin."""
|
|
238
|
+
return self._db_dict[CryonirspBudName.roi_1_origin_y.value]
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def roi_1_size_x(self) -> int:
|
|
242
|
+
"""Get the ROI #1 x size."""
|
|
243
|
+
return self._db_dict[CryonirspBudName.roi_1_size_x.value]
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def roi_1_size_y(self) -> int:
|
|
247
|
+
"""Get the ROI #1 y size."""
|
|
248
|
+
return self._db_dict[CryonirspBudName.roi_1_size_y.value]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Support classes for exposure conditions."""
|
|
2
|
+
from collections import namedtuple
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
# Number of digits used to round the exposure when creating the ExposureConditions tuple in fits_access
|
|
6
|
+
CRYO_EXP_TIME_ROUND_DIGITS: int = 3
|
|
7
|
+
|
|
8
|
+
"""Base class to hold a tuple of exposure time and filter name."""
|
|
9
|
+
ExposureConditionsBase = namedtuple("ExposureConditions", ["exposure_time", "filter_name"])
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ExposureConditions(ExposureConditionsBase):
|
|
13
|
+
"""Define str to make tags look reasonable."""
|
|
14
|
+
|
|
15
|
+
def __str__(self):
|
|
16
|
+
return f"{self.exposure_time}_{self.filter_name}"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AllowableOpticalDensityFilterNames(StrEnum):
|
|
20
|
+
"""Enum to implement list of allowable Optical Density Filter names."""
|
|
21
|
+
|
|
22
|
+
G278 = "G278"
|
|
23
|
+
G358 = "G358"
|
|
24
|
+
G408 = "G408"
|
|
25
|
+
OPEN = "OPEN"
|
|
26
|
+
NONE = "NONE"
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""CryoNIRSP calibration pipeline parameters."""
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
|
|
5
|
+
import astropy.units as u
|
|
6
|
+
import numpy as np
|
|
7
|
+
from dkist_processing_common.models.parameters import ParameterArmIdMixin
|
|
8
|
+
from dkist_processing_common.models.parameters import ParameterBase
|
|
9
|
+
from dkist_processing_common.models.parameters import ParameterWavelengthMixin
|
|
10
|
+
from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetMixin
|
|
11
|
+
|
|
12
|
+
from dkist_processing_cryonirsp.models.exposure_conditions import AllowableOpticalDensityFilterNames
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CryonirspParsingParameters(ParameterBase):
|
|
16
|
+
"""
|
|
17
|
+
Parameters specifically (and only) for the Parse task.
|
|
18
|
+
|
|
19
|
+
Needed because the Parse task doesn't yet know about arm id, wavelength, or obs_ip_start_time, which are all
|
|
20
|
+
required to initialize the main parameter class.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def max_cs_step_time_sec(self):
|
|
25
|
+
"""Time window within which CS steps with identical GOS configurations are considered to be the same."""
|
|
26
|
+
return self._find_most_recent_past_value(
|
|
27
|
+
"cryonirsp_max_cs_step_time_sec", start_date=datetime.now()
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CryonirspParameters(ParameterBase, ParameterWavelengthMixin, ParameterArmIdMixin):
|
|
32
|
+
"""Put all CryoNIRSP parameters parsed from the input dataset document in a single property."""
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def geo_upsample_factor(self) -> int:
|
|
36
|
+
"""Pixel precision (1/upsample_factor) to use during phase matching of beam/modulator images."""
|
|
37
|
+
return self._find_most_recent_past_value("cryonirsp_geo_upsample_factor")
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def geo_max_shift(self) -> int:
|
|
41
|
+
"""Max allowed pixel shift when computing spectral curvature."""
|
|
42
|
+
return self._find_most_recent_past_value("cryonirsp_geo_max_shift")
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def geo_poly_fit_order(self) -> int:
|
|
46
|
+
"""Order of polynomial used to fit spectral shift as a function of slit position."""
|
|
47
|
+
return self._find_most_recent_past_value("cryonirsp_geo_poly_fit_order")
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def geo_long_axis_gradient_displacement(self) -> int:
|
|
51
|
+
"""Number of pixels to shift along the long axis of a strip when computing a gradient."""
|
|
52
|
+
return self._find_most_recent_past_value("cryonirsp_geo_long_axis_gradient_displacement")
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def geo_strip_long_axis_size_fraction(self) -> float:
|
|
56
|
+
"""Fraction of full array size for the long axis of the strips used to find the beam angle."""
|
|
57
|
+
return self._find_most_recent_past_value("cryonirsp_geo_strip_long_axis_size_fraction")
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def geo_strip_short_axis_size_fraction(self) -> float:
|
|
61
|
+
"""Fraction of full array size for the short axis of the strips used to find the beam angle."""
|
|
62
|
+
return self._find_most_recent_past_value("cryonirsp_geo_strip_short_axis_size_fraction")
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def geo_strip_spectral_offset_size_fraction(self) -> float:
|
|
66
|
+
"""Fraction of full spectral size to set as the +/- offset from spectral center for the two strips used to find the beam angle."""
|
|
67
|
+
return self._find_most_recent_past_value(
|
|
68
|
+
"cryonirsp_geo_strip_spectral_offset_size_fraction"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def polcal_num_spectral_bins(self) -> int:
|
|
73
|
+
"""Return Number of demodulation matrices to compute across the entire FOV in the spectral dimension."""
|
|
74
|
+
return self._find_most_recent_past_value("cryonirsp_polcal_num_spectral_bins")
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def polcal_num_spatial_bins(self) -> int:
|
|
78
|
+
"""Return Number of demodulation matrices to compute across the entire FOV in the spatial dimension."""
|
|
79
|
+
return self._find_most_recent_past_value("cryonirsp_polcal_num_spatial_bins")
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def polcal_pac_fit_mode(self):
|
|
83
|
+
"""Name of set of fitting flags to use during PAC Calibration Unit parameter fits."""
|
|
84
|
+
return self._find_most_recent_past_value("cryonirsp_polcal_pac_fit_mode")
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def polcal_pac_init_set(self):
|
|
88
|
+
"""Name of set of initial values for Calibration Unit parameter fit."""
|
|
89
|
+
return self._find_most_recent_past_value("cryonirsp_polcal_pac_init_set")
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def beam_boundaries_smoothing_disk_size(self) -> int:
|
|
93
|
+
"""Return the size of the smoothing disk (in pixels) to be used in the beam boundaries computation."""
|
|
94
|
+
return self._find_most_recent_past_value("cryonirsp_beam_boundaries_smoothing_disk_size")
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def beam_boundaries_upsample_factor(self) -> int:
|
|
98
|
+
"""Return the upsample factor to be used in the beam boundaries cross correlation computation."""
|
|
99
|
+
return self._find_most_recent_past_value("cryonirsp_beam_boundaries_upsample_factor")
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def beam_boundaries_sp_beam_transition_region_size_fraction(self) -> float:
|
|
103
|
+
"""
|
|
104
|
+
Fraction of full spectral size to use as the size of the transition region between the two SP beams.
|
|
105
|
+
|
|
106
|
+
A region with size = (this parameter * full spectral size) and centered at the center of the spectral dimension
|
|
107
|
+
will be ignored when extracting the beams.
|
|
108
|
+
"""
|
|
109
|
+
return self._find_most_recent_past_value(
|
|
110
|
+
"cryonirsp_beam_boundaries_sp_beam_transition_region_size_fraction"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def bad_pixel_map_median_filter_size(self) -> list[int, int]:
|
|
115
|
+
"""Return the smoothing disk size to be used in the bad pixel map computation."""
|
|
116
|
+
filter_size = self._find_parameter_for_arm("cryonirsp_bad_pixel_map_median_filter_size")
|
|
117
|
+
return filter_size
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def bad_pixel_map_threshold_factor(self) -> float:
|
|
121
|
+
"""Return the threshold multiplicative factor to be used in the bad pixel map computation."""
|
|
122
|
+
return self._find_most_recent_past_value("cryonirsp_bad_pixel_map_threshold_factor")
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def corrections_bad_pixel_median_filter_size(self) -> int:
|
|
126
|
+
"""Return the size of the median filter to be used for bad pixel correction."""
|
|
127
|
+
return self._find_most_recent_past_value(
|
|
128
|
+
"cryonirsp_corrections_bad_pixel_median_filter_size"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@cached_property
|
|
132
|
+
def corrections_bad_pixel_fraction_threshold(self) -> float:
|
|
133
|
+
"""
|
|
134
|
+
Return the fraction of the bad pixel mask.
|
|
135
|
+
|
|
136
|
+
If exceeded, will cause the fallback to a faster but worse algorithm.
|
|
137
|
+
"""
|
|
138
|
+
return self._find_most_recent_past_value(
|
|
139
|
+
"cryonirsp_corrections_bad_pixel_fraction_threshold"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
@cached_property
|
|
143
|
+
def linearization_thresholds(self) -> np.ndarray:
|
|
144
|
+
"""Name of parameter associated with the linearization thresholds."""
|
|
145
|
+
param_dict = self._find_parameter_for_arm("cryonirsp_linearization_thresholds")
|
|
146
|
+
value = self._load_param_value_from_numpy_save(param_dict)
|
|
147
|
+
# float64 data can blow up the memory required for linearization - convert to float32
|
|
148
|
+
if np.issubdtype(value.dtype, np.float64):
|
|
149
|
+
value = value.astype(np.float32, casting="same_kind")
|
|
150
|
+
return value
|
|
151
|
+
|
|
152
|
+
@cached_property
|
|
153
|
+
def linearization_polyfit_coeffs(self) -> np.ndarray:
|
|
154
|
+
"""Name of parameter associated with the linearization polyfit coefficients."""
|
|
155
|
+
param_value = self._find_parameter_for_arm("cryonirsp_linearization_polyfit_coeffs")
|
|
156
|
+
return np.asarray(param_value, dtype=np.float32)
|
|
157
|
+
|
|
158
|
+
@cached_property
|
|
159
|
+
def linearization_max_memory_gb(self) -> float:
|
|
160
|
+
"""Get the maximum amount of memory in GB available to the linearity correction task worker."""
|
|
161
|
+
mem_size = self._find_most_recent_past_value("cryonirsp_linearization_max_memory_gb")
|
|
162
|
+
return mem_size
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def solar_characteristic_spatial_normalization_percentile(self) -> float:
|
|
166
|
+
"""Percentile to pass to `np.nanpercentile` when normalizing each spatial position of the characteristic spectra."""
|
|
167
|
+
return self._find_most_recent_past_value(
|
|
168
|
+
"cryonirsp_solar_characteristic_spatial_normalization_percentile"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def fringe_correction_on(self) -> bool:
|
|
173
|
+
"""Return True if fringe correction should be performed."""
|
|
174
|
+
return self._find_most_recent_past_value(
|
|
175
|
+
"cryonirsp_fringe_correction_on",
|
|
176
|
+
start_date=self._obs_ip_start_datetime,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def fringe_correction_spectral_filter_size(self) -> list[int, int]:
|
|
181
|
+
"""Get the filter kernel size for the spectral filtering in the fringe removal process."""
|
|
182
|
+
return self._find_most_recent_past_value("cryonirsp_fringe_correction_spectral_filter_size")
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def fringe_correction_spatial_filter_size(self) -> list[int, int]:
|
|
186
|
+
"""Get the filter kernel size for the spatial filtering in the fringe removal process."""
|
|
187
|
+
return self._find_most_recent_past_value("cryonirsp_fringe_correction_spatial_filter_size")
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def fringe_correction_lowpass_cutoff_period(self) -> float:
|
|
191
|
+
"""Get the lowpass filter cutoff period in pixels for the fringe removal process."""
|
|
192
|
+
return self._find_most_recent_past_value(
|
|
193
|
+
"cryonirsp_fringe_correction_lowpass_cutoff_period"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
@cached_property
|
|
197
|
+
def linearization_filter_attenuation_dict(self) -> dict:
|
|
198
|
+
"""Return a dict that maps the filter name to its attenuation parameter."""
|
|
199
|
+
filter_attenuation_dict = {
|
|
200
|
+
AllowableOpticalDensityFilterNames.G278.value: self._linearization_optical_density_filter_attenuation_g278,
|
|
201
|
+
AllowableOpticalDensityFilterNames.G358.value: self._linearization_optical_density_filter_attenuation_g358,
|
|
202
|
+
AllowableOpticalDensityFilterNames.G408.value: self._linearization_optical_density_filter_attenuation_g408,
|
|
203
|
+
AllowableOpticalDensityFilterNames.OPEN.value: self._linearization_optical_density_filter_attenuation_open,
|
|
204
|
+
AllowableOpticalDensityFilterNames.NONE.value: self._linearization_optical_density_filter_attenuation_none,
|
|
205
|
+
}
|
|
206
|
+
return filter_attenuation_dict
|
|
207
|
+
|
|
208
|
+
@cached_property
|
|
209
|
+
def _linearization_optical_density_filter_attenuation_g278(self) -> float:
|
|
210
|
+
"""Return the attenuation value for the G278 filter."""
|
|
211
|
+
return self._find_parameter_closest_wavelength(
|
|
212
|
+
"cryonirsp_linearization_optical_density_filter_attenuation_g278"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@cached_property
|
|
216
|
+
def _linearization_optical_density_filter_attenuation_g358(self) -> float:
|
|
217
|
+
"""Return the attenuation value for the G358 filter."""
|
|
218
|
+
return self._find_parameter_closest_wavelength(
|
|
219
|
+
"cryonirsp_linearization_optical_density_filter_attenuation_g358"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
@cached_property
|
|
223
|
+
def _linearization_optical_density_filter_attenuation_g408(self) -> float:
|
|
224
|
+
"""Return the attenuation value for the G408 filter."""
|
|
225
|
+
return self._find_parameter_closest_wavelength(
|
|
226
|
+
"cryonirsp_linearization_optical_density_filter_attenuation_g408"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
@cached_property
|
|
230
|
+
def _linearization_optical_density_filter_attenuation_none(self) -> float:
|
|
231
|
+
"""Return the attenuation value for a filter of 'none'."""
|
|
232
|
+
return 0.0
|
|
233
|
+
|
|
234
|
+
@cached_property
|
|
235
|
+
def _linearization_optical_density_filter_attenuation_open(self) -> float:
|
|
236
|
+
"""Return the attenuation value for a filter of 'Open'."""
|
|
237
|
+
return 0.0
|
|
238
|
+
|
|
239
|
+
@property
|
|
240
|
+
def cryo_instrument_alignment_angle(self) -> u.Quantity:
|
|
241
|
+
"""Return the CryoNIRSP instrument alignment angle."""
|
|
242
|
+
alignment_angle = -91.0 * u.deg
|
|
243
|
+
return alignment_angle
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def ci_spatial_scale_along_slit(self) -> u.Quantity:
|
|
247
|
+
"""Return the CryoNIRSP CI spatial scale along the slit."""
|
|
248
|
+
spatial_scale_along_slit = 0.05308 * u.arcsec / u.pix
|
|
249
|
+
return spatial_scale_along_slit
|
|
250
|
+
|
|
251
|
+
@property
|
|
252
|
+
def sp_spatial_scale_along_slit(self) -> u.Quantity:
|
|
253
|
+
"""Return the CryoNIRSP SP spatial scale along the slit."""
|
|
254
|
+
spatial_scale_along_slit = 0.12 * u.arcsec / u.pix
|
|
255
|
+
return spatial_scale_along_slit
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def mirror_scan_recalibration_constant(self) -> float:
|
|
259
|
+
"""Return the CryoNIRSP mirror scan recalibration constant."""
|
|
260
|
+
mirror_scan_recalibration_constant = 0.466 / 0.5
|
|
261
|
+
return mirror_scan_recalibration_constant
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def camera_mirror_focal_length_mm(self) -> u.Quantity:
|
|
265
|
+
"""Return the CryoNIRSP camera mirror focal length."""
|
|
266
|
+
return (
|
|
267
|
+
self._find_most_recent_past_value("cryonirsp_camera_mirror_focal_length_mm")
|
|
268
|
+
* u.millimeter
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def pixel_pitch_micron(self) -> u.Quantity:
|
|
273
|
+
"""Return the CryoNIRSP pixel pitch."""
|
|
274
|
+
return self._find_most_recent_past_value("cryonirsp_pixel_pitch_micron") * u.micron
|
|
275
|
+
|
|
276
|
+
@cached_property
|
|
277
|
+
def solar_atlas(self) -> np.ndarray:
|
|
278
|
+
"""Solar reference atlas.
|
|
279
|
+
|
|
280
|
+
Contains two arrays:
|
|
281
|
+
- wavelength in nanometers
|
|
282
|
+
- transmission at given wavelength
|
|
283
|
+
"""
|
|
284
|
+
param_dict = self._find_most_recent_past_value("cryonirsp_solar_atlas")
|
|
285
|
+
return self._load_param_value_from_numpy_save(param_dict)
|
|
286
|
+
|
|
287
|
+
@cached_property
|
|
288
|
+
def telluric_atlas(self) -> np.ndarray:
|
|
289
|
+
"""Telluric reference atlas.
|
|
290
|
+
|
|
291
|
+
Contains two arrays:
|
|
292
|
+
- wavelength in nanometers
|
|
293
|
+
- transmission at given wavelength
|
|
294
|
+
"""
|
|
295
|
+
param_dict = self._find_most_recent_past_value("cryonirsp_telluric_atlas")
|
|
296
|
+
return self._load_param_value_from_numpy_save(param_dict)
|