dkist-processing-visp 2.20.14__py3-none-any.whl → 5.1.1__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.
Files changed (73) hide show
  1. dkist_processing_visp/__init__.py +1 -0
  2. dkist_processing_visp/config.py +1 -0
  3. dkist_processing_visp/models/constants.py +61 -20
  4. dkist_processing_visp/models/fits_access.py +20 -0
  5. dkist_processing_visp/models/metric_code.py +10 -0
  6. dkist_processing_visp/models/parameters.py +129 -24
  7. dkist_processing_visp/models/tags.py +22 -1
  8. dkist_processing_visp/models/task_name.py +1 -0
  9. dkist_processing_visp/parsers/map_repeats.py +1 -0
  10. dkist_processing_visp/parsers/modulator_states.py +1 -0
  11. dkist_processing_visp/parsers/polarimeter_mode.py +4 -2
  12. dkist_processing_visp/parsers/raster_step.py +4 -1
  13. dkist_processing_visp/parsers/spectrograph_configuration.py +75 -0
  14. dkist_processing_visp/parsers/time.py +24 -14
  15. dkist_processing_visp/parsers/visp_l0_fits_access.py +19 -8
  16. dkist_processing_visp/parsers/visp_l1_fits_access.py +1 -0
  17. dkist_processing_visp/tasks/__init__.py +1 -0
  18. dkist_processing_visp/tasks/assemble_movie.py +1 -0
  19. dkist_processing_visp/tasks/background_light.py +2 -1
  20. dkist_processing_visp/tasks/dark.py +5 -4
  21. dkist_processing_visp/tasks/geometric.py +132 -20
  22. dkist_processing_visp/tasks/instrument_polarization.py +128 -18
  23. dkist_processing_visp/tasks/l1_output_data.py +203 -0
  24. dkist_processing_visp/tasks/lamp.py +53 -93
  25. dkist_processing_visp/tasks/make_movie_frames.py +8 -6
  26. dkist_processing_visp/tasks/mixin/beam_access.py +1 -0
  27. dkist_processing_visp/tasks/mixin/corrections.py +54 -4
  28. dkist_processing_visp/tasks/mixin/downsample.py +1 -0
  29. dkist_processing_visp/tasks/parse.py +50 -17
  30. dkist_processing_visp/tasks/quality_metrics.py +5 -4
  31. dkist_processing_visp/tasks/science.py +126 -46
  32. dkist_processing_visp/tasks/solar.py +896 -456
  33. dkist_processing_visp/tasks/visp_base.py +4 -3
  34. dkist_processing_visp/tasks/write_l1.py +38 -10
  35. dkist_processing_visp/tests/conftest.py +145 -47
  36. dkist_processing_visp/tests/header_models.py +157 -20
  37. dkist_processing_visp/tests/local_trial_workflows/l0_cals_only.py +21 -78
  38. dkist_processing_visp/tests/local_trial_workflows/l0_polcals_as_science.py +421 -0
  39. dkist_processing_visp/tests/local_trial_workflows/l0_solar_gain_as_science.py +387 -0
  40. dkist_processing_visp/tests/local_trial_workflows/l0_to_l1.py +18 -75
  41. dkist_processing_visp/tests/local_trial_workflows/local_trial_helpers.py +346 -14
  42. dkist_processing_visp/tests/test_assemble_movie.py +2 -3
  43. dkist_processing_visp/tests/test_assemble_quality.py +89 -4
  44. dkist_processing_visp/tests/test_background_light.py +51 -44
  45. dkist_processing_visp/tests/test_dark.py +4 -3
  46. dkist_processing_visp/tests/test_downsample.py +1 -0
  47. dkist_processing_visp/tests/test_fits_access.py +43 -0
  48. dkist_processing_visp/tests/test_geometric.py +45 -4
  49. dkist_processing_visp/tests/test_instrument_polarization.py +72 -9
  50. dkist_processing_visp/tests/test_lamp.py +22 -26
  51. dkist_processing_visp/tests/test_make_movie_frames.py +4 -4
  52. dkist_processing_visp/tests/test_map_repeats.py +3 -1
  53. dkist_processing_visp/tests/test_parameters.py +122 -21
  54. dkist_processing_visp/tests/test_parse.py +164 -18
  55. dkist_processing_visp/tests/test_quality.py +3 -4
  56. dkist_processing_visp/tests/test_science.py +113 -15
  57. dkist_processing_visp/tests/test_solar.py +318 -99
  58. dkist_processing_visp/tests/test_visp_constants.py +38 -8
  59. dkist_processing_visp/tests/test_workflows.py +1 -0
  60. dkist_processing_visp/tests/test_write_l1.py +22 -3
  61. dkist_processing_visp/workflows/__init__.py +1 -0
  62. dkist_processing_visp/workflows/l0_processing.py +10 -3
  63. dkist_processing_visp/workflows/trial_workflows.py +8 -2
  64. dkist_processing_visp-5.1.1.dist-info/METADATA +552 -0
  65. dkist_processing_visp-5.1.1.dist-info/RECORD +94 -0
  66. {dkist_processing_visp-2.20.14.dist-info → dkist_processing_visp-5.1.1.dist-info}/WHEEL +1 -1
  67. docs/conf.py +5 -1
  68. docs/gain_correction.rst +52 -44
  69. docs/science_calibration.rst +7 -0
  70. dkist_processing_visp/tasks/mixin/line_zones.py +0 -115
  71. dkist_processing_visp-2.20.14.dist-info/METADATA +0 -196
  72. dkist_processing_visp-2.20.14.dist-info/RECORD +0 -89
  73. {dkist_processing_visp-2.20.14.dist-info → dkist_processing_visp-5.1.1.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,11 @@
1
1
  """Visp make movie frames task."""
2
+
2
3
  import numpy as np
3
4
  from astropy.io import fits
4
5
  from astropy.visualization import ZScaleInterval
5
6
  from dkist_processing_common.codecs.fits import fits_access_decoder
6
7
  from dkist_processing_common.codecs.fits import fits_array_encoder
8
+ from dkist_processing_common.models.fits_access import MetadataKey
7
9
  from dkist_service_configuration.logging import logger
8
10
 
9
11
  from dkist_processing_visp.models.tags import VispTag
@@ -46,7 +48,7 @@ class MakeVispMovieFrames(VispTaskBase):
46
48
  stokes_states = ["I", "Q", "U", "V"]
47
49
  # Loop over the number of raster scans
48
50
  for map_scan in range(1, self.constants.num_map_scans + 1):
49
- with self.apm_processing_step(f"Making movie frame for {map_scan = }"):
51
+ with self.telemetry_span(f"Making movie frame for {map_scan = }"):
50
52
  instrument_set = set()
51
53
  wavelength_set = set()
52
54
  time_obs = []
@@ -77,7 +79,7 @@ class MakeVispMovieFrames(VispTaskBase):
77
79
  fits_access_class=VispL1FitsAccess,
78
80
  )
