dkist-processing-cryonirsp 1.4.15__py3-none-any.whl → 1.4.16rc1__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/170.feature.rst +11 -0
- changelog/170.misc.1.rst +2 -0
- changelog/170.misc.rst +3 -0
- changelog/174.bugfix.rst +1 -0
- dkist_processing_cryonirsp/codecs/__init__.py +5 -0
- dkist_processing_cryonirsp/codecs/fits.py +52 -0
- dkist_processing_cryonirsp/models/beam_boundaries.py +39 -0
- dkist_processing_cryonirsp/models/parameters.py +0 -1
- dkist_processing_cryonirsp/models/tags.py +34 -0
- dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py +38 -2
- dkist_processing_cryonirsp/tasks/assemble_movie.py +2 -2
- dkist_processing_cryonirsp/tasks/bad_pixel_map.py +14 -9
- dkist_processing_cryonirsp/tasks/beam_boundaries_base.py +24 -43
- dkist_processing_cryonirsp/tasks/ci_beam_boundaries.py +1 -1
- dkist_processing_cryonirsp/tasks/ci_science.py +24 -6
- dkist_processing_cryonirsp/tasks/cryonirsp_base.py +0 -10
- dkist_processing_cryonirsp/tasks/dark.py +34 -14
- dkist_processing_cryonirsp/tasks/gain.py +69 -22
- dkist_processing_cryonirsp/tasks/instrument_polarization.py +131 -49
- dkist_processing_cryonirsp/tasks/l1_output_data.py +0 -1
- dkist_processing_cryonirsp/tasks/linearity_correction.py +4 -7
- dkist_processing_cryonirsp/tasks/make_movie_frames.py +5 -5
- dkist_processing_cryonirsp/tasks/quality_metrics.py +4 -4
- dkist_processing_cryonirsp/tasks/science_base.py +34 -10
- dkist_processing_cryonirsp/tasks/sp_beam_boundaries.py +1 -1
- dkist_processing_cryonirsp/tasks/sp_dispersion_axis_correction.py +14 -6
- dkist_processing_cryonirsp/tasks/sp_geometric.py +112 -39
- dkist_processing_cryonirsp/tasks/sp_science.py +53 -11
- dkist_processing_cryonirsp/tasks/sp_solar_gain.py +108 -29
- dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py +2 -10
- dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py +8 -11
- dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py +1 -1
- dkist_processing_cryonirsp/tests/test_bad_pixel_maps.py +1 -2
- dkist_processing_cryonirsp/tests/test_ci_beam_boundaries.py +6 -5
- dkist_processing_cryonirsp/tests/test_ci_science.py +25 -24
- dkist_processing_cryonirsp/tests/test_cryo_base.py +41 -43
- dkist_processing_cryonirsp/tests/test_dark.py +20 -28
- dkist_processing_cryonirsp/tests/test_gain.py +46 -35
- dkist_processing_cryonirsp/tests/test_instrument_polarization.py +22 -16
- dkist_processing_cryonirsp/tests/test_linearity_correction.py +1 -4
- dkist_processing_cryonirsp/tests/test_quality.py +1 -2
- dkist_processing_cryonirsp/tests/test_sp_beam_boundaries.py +6 -5
- dkist_processing_cryonirsp/tests/test_sp_dispersion_axis_correction.py +10 -9
- dkist_processing_cryonirsp/tests/test_sp_geometric.py +108 -53
- dkist_processing_cryonirsp/tests/test_sp_science.py +49 -35
- dkist_processing_cryonirsp/tests/test_sp_solar.py +70 -38
- {dkist_processing_cryonirsp-1.4.15.dist-info → dkist_processing_cryonirsp-1.4.16rc1.dist-info}/METADATA +2 -2
- {dkist_processing_cryonirsp-1.4.15.dist-info → dkist_processing_cryonirsp-1.4.16rc1.dist-info}/RECORD +50 -46
- dkist_processing_cryonirsp/tasks/mixin/beam_access.py +0 -52
- dkist_processing_cryonirsp/tasks/mixin/intermediate_frame.py +0 -193
- dkist_processing_cryonirsp/tasks/mixin/linearized_frame.py +0 -309
- {dkist_processing_cryonirsp-1.4.15.dist-info → dkist_processing_cryonirsp-1.4.16rc1.dist-info}/WHEEL +0 -0
- {dkist_processing_cryonirsp-1.4.15.dist-info → dkist_processing_cryonirsp-1.4.16rc1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Remove read/write mixins for tasks: intermediate frame, linearized frame, and beam access.
|
|
2
|
+
The functionality of those mixins is replaced with the standard read and write methods
|
|
3
|
+
from `dkist-processing-common` and three new elements:
|
|
4
|
+
|
|
5
|
+
* New composite tags for intermediate frames, linearized frames, and beam boundary data.
|
|
6
|
+
* New `cryo_fits_access_decoder` and `cryo_fits_array_decoder` that replace the standard decoders
|
|
7
|
+
from `dkist-processing-common`. The new decoders optionally slice out the illuminated beam
|
|
8
|
+
portion of the array and take optional `fits_access_class` arguments.
|
|
9
|
+
* New `CryonirspLinearizedFitsAccess` fits access class that inherits from CryonirspL0FitsAccess
|
|
10
|
+
and handles flipping the dispersion axis for the SP arm so that wavelength increases from left
|
|
11
|
+
to right like the other instruments.
|
changelog/170.misc.1.rst
ADDED
changelog/170.misc.rst
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Use the existing BeamBoundaries dataclass and new intermediate_beam_boundaries composite tag with
|
|
2
|
+
standard read methods to access beam boundaries where beam slicing is necessary. BeamBoundary objects
|
|
3
|
+
are passed to new decoders to access the illuminated beam portion of the array.
|
changelog/174.bugfix.rst
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Remove the lamp gain task from CI local workflows.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Encoders and decoders for writing and reading Cryo-NIRSP FITS files."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
from dkist_processing_common.codecs.fits import fits_access_decoder as common_fits_access_decoder
|
|
6
|
+
from dkist_processing_common.models.fits_access import FitsAccessBase
|
|
7
|
+
|
|
8
|
+
from dkist_processing_cryonirsp.models.beam_boundaries import BeamBoundary
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def cryo_fits_access_decoder(
|
|
12
|
+
path: Path,
|
|
13
|
+
fits_access_class: FitsAccessBase = FitsAccessBase,
|
|
14
|
+
beam_boundary: BeamBoundary | None = None,
|
|
15
|
+
**fits_access_kwargs,
|
|
16
|
+
) -> FitsAccessBase:
|
|
17
|
+
"""
|
|
18
|
+
Read a Path with `fits`, ingest into a `FitsAccessBase`-type object, then slice out the beam.
|
|
19
|
+
|
|
20
|
+
Cryo-specific replacement for method from `dkist-processing-common` with the same name.
|
|
21
|
+
"""
|
|
22
|
+
frame = common_fits_access_decoder(
|
|
23
|
+
path, fits_access_class=fits_access_class, **fits_access_kwargs
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if beam_boundary is not None:
|
|
27
|
+
frame.data = frame.data[beam_boundary.slices]
|
|
28
|
+
|
|
29
|
+
return frame
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def cryo_fits_array_decoder(
|
|
33
|
+
path: Path,
|
|
34
|
+
fits_access_class: FitsAccessBase = FitsAccessBase,
|
|
35
|
+
beam_boundary: BeamBoundary | None = None,
|
|
36
|
+
auto_squeeze: bool = True,
|
|
37
|
+
**fits_access_kwargs,
|
|
38
|
+
) -> np.array:
|
|
39
|
+
"""
|
|
40
|
+
Read a Path with `fits` and return the `.data` from `fits_access_decoder`.
|
|
41
|
+
|
|
42
|
+
Cryo-specific replacement for method from `dkist-processing-common` with the same name.
|
|
43
|
+
Unlike the version in `-common`, this method allows a fits_access_class parameter.
|
|
44
|
+
"""
|
|
45
|
+
frame = cryo_fits_access_decoder(
|
|
46
|
+
path,
|
|
47
|
+
fits_access_class=fits_access_class,
|
|
48
|
+
beam_boundary=beam_boundary,
|
|
49
|
+
auto_squeeze=auto_squeeze,
|
|
50
|
+
**fits_access_kwargs,
|
|
51
|
+
)
|
|
52
|
+
return frame.data
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Beam boundary class."""
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class BeamBoundary:
|
|
9
|
+
"""Simple dataclass to hold boundary information for the illuminated portion of the beam array."""
|
|
10
|
+
|
|
11
|
+
y_min: int
|
|
12
|
+
y_max: int
|
|
13
|
+
x_min: int
|
|
14
|
+
x_max: int
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def y_slice(self):
|
|
18
|
+
"""Return a slice object representing the illumination along the y-axis (numpy 0 axis)."""
|
|
19
|
+
return slice(self.y_min, self.y_max)
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def x_slice(self):
|
|
23
|
+
"""Return a slice object representing the illumination along the x-axis (numpy 1 axis)."""
|
|
24
|
+
return slice(self.x_min, self.x_max)
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def slices(self):
|
|
28
|
+
"""Return a tuple of slices in numpy order representing the illuminated portion of the beam array."""
|
|
29
|
+
return self.y_slice, self.x_slice
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def beam_boundaries(self):
|
|
33
|
+
"""Return a tuple containing the beam boundaries."""
|
|
34
|
+
return self.y_min, self.y_max, self.x_min, self.x_max
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def beam_boundaries_array(self):
|
|
38
|
+
"""Return a tuple containing the beam boundaries."""
|
|
39
|
+
return np.array(self.beam_boundaries)
|
|
@@ -7,7 +7,6 @@ import numpy as np
|
|
|
7
7
|
from dkist_processing_common.models.parameters import ParameterArmIdMixin
|
|
8
8
|
from dkist_processing_common.models.parameters import ParameterBase
|
|
9
9
|
from dkist_processing_common.models.parameters import ParameterWavelengthMixin
|
|
10
|
-
from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetMixin
|
|
11
10
|
|
|
12
11
|
from dkist_processing_cryonirsp.models.exposure_conditions import AllowableOpticalDensityFilterNames
|
|
13
12
|
|
|
@@ -166,3 +166,37 @@ class CryonirspTag(Tag):
|
|
|
166
166
|
def task_characteristic_spectra(cls) -> str:
|
|
167
167
|
"""Tags 1D intermediate characteristic spectra."""
|
|
168
168
|
return cls.format_tag(StemName.task, CryonirspTaskName.solar_char_spec.value)
|
|
169
|
+
|
|
170
|
+
##################
|
|
171
|
+
# COMPOSITE TAGS #
|
|
172
|
+
##################
|
|
173
|
+
@classmethod
|
|
174
|
+
def intermediate_frame(
|
|
175
|
+
cls, beam: int | None = None, exposure_conditions: ExposureConditions | None = None
|
|
176
|
+
) -> list[str]:
|
|
177
|
+
"""Tag by intermediate and frame, and optionally by beam and exposure_conditions."""
|
|
178
|
+
tag_list = [cls.intermediate(), cls.frame()]
|
|
179
|
+
if beam is not None:
|
|
180
|
+
tag_list += [cls.beam(beam)]
|
|
181
|
+
if exposure_conditions is not None:
|
|
182
|
+
tag_list += [cls.exposure_conditions(exposure_conditions)]
|
|
183
|
+
return tag_list
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def linearized_frame(
|
|
187
|
+
cls, beam: int | None = None, exposure_conditions: ExposureConditions | None = None
|
|
188
|
+
) -> list[str]:
|
|
189
|
+
"""Tag by linearized, by frame, by beam, and optionally by exposure_conditions."""
|
|
190
|
+
tag_list = [cls.linearized(), cls.frame()]
|
|
191
|
+
if beam is not None:
|
|
192
|
+
tag_list += [cls.beam(beam)]
|
|
193
|
+
if exposure_conditions is not None:
|
|
194
|
+
tag_list += [cls.exposure_conditions(exposure_conditions)]
|
|
195
|
+
return tag_list
|
|
196
|
+
|
|
197
|
+
@classmethod
|
|
198
|
+
def intermediate_beam_boundaries(cls, beam: int) -> list[str]:
|
|
199
|
+
"""Tag list for retrieving beam boundaries."""
|
|
200
|
+
tag_list = cls.intermediate_frame(beam=beam)
|
|
201
|
+
tag_list += [cls.task_beam_boundaries()]
|
|
202
|
+
return tag_list
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""CryoNIRSP FITS access for L0 data."""
|
|
2
|
+
import numpy as np
|
|
2
3
|
from astropy.io import fits
|
|
3
4
|
from dkist_processing_common.parsers.l0_fits_access import L0FitsAccess
|
|
4
5
|
|
|
@@ -8,7 +9,7 @@ from dkist_processing_cryonirsp.models.exposure_conditions import ExposureCondit
|
|
|
8
9
|
|
|
9
10
|
class CryonirspRampFitsAccess(L0FitsAccess):
|
|
10
11
|
"""
|
|
11
|
-
Class to provide easy access to L0 headers for non-linearized (raw)
|
|
12
|
+
Class to provide easy access to L0 headers for non-linearized (raw) files.
|
|
12
13
|
|
|
13
14
|
i.e. instead of <CryonirspL0FitsAccess>.header['key'] this class lets us use <CryonirspL0FitsAccess>.key instead
|
|
14
15
|
|
|
@@ -46,7 +47,7 @@ class CryonirspRampFitsAccess(L0FitsAccess):
|
|
|
46
47
|
|
|
47
48
|
class CryonirspL0FitsAccess(L0FitsAccess):
|
|
48
49
|
"""
|
|
49
|
-
Class to provide easy access to L0 headers for linearized (ready for processing)
|
|
50
|
+
Class to provide easy access to L0 headers for linearized (ready for processing) files.
|
|
50
51
|
|
|
51
52
|
i.e. instead of <CryonirspL0FitsAccess>.header['key'] this class lets us use <CryonirspL0FitsAccess>.key instead
|
|
52
53
|
|
|
@@ -110,3 +111,38 @@ class CryonirspL0FitsAccess(L0FitsAccess):
|
|
|
110
111
|
def cn1_scan_step(self):
|
|
111
112
|
"""Convert the inner loop step number from float to int."""
|
|
112
113
|
return int(self.header["CNP1DCUR"])
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class CryonirspLinearizedFitsAccess(CryonirspL0FitsAccess):
|
|
117
|
+
"""
|
|
118
|
+
Class to access to linearized CryoNIRSP data.
|
|
119
|
+
|
|
120
|
+
Flip the dispersion axis of the SP arm.
|
|
121
|
+
Cryo's wavelength decreases from left to right, so we flip it here to match the other instruments.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
hdu :
|
|
126
|
+
Fits L0 header object
|
|
127
|
+
|
|
128
|
+
name : str
|
|
129
|
+
The name of the file that was loaded into this FitsAccess object
|
|
130
|
+
|
|
131
|
+
auto_squeeze : bool
|
|
132
|
+
When set to True, dimensions of length 1 will be removed from the array
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def data(self):
|
|
137
|
+
"""Override parent method to flip the SP arm array."""
|
|
138
|
+
parent_data = super().data
|
|
139
|
+
if self.arm_id == "SP":
|
|
140
|
+
return np.flip(parent_data, 1)
|
|
141
|
+
return parent_data
|
|
142
|
+
|
|
143
|
+
@data.setter
|
|
144
|
+
def data(self, value: np.array):
|
|
145
|
+
"""Override parent setter method to unflip the SP arm array."""
|
|
146
|
+
if self.arm_id == "SP":
|
|
147
|
+
value = np.flip(value, 1)
|
|
148
|
+
super(CryonirspL0FitsAccess, type(self)).data.__set__(self, value)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"""CryoNIRSP-specific assemble movie task subclass."""
|
|
2
2
|
import numpy as np
|
|
3
|
-
from dkist_processing_common.codecs.fits import fits_array_decoder
|
|
4
3
|
from dkist_processing_common.tasks import AssembleMovie
|
|
5
4
|
from dkist_service_configuration.logging import logger
|
|
6
5
|
from PIL import ImageDraw
|
|
7
6
|
from PIL.ImageFont import FreeTypeFont
|
|
8
7
|
|
|
8
|
+
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_array_decoder
|
|
9
9
|
from dkist_processing_cryonirsp.models.constants import CryonirspConstants
|
|
10
10
|
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
11
11
|
from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import CryonirspL0FitsAccess
|
|
@@ -36,7 +36,7 @@ class AssembleCryonirspMovieBase(AssembleMovie):
|
|
|
36
36
|
def compute_frame_shape(self) -> tuple[int, int]:
|
|
37
37
|
"""Dynamically set the dimensions of the movie based on L1 file shape."""
|
|
38
38
|
movie_frame_arrays = self.read(
|
|
39
|
-
tags=[CryonirspTag.movie_frame()], decoder=
|
|
39
|
+
tags=[CryonirspTag.movie_frame()], decoder=cryo_fits_array_decoder
|
|
40
40
|
)
|
|
41
41
|
random_frame = next(movie_frame_arrays)
|
|
42
42
|
raw_L1_shape = random_frame.shape
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"""Task class for bad pixel map computation."""
|
|
2
2
|
import numpy as np
|
|
3
3
|
import scipy.ndimage as spnd
|
|
4
|
+
from dkist_processing_common.codecs.fits import fits_array_encoder
|
|
4
5
|
from dkist_processing_math.statistics import average_numpy_arrays
|
|
5
6
|
from dkist_service_configuration.logging import logger
|
|
6
7
|
|
|
8
|
+
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_array_decoder
|
|
7
9
|
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
8
|
-
from dkist_processing_cryonirsp.
|
|
10
|
+
from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import (
|
|
11
|
+
CryonirspLinearizedFitsAccess,
|
|
12
|
+
)
|
|
9
13
|
from dkist_processing_cryonirsp.tasks.cryonirsp_base import CryonirspTaskBase
|
|
10
14
|
|
|
11
15
|
__all__ = ["BadPixelMapCalibration"]
|
|
@@ -68,8 +72,10 @@ class BadPixelMapCalibration(CryonirspTaskBase):
|
|
|
68
72
|
bad_pixel_map[zeros] = 1
|
|
69
73
|
|
|
70
74
|
with self.apm_writing_step("Writing bad pixel map"):
|
|
71
|
-
self.
|
|
72
|
-
bad_pixel_map,
|
|
75
|
+
self.write(
|
|
76
|
+
data=bad_pixel_map,
|
|
77
|
+
tags=[CryonirspTag.intermediate_frame(), CryonirspTag.task_bad_pixel_map()],
|
|
78
|
+
encoder=fits_array_encoder,
|
|
73
79
|
)
|
|
74
80
|
|
|
75
81
|
def compute_average_gain_array(self) -> np.ndarray:
|
|
@@ -85,12 +91,11 @@ class BadPixelMapCalibration(CryonirspTaskBase):
|
|
|
85
91
|
-------
|
|
86
92
|
The average gain array
|
|
87
93
|
"""
|
|
88
|
-
lin_corr_gain_arrays = self.
|
|
89
|
-
tags=[
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
CryonirspTag.frame(),
|
|
93
|
-
]
|
|
94
|
+
lin_corr_gain_arrays = self.read(
|
|
95
|
+
tags=[CryonirspTag.linearized_frame(), CryonirspTag.task_solar_gain()],
|
|
96
|
+
decoder=cryo_fits_array_decoder,
|
|
97
|
+
fits_access_class=CryonirspLinearizedFitsAccess,
|
|
94
98
|
)
|
|
99
|
+
|
|
95
100
|
averaged_gain_data = average_numpy_arrays(lin_corr_gain_arrays)
|
|
96
101
|
return averaged_gain_data
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""CryoNIRSP compute beam boundary task."""
|
|
2
2
|
from abc import abstractmethod
|
|
3
|
-
from dataclasses import dataclass
|
|
4
3
|
|
|
5
4
|
import numpy as np
|
|
5
|
+
from dkist_processing_common.codecs.fits import fits_array_encoder
|
|
6
6
|
from dkist_processing_math.statistics import average_numpy_arrays
|
|
7
7
|
from dkist_service_configuration.logging import logger
|
|
8
8
|
from largestinteriorrectangle import lir
|
|
@@ -11,40 +11,15 @@ from skimage.exposure import rescale_intensity
|
|
|
11
11
|
from skimage.morphology import disk
|
|
12
12
|
from skimage.util import img_as_ubyte
|
|
13
13
|
|
|
14
|
+
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_array_decoder
|
|
15
|
+
from dkist_processing_cryonirsp.models.beam_boundaries import BeamBoundary
|
|
14
16
|
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
17
|
+
from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import (
|
|
18
|
+
CryonirspLinearizedFitsAccess,
|
|
19
|
+
)
|
|
15
20
|
from dkist_processing_cryonirsp.tasks.cryonirsp_base import CryonirspTaskBase
|
|
16
21
|
|
|
17
|
-
__all__ = ["BeamBoundariesCalibrationBase"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@dataclass
|
|
21
|
-
class BeamBoundary:
|
|
22
|
-
"""Simple dataclass to hold boundary information for the illuminated portion of the beam array."""
|
|
23
|
-
|
|
24
|
-
y_min: int
|
|
25
|
-
y_max: int
|
|
26
|
-
x_min: int
|
|
27
|
-
x_max: int
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def y_slice(self):
|
|
31
|
-
"""Return a slice object representing the illumination along the y-axis (numpy 0 axis)."""
|
|
32
|
-
return slice(self.y_min, self.y_max)
|
|
33
|
-
|
|
34
|
-
@property
|
|
35
|
-
def x_slice(self):
|
|
36
|
-
"""Return a slice object representing the illumination along the x-axis (numpy 1 axis)."""
|
|
37
|
-
return slice(self.x_min, self.x_max)
|
|
38
|
-
|
|
39
|
-
@property
|
|
40
|
-
def beam_boundaries(self):
|
|
41
|
-
"""Return a tuple containing the beam boundaries."""
|
|
42
|
-
return self.y_min, self.y_max, self.x_min, self.x_max
|
|
43
|
-
|
|
44
|
-
@property
|
|
45
|
-
def beam_boundaries_array(self):
|
|
46
|
-
"""Return a tuple containing the beam boundaries."""
|
|
47
|
-
return np.array(self.beam_boundaries)
|
|
22
|
+
__all__ = ["BeamBoundariesCalibrationBase"]
|
|
48
23
|
|
|
49
24
|
|
|
50
25
|
class BeamBoundariesCalibrationBase(CryonirspTaskBase):
|
|
@@ -91,7 +66,12 @@ class BeamBoundariesCalibrationBase(CryonirspTaskBase):
|
|
|
91
66
|
|
|
92
67
|
# Step 2:
|
|
93
68
|
with self.apm_task_step(f"Retrieve bad pixel map"):
|
|
94
|
-
bad_pixel_map =
|
|
69
|
+
bad_pixel_map = next(
|
|
70
|
+
self.read(
|
|
71
|
+
tags=[CryonirspTag.intermediate_frame(), CryonirspTag.task_bad_pixel_map()],
|
|
72
|
+
decoder=cryo_fits_array_decoder,
|
|
73
|
+
)
|
|
74
|
+
)
|
|
95
75
|
corrected_solar_gain_array = self.corrections_correct_bad_pixels(
|
|
96
76
|
average_solar_gain_array, bad_pixel_map
|
|
97
77
|
)
|
|
@@ -128,10 +108,13 @@ class BeamBoundariesCalibrationBase(CryonirspTaskBase):
|
|
|
128
108
|
# Step 10:
|
|
129
109
|
with self.apm_writing_step("Writing beam boundaries"):
|
|
130
110
|
for beam, bounds in enumerate(boundaries, start=1):
|
|
131
|
-
self.
|
|
132
|
-
bounds.beam_boundaries_array,
|
|
133
|
-
|
|
134
|
-
|
|
111
|
+
self.write(
|
|
112
|
+
data=bounds.beam_boundaries_array,
|
|
113
|
+
tags=[
|
|
114
|
+
CryonirspTag.intermediate_frame(beam=beam),
|
|
115
|
+
CryonirspTag.task_beam_boundaries(),
|
|
116
|
+
],
|
|
117
|
+
encoder=fits_array_encoder,
|
|
135
118
|
)
|
|
136
119
|
|
|
137
120
|
def compute_average_gain_array(self) -> np.ndarray:
|
|
@@ -148,12 +131,10 @@ class BeamBoundariesCalibrationBase(CryonirspTaskBase):
|
|
|
148
131
|
-------
|
|
149
132
|
The average gain array
|
|
150
133
|
"""
|
|
151
|
-
lin_corr_gain_arrays = self.
|
|
152
|
-
tags=[
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
CryonirspTag.frame(),
|
|
156
|
-
]
|
|
134
|
+
lin_corr_gain_arrays = self.read(
|
|
135
|
+
tags=[CryonirspTag.linearized_frame(), CryonirspTag.task_solar_gain()],
|
|
136
|
+
decoder=cryo_fits_array_decoder,
|
|
137
|
+
fits_access_class=CryonirspLinearizedFitsAccess,
|
|
157
138
|
)
|
|
158
139
|
averaged_gain_data = average_numpy_arrays(lin_corr_gain_arrays)
|
|
159
140
|
return averaged_gain_data
|
|
@@ -3,8 +3,8 @@ import largestinteriorrectangle as lir
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
from dkist_service_configuration.logging import logger
|
|
5
5
|
|
|
6
|
+
from dkist_processing_cryonirsp.models.beam_boundaries import BeamBoundary
|
|
6
7
|
from dkist_processing_cryonirsp.tasks.beam_boundaries_base import BeamBoundariesCalibrationBase
|
|
7
|
-
from dkist_processing_cryonirsp.tasks.beam_boundaries_base import BeamBoundary
|
|
8
8
|
|
|
9
9
|
__all__ = ["CIBeamBoundariesCalibration"]
|
|
10
10
|
|
|
@@ -3,6 +3,7 @@ from collections import defaultdict
|
|
|
3
3
|
|
|
4
4
|
from dkist_service_configuration.logging import logger
|
|
5
5
|
|
|
6
|
+
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_array_decoder
|
|
6
7
|
from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
|
|
7
8
|
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
8
9
|
from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import CryonirspL0FitsAccess
|
|
@@ -141,22 +142,39 @@ class CIScienceCalibration(ScienceCalibrationBase):
|
|
|
141
142
|
beam = self.CI_BEAM
|
|
142
143
|
# Load the dark arrays
|
|
143
144
|
for exposure_conditions in self.constants.observe_exposure_conditions_list:
|
|
144
|
-
dark_array =
|
|
145
|
-
|
|
145
|
+
dark_array = next(
|
|
146
|
+
self.read(
|
|
147
|
+
tags=[
|
|
148
|
+
CryonirspTag.intermediate_frame(
|
|
149
|
+
beam=beam, exposure_conditions=exposure_conditions
|
|
150
|
+
),
|
|
151
|
+
CryonirspTag.task_dark(),
|
|
152
|
+
],
|
|
153
|
+
decoder=cryo_fits_array_decoder,
|
|
154
|
+
)
|
|
146
155
|
)
|
|
147
156
|
dark_dict[CryonirspTag.beam(beam)][
|
|
148
157
|
CryonirspTag.exposure_conditions(exposure_conditions)
|
|
149
158
|
] = dark_array
|
|
150
159
|
|
|
151
160
|
# Load the gain arrays
|
|
152
|
-
solar_dict[CryonirspTag.beam(beam)] =
|
|
153
|
-
|
|
161
|
+
solar_dict[CryonirspTag.beam(beam)] = next(
|
|
162
|
+
self.read(
|
|
163
|
+
tags=[CryonirspTag.intermediate_frame(beam=beam), CryonirspTag.task_solar_gain()],
|
|
164
|
+
decoder=cryo_fits_array_decoder,
|
|
165
|
+
)
|
|
154
166
|
)
|
|
155
167
|
|
|
156
168
|
# Load the demod matrices
|
|
157
169
|
if self.constants.correct_for_polarization:
|
|
158
|
-
demod_dict[CryonirspTag.beam(beam)] =
|
|
159
|
-
|
|
170
|
+
demod_dict[CryonirspTag.beam(beam)] = next(
|
|
171
|
+
self.read(
|
|
172
|
+
tags=[
|
|
173
|
+
CryonirspTag.intermediate_frame(beam=beam),
|
|
174
|
+
CryonirspTag.task_demodulation_matrices(),
|
|
175
|
+
],
|
|
176
|
+
decoder=cryo_fits_array_decoder,
|
|
177
|
+
)
|
|
160
178
|
)
|
|
161
179
|
|
|
162
180
|
return CalibrationCollection(
|
|
@@ -7,22 +7,12 @@ from dkist_processing_common.tasks.mixin.quality import QualityMixin
|
|
|
7
7
|
|
|
8
8
|
from dkist_processing_cryonirsp.models.constants import CryonirspConstants
|
|
9
9
|
from dkist_processing_cryonirsp.models.parameters import CryonirspParameters
|
|
10
|
-
from dkist_processing_cryonirsp.tasks.mixin.beam_access import BeamAccessMixin
|
|
11
10
|
from dkist_processing_cryonirsp.tasks.mixin.corrections import CorrectionsMixin
|
|
12
|
-
from dkist_processing_cryonirsp.tasks.mixin.intermediate_frame import (
|
|
13
|
-
IntermediateFrameMixin,
|
|
14
|
-
)
|
|
15
|
-
from dkist_processing_cryonirsp.tasks.mixin.linearized_frame import (
|
|
16
|
-
LinearizedFrameMixin,
|
|
17
|
-
)
|
|
18
11
|
|
|
19
12
|
|
|
20
13
|
class CryonirspTaskBase(
|
|
21
14
|
WorkflowTaskBase,
|
|
22
15
|
InputDatasetMixin,
|
|
23
|
-
BeamAccessMixin,
|
|
24
|
-
LinearizedFrameMixin,
|
|
25
|
-
IntermediateFrameMixin,
|
|
26
16
|
CorrectionsMixin,
|
|
27
17
|
QualityMixin,
|
|
28
18
|
ABC,
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"""CryoNIRSP dark calibration task."""
|
|
2
|
+
from dkist_processing_common.codecs.fits import fits_array_encoder
|
|
2
3
|
from dkist_processing_common.models.task_name import TaskName
|
|
3
4
|
from dkist_processing_math.statistics import average_numpy_arrays
|
|
4
5
|
from dkist_service_configuration.logging import logger
|
|
5
6
|
|
|
7
|
+
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_array_decoder
|
|
8
|
+
from dkist_processing_cryonirsp.models.beam_boundaries import BeamBoundary
|
|
6
9
|
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
10
|
+
from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import (
|
|
11
|
+
CryonirspLinearizedFitsAccess,
|
|
12
|
+
)
|
|
7
13
|
from dkist_processing_cryonirsp.tasks.cryonirsp_base import CryonirspTaskBase
|
|
8
14
|
|
|
9
15
|
__all__ = ["DarkCalibration"]
|
|
@@ -55,21 +61,32 @@ class DarkCalibration(CryonirspTaskBase):
|
|
|
55
61
|
f"Calculating dark frames for {self.constants.num_beams} beams and {len(target_exposure_conditions)} exp times"
|
|
56
62
|
):
|
|
57
63
|
total_dark_frames_used = 0
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
|
|
65
|
+
for beam in range(1, self.constants.num_beams + 1):
|
|
66
|
+
beam_array = next(
|
|
67
|
+
self.read(
|
|
68
|
+
tags=CryonirspTag.intermediate_beam_boundaries(beam=beam),
|
|
69
|
+
decoder=cryo_fits_array_decoder,
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
beam_boundary = BeamBoundary(*beam_array)
|
|
73
|
+
|
|
74
|
+
for exposure_conditions in target_exposure_conditions:
|
|
60
75
|
logger.info(
|
|
61
76
|
f"Gathering input dark frames for {exposure_conditions = } and {beam = }"
|
|
62
77
|
)
|
|
63
78
|
dark_tags = [
|
|
64
|
-
CryonirspTag.
|
|
65
|
-
CryonirspTag.frame(),
|
|
79
|
+
CryonirspTag.linearized_frame(exposure_conditions=exposure_conditions),
|
|
66
80
|
CryonirspTag.task_dark(),
|
|
67
|
-
CryonirspTag.exposure_conditions(exposure_conditions),
|
|
68
81
|
]
|
|
69
82
|
current_exp_dark_count = self.scratch.count_all(tags=dark_tags)
|
|
70
83
|
total_dark_frames_used += current_exp_dark_count
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
|
|
85
|
+
linearized_dark_arrays = self.read(
|
|
86
|
+
tags=dark_tags,
|
|
87
|
+
decoder=cryo_fits_array_decoder,
|
|
88
|
+
fits_access_class=CryonirspLinearizedFitsAccess,
|
|
89
|
+
beam_boundary=beam_boundary,
|
|
73
90
|
)
|
|
74
91
|
|
|
75
92
|
with self.apm_processing_step(
|
|
@@ -80,18 +97,21 @@ class DarkCalibration(CryonirspTaskBase):
|
|
|
80
97
|
with self.apm_writing_step(
|
|
81
98
|
f"Writing dark for {exposure_conditions = } {beam = }"
|
|
82
99
|
):
|
|
83
|
-
self.
|
|
84
|
-
averaged_dark_array,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
self.write(
|
|
101
|
+
data=averaged_dark_array,
|
|
102
|
+
tags=[
|
|
103
|
+
CryonirspTag.intermediate_frame(
|
|
104
|
+
beam=beam, exposure_conditions=exposure_conditions
|
|
105
|
+
),
|
|
106
|
+
CryonirspTag.task_dark(),
|
|
107
|
+
],
|
|
108
|
+
encoder=fits_array_encoder,
|
|
88
109
|
)
|
|
89
110
|
|
|
90
111
|
with self.apm_processing_step("Computing and logging quality metrics"):
|
|
91
112
|
no_of_raw_dark_frames: int = self.scratch.count_all(
|
|
92
113
|
tags=[
|
|
93
|
-
CryonirspTag.
|
|
94
|
-
CryonirspTag.frame(),
|
|
114
|
+
CryonirspTag.linearized_frame(),
|
|
95
115
|
CryonirspTag.task_dark(),
|
|
96
116
|
],
|
|
97
117
|
)
|