79
81
  )
80
- data = calibrated_frame.data
82
+ data = np.nan_to_num(calibrated_frame.data, nan=0)
81
83
  if self.constants.num_raster_steps == 1:
82
84
  logger.info(
83
85
  "Only a single raster step found. Making a spectral movie."
@@ -120,16 +122,16 @@ class MakeVispMovieFrames(VispTaskBase):
120
122
  f"There should only be one instrument value in the headers. "
121
123
  f"Found {len(instrument_set)}: {instrument_set=}"
122
124
  )
123
- header["INSTRUME"] = instrument_set.pop()
125
+ header[MetadataKey.instrument] = instrument_set.pop()
124
126
  # The timestamp of a movie frame will be the time of raster scan start
125
- header["DATE-BEG"] = time_obs[0]
127
+ header[MetadataKey.time_obs] = time_obs[0]
126
128
  # Make sure only one wavelength value was found
127
129
  if len(wavelength_set) != 1:
128
130
  raise ValueError(
129
131
  f"There should only be one wavelength value in the headers. "
130
132
  f"Found {len(wavelength_set)}: {wavelength_set=}"
131
133
  )
132
- header["LINEWAV"] = wavelength_set.pop()
134
+ header[MetadataKey.wavelength] = wavelength_set.pop()
133
135
  # Write the movie frame file to disk and tag it, normalizing across stokes intensities
134
136
  if is_polarized:
135
137
  i_norm = ZScaleInterval()(stokes_i_data)
@@ -146,7 +148,7 @@ class MakeVispMovieFrames(VispTaskBase):
146
148
  else:
147
149
  movie_frame_data = stokes_i_data
148
150
 
149
- with self.apm_writing_step(f"Writing movie frame for {map_scan = }"):
151
+ with self.telemetry_span(f"Writing movie frame for {map_scan = }"):
150
152
  self.write(
151
153
  data=np.asarray(movie_frame_data),
152
154
  tags=[
@@ -1,4 +1,5 @@
1
1
  """Helper to manage extract a given beam from input data."""
2
+
2
3
  import numpy as np
3
4
 
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Helper for ViSP array corrections."""
2
+
2
3
  from typing import Generator
3
4
  from typing import Iterable
4
5
 
@@ -16,6 +17,9 @@ class CorrectionsMixin:
16
17
  arrays: Iterable[np.ndarray] | np.ndarray,
17
18
  shift: np.ndarray = np.zeros(2),
18
19
  angle: float = 0.0,
20
+ mode: str = "edge",
21
+ order: int = 5,
22
+ cval: float = np.nan,
19
23
  ) -> Generator[np.ndarray, None, None]:
20
24
  """
21
25
  Shift and then rotate data.
@@ -34,6 +38,24 @@ class CorrectionsMixin:
34
38
  angle : float
35
39
  The angle (in radians) between slit hairlines and pixel axes.
36
40
 
41
+ mode : {'constant', 'edge', 'symmetric', 'reflect', 'wrap'}
42
+ Points outside the boundaries of the input are filled according
43
+ to the given mode. Modes match the behaviour of `numpy.pad`.
44
+
45
+ order : int
46
+ The order of interpolation. The order has to be in the range 0-5:
47
+ - 0: Nearest-neighbor
48
+ - 1: Bi-linear (default)
49
+ - 2: Bi-quadratic
50
+ - 3: Bi-cubic
51
+ - 4: Bi-quartic
52
+ - 5: Bi-quintic
53
+
54
+ cval : float
55
+ Used in conjunction with mode 'constant', the value outside
56
+ the image boundaries.
57
+
58
+
37
59
  Returns
38
60
  -------
39
61
  Generator
@@ -45,12 +67,21 @@ class CorrectionsMixin:
45
67
  array[np.where(array == np.inf)] = np.max(array[np.isfinite(array)])
46
68
  array[np.where(array == -np.inf)] = np.min(array[np.isfinite(array)])
47
69
  array[np.isnan(array)] = np.nanmedian(array)
48
- translated = affine_transform_arrays(array, translation=-shift, mode="reflect", order=5)
49
- yield next(rotate_arrays_about_point(translated, angle=-angle, mode="reflect", order=5))
70
+ translated = affine_transform_arrays(
71
+ array, translation=-shift, mode=mode, order=order, cval=cval
72
+ )
73
+ yield next(
74
+ rotate_arrays_about_point(
75
+ translated, angle=-angle, mode=mode, order=order, cval=cval
76
+ )
77
+ )
50
78
 
51
79
  @staticmethod
52
80
  def corrections_remove_spec_geometry(
53
- arrays: Iterable[np.ndarray] | np.ndarray, spec_shift: np.ndarray
81
+ arrays: Iterable[np.ndarray] | np.ndarray,
82
+ spec_shift: np.ndarray,
83
+ cval: float | None = None,
84
+ order: int = 3,
54
85
  ) -> Generator[np.ndarray, None, None]:
55
86
  """
56
87
  Remove spectral curvature.
@@ -66,6 +97,19 @@ class CorrectionsMixin:
66
97
  Array with shape (X), where X is the number of pixels in the spatial dimension.
67
98
  This dimension gives the spectral shift.
68
99
 
100
+ order : int
101
+ The order of interpolation. The order has to be in the range 0-5:
102
+ - 0: Nearest-neighbor
103
+ - 1: Bi-linear (default)
104
+ - 2: Bi-quadratic
105
+ - 3: Bi-cubic
106
+ - 4: Bi-quartic
107
+ - 5: Bi-quintic
108
+
109
+ cval : float
110
+ Used in conjunction with mode 'constant', the value outside
111
+ the image boundaries.
112
+
69
113
  Returns
70
114
  -------
71
115
  Generator
@@ -77,8 +121,14 @@ class CorrectionsMixin:
77
121
  numy = array.shape[1]
78
122
  array_output = np.zeros(array.shape)
79
123
  for j in range(numy):
124
+ if cval is None:
125
+ cval = np.nanmedian(array[:, j])
80
126
  array_output[:, j] = spnd.shift(
81
- array[:, j], -spec_shift[j], mode="constant", cval=np.nanmedian(array[:, j])
127
+ array[:, j],
128
+ -spec_shift[j],
129
+ mode="constant",
130
+ cval=cval,
131
+ order=order,
82
132
  )
83
133
  yield array_output
84
134
 
@@ -1,4 +1,5 @@
1
1
  """Helper mixin for downsampling data."""
2
+
2
3
  import numpy as np
3
4
 
4
5
 
@@ -1,23 +1,28 @@
1
1
  """ViSP parse task."""
2
+
2
3
  from typing import TypeVar
3
4
 
5
+ from dkist_processing_common.models.fits_access import MetadataKey
4
6
  from dkist_processing_common.models.flower_pot import Stem
5
7
  from dkist_processing_common.models.task_name import TaskName
6
8
  from dkist_processing_common.parsers.cs_step import CSStepFlower
7
9
  from dkist_processing_common.parsers.cs_step import NumCSStepBud
8
- from dkist_processing_common.parsers.task import parse_header_ip_task_with_gains
10
+ from dkist_processing_common.parsers.retarder import RetarderNameBud
11
+ from dkist_processing_common.parsers.task import PolcalTaskFlower
9
12
  from dkist_processing_common.parsers.task import TaskTypeFlower
13
+ from dkist_processing_common.parsers.task import parse_header_ip_task_with_gains
10
14
  from dkist_processing_common.parsers.time import ExposureTimeFlower
11
15
  from dkist_processing_common.parsers.time import ObsIpStartTimeBud
12
16
  from dkist_processing_common.parsers.time import ReadoutExpTimeFlower
13
17
  from dkist_processing_common.parsers.time import TaskExposureTimesBud
14
18
  from dkist_processing_common.parsers.time import TaskReadoutExpTimesBud
19
+ from dkist_processing_common.parsers.unique_bud import TaskUniqueBud
15
20
  from dkist_processing_common.parsers.unique_bud import UniqueBud
16
21
  from dkist_processing_common.parsers.wavelength import ObserveWavelengthBud
17
22
  from dkist_processing_common.tasks import ParseL0InputDataBase
18
- from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetMixin
19
23
 
20
24
  from dkist_processing_visp.models.constants import VispBudName
25
+ from dkist_processing_visp.models.fits_access import VispMetadataKey
21
26
  from dkist_processing_visp.models.parameters import VispParsingParameters
22
27
  from dkist_processing_visp.parsers.map_repeats import MapScanFlower
23
28
  from dkist_processing_visp.parsers.map_repeats import NumMapScansBud
@@ -26,15 +31,17 @@ from dkist_processing_visp.parsers.modulator_states import NumberModulatorStates
26
31
  from dkist_processing_visp.parsers.polarimeter_mode import PolarimeterModeBud
27
32
  from dkist_processing_visp.parsers.raster_step import RasterScanStepFlower
28
33
  from dkist_processing_visp.parsers.raster_step import TotalRasterStepsBud
34
+ from dkist_processing_visp.parsers.spectrograph_configuration import IncidentLightAngleBud
35
+ from dkist_processing_visp.parsers.spectrograph_configuration import ReflectedLightAngleBud
29
36
  from dkist_processing_visp.parsers.time import DarkReadoutExpTimePickyBud
30
- from dkist_processing_visp.parsers.time import NonDarkTaskReadoutExpTimesBud
37
+ from dkist_processing_visp.parsers.time import NonDarkNonPolcalTaskReadoutExpTimesBud
31
38
  from dkist_processing_visp.parsers.visp_l0_fits_access import VispL0FitsAccess
32
39
 
33
40
  S = TypeVar("S", bound=Stem)
34
41
  __all__ = ["ParseL0VispInputData"]
35
42
 
36
43
 
37
- class ParseL0VispInputData(ParseL0InputDataBase, InputDatasetMixin):
44
+ class ParseL0VispInputData(ParseL0InputDataBase):
38
45
  """
39
46
  Parse input ViSP data. Subclassed from the ParseL0InputDataBase task in dkist_processing_common to add ViSP specific parameters.
40
47
 
@@ -60,7 +67,7 @@ class ParseL0VispInputData(ParseL0InputDataBase, InputDatasetMixin):
60
67
  workflow_name=workflow_name,
61
68
  workflow_version=workflow_version,
62
69
  )
63
- self.parameters = VispParsingParameters(self.input_dataset_parameters)
70
+ self.parameters = VispParsingParameters(scratch=self.scratch)
64
71
 
65
72
  @property
66
73
  def fits_parsing_class(self):
@@ -71,6 +78,7 @@ class ParseL0VispInputData(ParseL0InputDataBase, InputDatasetMixin):
71
78
  def constant_buds(self) -> list[S]:
72
79
  """Add ViSP specific constants to common constants."""
73
80
  return super().constant_buds + [
81
+ UniqueBud(constant_name=VispBudName.arm_id.value, metadata_key=VispMetadataKey.arm_id),
74
82
  NumMapScansBud(),
75
83
  TotalRasterStepsBud(),
76
84
  NumCSStepBud(self.parameters.max_cs_step_time_sec),
@@ -78,51 +86,75 @@ class ParseL0VispInputData(ParseL0InputDataBase, InputDatasetMixin):
78
86
  NumberModulatorStatesBud(),
79
87
  ObserveWavelengthBud(),
80
88
  PolarimeterModeBud(),
81
- NonDarkTaskReadoutExpTimesBud(),
89
+ RetarderNameBud(),
90
+ NonDarkNonPolcalTaskReadoutExpTimesBud(),
82
91
  DarkReadoutExpTimePickyBud(),
92
+ IncidentLightAngleBud(),
93
+ ReflectedLightAngleBud(),
94
+ TaskUniqueBud(
95
+ constant_name=VispBudName.grating_constant_inverse_mm.value,
96
+ metadata_key=VispMetadataKey.grating_constant_inverse_mm,
97
+ ip_task_types=[TaskName.observe.value, TaskName.solar_gain.value],
98
+ task_type_parsing_function=parse_header_ip_task_with_gains,
99
+ ),
100
+ TaskUniqueBud(
101
+ constant_name=VispBudName.solar_gain_ip_start_time.value,
102
+ metadata_key=MetadataKey.ip_start_time,
103
+ ip_task_types=TaskName.solar_gain,
104
+ task_type_parsing_function=parse_header_ip_task_with_gains,
105
+ ),
83
106
  TaskExposureTimesBud(
84
107
  stem_name=VispBudName.lamp_exposure_times.value,
85
- ip_task_type=TaskName.lamp_gain.value,
108
+ ip_task_types=TaskName.lamp_gain.value,
86
109
  header_task_parsing_func=parse_header_ip_task_with_gains,
87
110
  ),
88
111
  TaskExposureTimesBud(
89
112
  stem_name=VispBudName.solar_exposure_times.value,
90
- ip_task_type=TaskName.solar_gain.value,
113
+ ip_task_types=TaskName.solar_gain.value,
91
114
  header_task_parsing_func=parse_header_ip_task_with_gains,
92
115
  ),
93
116
  TaskExposureTimesBud(
94
117
  stem_name=VispBudName.observe_exposure_times.value,
95
- ip_task_type=TaskName.observe.value,
118
+ ip_task_types=TaskName.observe.value,
96
119
  header_task_parsing_func=parse_header_ip_task_with_gains,
97
120
  ),
98
121
  TaskExposureTimesBud(
99
122
  stem_name=VispBudName.polcal_exposure_times.value,
100
- ip_task_type=TaskName.polcal.value,
123
+ ip_task_types=TaskName.polcal.value,
101
124
  header_task_parsing_func=parse_header_ip_task_with_gains,
102
125
  ),
103
126
  TaskReadoutExpTimesBud(
104
127
  stem_name=VispBudName.lamp_readout_exp_times.value,
105
- ip_task_type=TaskName.lamp_gain.value,
128
+ ip_task_types=TaskName.lamp_gain.value,
106
129
  header_task_parsing_func=parse_header_ip_task_with_gains,
107
130
  ),
108
131
  TaskReadoutExpTimesBud(
109
132
  stem_name=VispBudName.solar_readout_exp_times.value,
110
- ip_task_type=TaskName.solar_gain.value,
133
+ ip_task_types=TaskName.solar_gain.value,
111
134
  header_task_parsing_func=parse_header_ip_task_with_gains,
112
135
  ),
113
136
  TaskReadoutExpTimesBud(
114
137
  stem_name=VispBudName.observe_readout_exp_times.value,
115
- ip_task_type=TaskName.observe.value,
138
+ ip_task_types=TaskName.observe.value,
116
139
  header_task_parsing_func=parse_header_ip_task_with_gains,
117
140
  ),
118
141
  TaskReadoutExpTimesBud(
119
142
  stem_name=VispBudName.polcal_readout_exp_times.value,
120
- ip_task_type=TaskName.polcal.value,
143
+ ip_task_types=TaskName.polcal.value,
121
144
  header_task_parsing_func=parse_header_ip_task_with_gains,
122
145
  ),
123
- UniqueBud(constant_name=VispBudName.axis_1_type.value, metadata_key="axis_1_type"),
124
- UniqueBud(constant_name=VispBudName.axis_2_type.value, metadata_key="axis_2_type"),
125
- UniqueBud(constant_name=VispBudName.axis_3_type.value, metadata_key="axis_3_type"),
146
+ UniqueBud(
147
+ constant_name=VispBudName.axis_1_type.value,
148
+ metadata_key=VispMetadataKey.axis_1_type,
149
+ ),
150
+ UniqueBud(
151
+ constant_name=VispBudName.axis_2_type.value,
152
+ metadata_key=VispMetadataKey.axis_2_type,
153
+ ),
154
+ UniqueBud(
155
+ constant_name=VispBudName.axis_3_type.value,
156
+ metadata_key=VispMetadataKey.axis_3_type,
157
+ ),
126
158
  ]
127
159
 
128
160
  @property
@@ -132,6 +164,7 @@ class ParseL0VispInputData(ParseL0InputDataBase, InputDatasetMixin):
132
164
  CSStepFlower(max_cs_step_time_sec=self.parameters.max_cs_step_time_sec),
133
165
  MapScanFlower(),
134
166
  TaskTypeFlower(header_task_parsing_func=parse_header_ip_task_with_gains),
167
+ PolcalTaskFlower(),
135
168
  RasterScanStepFlower(),
136
169
  ModulatorStateFlower(),
137
170
  ExposureTimeFlower(),
@@ -1,4 +1,5 @@
1
1
  """ViSP quality metrics task."""
2
+
2
3
  from dataclasses import dataclass
3
4
  from dataclasses import field
4
5
  from typing import Iterable
@@ -105,7 +106,7 @@ class VispL1QualityMetrics(VispTaskBase, QualityMixin):
105
106
 
106
107
  def compute_sensitivity(self) -> None:
107
108
  """Compute RMS noise and sensitivity estimate for L1 Visp frames."""
108
- with self.apm_processing_step("Calculating polarization metrics"):
109
+ with self.telemetry_span("Calculating polarization metrics"):
109
110
  all_datetimes = []
110
111
  all_I_sensitivity = []
111
112
  all_Q_sensitivity = []
@@ -161,7 +162,7 @@ class VispL1QualityMetrics(VispTaskBase, QualityMixin):
161
162
  continue
162
163
 
163
164
  # compute sensitivity for this Stokes parameter
164
- data_list.append(np.std(stokes_frame.data) / stokesI_med)
165
+ data_list.append(np.nanstd(stokes_frame.data) / stokesI_med)
165
166
 
166
167
  all_datetimes.append(Time(np.mean(polarization_data.datetimes), format="mjd").isot)
167
168
  for target, source in zip(
@@ -173,7 +174,7 @@ class VispL1QualityMetrics(VispTaskBase, QualityMixin):
173
174
  continue
174
175
  target.append(np.mean(source))
175
176
 
176
- with self.apm_step("Sending lists for storage"):
177
+ with self.telemetry_span("Sending lists for storage"):
177
178
  for stokes_index, stokes_noise in zip(
178
179
  ("I", "Q", "U", "V"),
179
180
  (all_I_sensitivity, all_Q_sensitivity, all_U_sensitivity, all_V_sensitivity),
@@ -186,7 +187,7 @@ class VispL1QualityMetrics(VispTaskBase, QualityMixin):
186
187
 
187
188
  def compute_noise(self):
188
189
  """Compute noise in data."""
189
- with self.apm_processing_step("Calculating L1 ViSP noise metrics"):
190
+ with self.telemetry_span("Calculating L1 ViSP noise metrics"):
190
191
  for stokes in ["I", "Q", "U", "V"]:
191
192
  tags = [VispTag.calibrated(), VispTag.frame(), VispTag.stokes(stokes)]
192
193
  if self.scratch.count_all(tags=tags) > 0: