dkist-processing-visp 3.3.0__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 (71) 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 +52 -21
  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 -19
  7. dkist_processing_visp/models/tags.py +1 -0
  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 +3 -1
  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 +15 -7
  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 +13 -12
  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 +34 -4
  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 +2 -0
  34. dkist_processing_visp/tasks/write_l1.py +25 -5
  35. dkist_processing_visp/tests/conftest.py +99 -35
  36. dkist_processing_visp/tests/header_models.py +92 -20
  37. dkist_processing_visp/tests/local_trial_workflows/l0_cals_only.py +4 -23
  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 +10 -29
  40. dkist_processing_visp/tests/local_trial_workflows/l0_to_l1.py +1 -21
  41. dkist_processing_visp/tests/local_trial_workflows/local_trial_helpers.py +98 -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 +8 -5
  45. dkist_processing_visp/tests/test_dark.py +4 -3
  46. dkist_processing_visp/tests/test_fits_access.py +43 -0
  47. dkist_processing_visp/tests/test_geometric.py +45 -4
  48. dkist_processing_visp/tests/test_instrument_polarization.py +4 -3
  49. dkist_processing_visp/tests/test_lamp.py +22 -26
  50. dkist_processing_visp/tests/test_make_movie_frames.py +4 -4
  51. dkist_processing_visp/tests/test_map_repeats.py +3 -1
  52. dkist_processing_visp/tests/test_parameters.py +122 -21
  53. dkist_processing_visp/tests/test_parse.py +98 -14
  54. dkist_processing_visp/tests/test_quality.py +2 -3
  55. dkist_processing_visp/tests/test_science.py +113 -15
  56. dkist_processing_visp/tests/test_solar.py +318 -99
  57. dkist_processing_visp/tests/test_visp_constants.py +36 -8
  58. dkist_processing_visp/tests/test_workflows.py +1 -0
  59. dkist_processing_visp/tests/test_write_l1.py +17 -3
  60. dkist_processing_visp/workflows/__init__.py +1 -0
  61. dkist_processing_visp/workflows/l0_processing.py +8 -2
  62. dkist_processing_visp/workflows/trial_workflows.py +8 -2
  63. dkist_processing_visp-5.1.1.dist-info/METADATA +552 -0
  64. dkist_processing_visp-5.1.1.dist-info/RECORD +94 -0
  65. docs/conf.py +5 -1
  66. docs/gain_correction.rst +50 -42
  67. dkist_processing_visp/tasks/mixin/line_zones.py +0 -115
  68. dkist_processing_visp-3.3.0.dist-info/METADATA +0 -459
  69. dkist_processing_visp-3.3.0.dist-info/RECORD +0 -90
  70. {dkist_processing_visp-3.3.0.dist-info → dkist_processing_visp-5.1.1.dist-info}/WHEEL +0 -0
  71. {dkist_processing_visp-3.3.0.dist-info → dkist_processing_visp-5.1.1.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  """ViSP base class."""
2
+
2
3
  from abc import ABC
3
4
 
4
5
  from dkist_processing_common.tasks import WorkflowTaskBase
@@ -44,4 +45,5 @@ class VispTaskBase(WorkflowTaskBase, ABC):
44
45
  scratch=self.scratch,
45
46
  obs_ip_start_time=self.constants.obs_ip_start_time,
46
47
  wavelength=self.constants.wavelength,
48
+ arm_id=self.constants.arm_id,
47
49
  )
@@ -1,14 +1,17 @@
1
1
  """Visp write L1 task."""
2
+
2
3
  from functools import cache
3
4
  from typing import Literal
4
5
 
5
6
  import astropy.units as u
6
7
  from astropy.io import fits
8
+ from dkist_processing_common.models.fits_access import MetadataKey
7
9
  from dkist_processing_common.tasks import WriteL1Frame
8
10
  from dkist_processing_common.tasks.write_l1 import WavelengthRange
9
11
  from dkist_service_configuration.logging import logger
10
12
 
11
13
  from dkist_processing_visp.models.constants import VispConstants
14
+ from dkist_processing_visp.models.fits_access import VispMetadataKey
12
15
 
13
16
  cached_info_logger = cache(logger.info)
14
17
  __all__ = ["VispWriteL1Frame"]
@@ -54,7 +57,7 @@ class VispWriteL1Frame(WriteL1Frame):
54
57
  """
55
58
  # Correct the headers for the number of map and scan steps per map due to potential observation aborts
56
59
  header["VSPNMAPS"] = self.constants.num_map_scans
57
- header["VSPNSTP"] = self.constants.num_raster_steps
60
+ header[VispMetadataKey.total_raster_steps] = self.constants.num_raster_steps
58
61
 
59
62
  if stokes.upper() not in self.constants.stokes_params:
60
63
  raise ValueError("The stokes parameter must be one of I, Q, U, V")
@@ -91,7 +94,7 @@ class VispWriteL1Frame(WriteL1Frame):
91
94
  header[f"CNAME{i}"] = "helioprojective longitude"
92
95
  header[f"DUNIT{i}"] = header[f"CUNIT{i}"]
93
96
  # Current position in raster scan which counts from zero
94
- header[f"DINDEX{i}"] = header["VSPSTP"] + 1
97
+ header[f"DINDEX{i}"] = header[VispMetadataKey.raster_scan_step] + 1
95
98
  else:
96
99
  raise ValueError(
97
100
  f"Unexpected axis type. Expected ['HPLT-TAN', 'AWAV', 'HPLN-TAN']. Got {axis_type}"
@@ -104,9 +107,9 @@ class VispWriteL1Frame(WriteL1Frame):
104
107
  if self.constants.num_map_scans > 1:
105
108
  cached_info_logger("Adding map scan dataset axis")
106
109
  num_axis += 1
107
- header[
108
- f"DNAXIS{num_axis}"
109
- ] = self.constants.num_map_scans # total number of raster scans in the dataset
110
+ header[f"DNAXIS{num_axis}"] = (
111
+ self.constants.num_map_scans
112
+ ) # total number of raster scans in the dataset
110
113
  header[f"DTYPE{num_axis}"] = "TEMPORAL"
111
114
  header[f"DPNAME{num_axis}"] = "raster map repeat number"
112
115
  header[f"DWNAME{num_axis}"] = "time"
@@ -193,3 +196,20 @@ class VispWriteL1Frame(WriteL1Frame):
193
196
  min=u.Quantity(minimum, unit=wavelength_unit),
194
197
  max=u.Quantity(maximum, unit=wavelength_unit),
195
198
  )
199
+
200
+ def add_timing_headers(self, header: fits.Header) -> fits.Header:
201
+ """
202
+ Add timing headers to the FITS header.
203
+
204
+ This method adds or updates headers related to frame timings.
205
+ """
206
+ # The source data is based on L0 data but L1 data takes L0 cadence * modstates to obtain.
207
+ # This causes both the cadence and the full exposure time to be num_modstates times longer.
208
+ header["CADENCE"] = self.constants.average_cadence * self.constants.num_modstates
209
+ header["CADMIN"] = self.constants.minimum_cadence * self.constants.num_modstates
210
+ header["CADMAX"] = self.constants.maximum_cadence * self.constants.num_modstates
211
+ header["CADVAR"] = self.constants.variance_cadence * self.constants.num_modstates
212
+ header[MetadataKey.fpa_exposure_time_ms] = (
213
+ header[MetadataKey.fpa_exposure_time_ms] * self.constants.num_modstates
214
+ )
215
+ return header
@@ -1,8 +1,10 @@
1
1
  import json
2
2
  from dataclasses import asdict
3
3
  from dataclasses import dataclass
4
+ from dataclasses import field
4
5
  from dataclasses import is_dataclass
5
6
  from random import randint
7
+ from typing import Any
6
8
  from typing import Callable
7
9
  from typing import Type
8
10
 
@@ -18,6 +20,9 @@ from dkist_processing_common.codecs.fits import fits_hdulist_encoder
18
20
  from dkist_processing_common.models.input_dataset import InputDatasetPartDocumentList
19
21
  from dkist_processing_common.tasks import WorkflowTaskBase
20
22
 
23
+ # Don't remove this; tests will break
24
+ from dkist_processing_common.tests.mock_metadata_store import fake_gql_client
25
+
21
26
  from dkist_processing_visp.models.constants import VispConstants
22
27
  from dkist_processing_visp.models.parameters import VispParameters
23
28
  from dkist_processing_visp.models.tags import VispTag
@@ -40,6 +45,7 @@ def init_visp_constants_db():
40
45
 
41
46
  @dataclass
42
47
  class VispConstantsDb:
48
+ ARM_ID: int = 1
43
49
  POLARIMETER_MODE: str = "observe_polarimetric"
44
50
  OBS_IP_START_TIME: str = "2022-11-28T13:54:00"
45
51
  NUM_MODSTATES: int = 10
@@ -65,6 +71,10 @@ class VispConstantsDb:
65
71
  OBSERVE_READOUT_EXP_TIMES: tuple[float] = (0.02,)
66
72
  POLCAL_READOUT_EXP_TIMES: tuple[float] = (0.02,)
67
73
  SPECTRAL_LINE: str = "VISP Ca II H"
74
+ INCIDENT_LIGHT_ANGLE_DEG: float = 73.22
75
+ REFLECTED_LIGHT_ANGLE_DEG: float = 64.92
76
+ GRATING_CONSTANT_INVERSE_MM: float = 316.0
77
+ SOLAR_GAIN_IP_START_TIME: str = "2025-09-24T20:00:00"
68
78
  STOKES_PARAMS: tuple[str] = (
69
79
  "I",
70
80
  "Q",
@@ -127,19 +137,59 @@ class VispInputDatasetParameterValues:
127
137
  visp_geo_upsample_factor: float = 10.0
128
138
  visp_geo_max_shift: float = 40.0
129
139
  visp_geo_poly_fit_order: int = 3
130
- visp_solar_spectral_avg_window: WavelengthParameter = WavelengthParameter(
131
- values=(800, 800, 800, 800)
140
+ visp_geo_zone_prominence: WavelengthParameter = WavelengthParameter(values=(0.2, 0.2, 0.3, 0.2))
141
+ visp_geo_zone_width: WavelengthParameter = WavelengthParameter(values=(7, 2, 3, 2))
142
+ visp_geo_zone_bg_order: WavelengthParameter = WavelengthParameter(values=(21, 22, 11, 22))
143
+ visp_geo_zone_normalization_percentile: WavelengthParameter = WavelengthParameter(
144
+ values=(90, 99, 90, 90)
145
+ )
146
+ visp_geo_zone_rel_height: float = 0.97
147
+ visp_solar_spatial_median_filter_width_px: WavelengthParameter = WavelengthParameter(
148
+ values=(250, 250, 250, 250)
132
149
  )
133
150
  visp_solar_characteristic_spatial_normalization_percentile: float = 90.0
134
- visp_solar_zone_prominence: WavelengthParameter = WavelengthParameter(
135
- values=(0.2, 0.2, 0.3, 0.2)
151
+ visp_solar_vignette_initial_continuum_poly_fit_order: int = 6
152
+ visp_solar_vignette_crval_bounds_px: float = 7
153
+ visp_solar_vignette_dispersion_bounds_fraction: float = 0.02
154
+ visp_solar_vignette_wavecal_fit_kwargs: dict[str, Any] = field(
155
+ default_factory=lambda: {
156
+ "method": "differential_evolution",
157
+ "init": "halton",
158
+ "popsize": 1,
159
+ "tol": 1e-10,
160
+ }
136
161
  )
137
- visp_solar_zone_width: WavelengthParameter = WavelengthParameter(values=(7, 2, 3, 2))
138
- visp_solar_zone_bg_order: WavelengthParameter = WavelengthParameter(values=(21, 22, 11, 22))
139
- visp_solar_zone_normalization_percentile: WavelengthParameter = WavelengthParameter(
140
- values=(90, 99, 90, 90)
162
+ visp_solar_vignette_spectral_poly_fit_order: int = 12
163
+ visp_solar_vignette_min_samples: float = 0.9
164
+ visp_wavecal_camera_lens_parameters_1: tuple[float, float, float] = (
165
+ 0.7613,
166
+ 1.720e-4,
167
+ -8.139e-8,
168
+ )
169
+ visp_wavecal_camera_lens_parameters_2: tuple[float, float, float] = (
170
+ 0.9512,
171
+ 2.141e-4,
172
+ -1.014e-7,
141
173
  )
142
- visp_solar_zone_rel_height: float = 0.97
174
+ visp_wavecal_camera_lens_parameters_3: tuple[float, float, float] = (
175
+ 0.1153e1,
176
+ 2.595e-4,
177
+ -1.230e-7,
178
+ )
179
+ visp_wavecal_pixel_pitch_micron_per_pix: float = 6.5
180
+ visp_wavecal_atlas_download_config: dict[str, str] = field(
181
+ default_factory=lambda: {
182
+ "base_url": "doi:10.5281/zenodo.14646787/",
183
+ "telluric_reference_atlas_file_name": "telluric_reference_atlas.npy",
184
+ "telluric_reference_atlas_hash_id": "md5:8db5e12508b293bca3495d81a0747447",
185
+ "solar_reference_atlas_file_name": "solar_reference_atlas.npy",
186
+ "solar_reference_atlas_hash_id": "md5:84ab4c50689ef235fe5ed4f7ee905ca0",
187
+ }
188
+ )
189
+ visp_wavecal_init_crval_guess_normalization_percentile: float = 95
190
+ visp_wavecal_init_resolving_power: int = 150000
191
+ visp_wavecal_init_straylight_fraction: float = 0.2
192
+ visp_wavecal_init_opacity_factor: float = 5.0
143
193
  visp_polcal_spatial_median_filter_width_px: int = 10
144
194
  visp_polcal_num_spatial_bins: int = 10
145
195
  visp_polcal_demod_spatial_smooth_fit_order: int = 17
@@ -159,6 +209,32 @@ def testing_obs_ip_start_time() -> str:
159
209
  return "1946-11-20T12:34:56"
160
210
 
161
211
 
212
+ @pytest.fixture(scope="session")
213
+ def testing_grating_constant() -> float:
214
+ # Just make it different than the defaults in header_models.py
215
+ return 317.2
216
+
217
+
218
+ @pytest.fixture(scope="session")
219
+ def testing_grating_angle() -> float:
220
+ return -43.2
221
+
222
+
223
+ @pytest.fixture(scope="session")
224
+ def testing_arm_position() -> float:
225
+ return -5.3
226
+
227
+
228
+ @pytest.fixture(scope="session")
229
+ def testing_solar_ip_start_time() -> str:
230
+ return "1946-11-21T12:34:56"
231
+
232
+
233
+ @pytest.fixture(scope="session")
234
+ def testing_arm_id() -> int:
235
+ return 2
236
+
237
+
162
238
  @pytest.fixture(scope="session")
163
239
  def input_dataset_document_simple_parameters_part():
164
240
  """Convert a dataclass of parameterValues into an actual input dataset parameters part."""
@@ -185,13 +261,17 @@ def input_dataset_document_simple_parameters_part():
185
261
 
186
262
  @pytest.fixture(scope="session")
187
263
  def assign_input_dataset_doc_to_task(
188
- input_dataset_document_simple_parameters_part, testing_obs_ip_start_time, testing_wavelength
264
+ input_dataset_document_simple_parameters_part,
265
+ testing_obs_ip_start_time,
266
+ testing_wavelength,
267
+ testing_arm_id,
189
268
  ):
190
269
  def update_task(
191
270
  task: WorkflowTaskBase,
192
271
  parameter_values,
193
272
  parameter_class=VispParameters,
194
273
  obs_ip_start_time=testing_obs_ip_start_time,
274
+ arm_id=testing_arm_id,
195
275
  ):
196
276
  task.write(
197
277
  data=InputDatasetPartDocumentList(
@@ -204,6 +284,7 @@ def assign_input_dataset_doc_to_task(
204
284
  scratch=task.scratch,
205
285
  obs_ip_start_time=obs_ip_start_time,
206
286
  wavelength=testing_wavelength,
287
+ arm_id=str(arm_id),
207
288
  )
208
289
 
209
290
  return update_task
@@ -342,28 +423,14 @@ def write_intermediate_background_to_task(
342
423
  )
343
424
 
344
425
 
345
- def write_intermediate_lamp_to_task(
346
- task, *, lamp_signal: float, beam: int, modstate: int, data_shape: tuple[int, int]
347
- ):
348
- lamp_array = np.ones(data_shape) * lamp_signal
349
- task.write(
350
- data=lamp_array,
351
- tags=[
352
- VispTag.intermediate_frame(beam=beam, modstate=modstate),
353
- VispTag.task_lamp_gain(),
354
- ],
355
- encoder=fits_array_encoder,
356
- )
357
-
358
-
359
426
  def write_intermediate_solar_to_task(
360
- task, *, solar_signal: float, beam: int, modstate: int, data_shape: tuple[int, int]
427
+ task, *, solar_signal: float, beam: int, data_shape: tuple[int, int]
361
428
  ):
362
429
  solar_array = np.ones(data_shape) * solar_signal
363
430
  task.write(
364
431
  data=solar_array,
365
432
  tags=[
366
- VispTag.intermediate_frame(beam=beam, modstate=modstate),
433
+ VispTag.intermediate_frame(beam=beam),
367
434
  VispTag.task_solar_gain(),
368
435
  ],
369
436
  encoder=fits_array_encoder,
@@ -413,19 +480,16 @@ def write_intermediate_geometric_to_task(
413
480
  def write_dummy_intermediate_solar_cals_to_task(
414
481
  task,
415
482
  *,
416
- num_modstates: int,
417
483
  data_shape: tuple[int, int],
418
484
  ):
419
485
  solar_signal = 1.0
420
486
  for beam in [1, 2]:
421
- for modstate in range(1, num_modstates + 1):
422
- write_intermediate_solar_to_task(
423
- task=task,
424
- solar_signal=solar_signal,
425
- beam=beam,
426
- modstate=modstate,
427
- data_shape=data_shape,
428
- )
487
+ write_intermediate_solar_to_task(
488
+ task=task,
489
+ solar_signal=solar_signal,
490
+ beam=beam,
491
+ data_shape=data_shape,
492
+ )
429
493
 
430
494
 
431
495
  def write_intermediate_polcal_darks_to_task(
@@ -8,6 +8,7 @@ values.
8
8
  This is very nice, but it's important to understand that the kwargs matter beyond just setting header values; they
9
9
  actually control the output of the generators themselves.
10
10
  """
11
+
11
12
  import uuid
12
13
  from random import choice
13
14
  from random import random
@@ -30,6 +31,12 @@ class VispHeaders(Spec122Dataset):
30
31
  num_modstates_header_value: int = 2,
31
32
  instrument: str = "visp",
32
33
  polarimeter_mode: str = "observe_polarimetric",
34
+ arm_id: int = 1,
35
+ ip_start_time: str = "2022-11-28T13:00:00",
36
+ ip_end_time: str = "2022-11-28T13:00:00",
37
+ grating_constant: float = 316.0,
38
+ grating_angle: float = -69.9,
39
+ arm_position: float = -4.0,
33
40
  **kwargs,
34
41
  ):
35
42
  super().__init__(
@@ -39,14 +46,32 @@ class VispHeaders(Spec122Dataset):
39
46
  instrument=instrument,
40
47
  **kwargs,
41
48
  )
49
+ self.add_constant_key("VISP_001", arm_id)
42
50
  self.add_constant_key("WAVELNTH", 656.30)
43
51
  self.add_constant_key("VISP_010", num_modstates_header_value)
44
52
  self.add_constant_key("ID___013", "TEST_PROPOSAL_ID")
45
53
  self.add_constant_key("VISP_006", polarimeter_mode)
46
54
  self.add_constant_key("PAC__005", "0")
47
55
  self.add_constant_key("PAC__007", "10")
56
+ self.add_constant_key("DKIST011", ip_start_time)
57
+ self.add_constant_key("DKIST012", ip_end_time)
48
58
  self.add_constant_key("FILE_ID", uuid.uuid4().hex)
59
+
60
+ self.add_constant_key("VISP_002", arm_position)
61
+ self.add_constant_key("VISP_013", grating_constant)
62
+ self.add_constant_key("VISP_015", grating_angle)
63
+
49
64
  self.num_modstates_header_value = num_modstates_header_value
65
+ self.add_constant_key("CAM__001", "camera_id")
66
+ self.add_constant_key("CAM__002", "camera_name")
67
+ self.add_constant_key("CAM__003", 1)
68
+ self.add_constant_key("CAM__009", 1)
69
+ self.add_constant_key("CAM__010", 1)
70
+ self.add_constant_key("CAM__011", 1)
71
+ self.add_constant_key("CAM__012", 1)
72
+ self.add_constant_key("ID___014", "v1")
73
+ self.add_constant_key("TELTRACK", "Fixed Solar Rotation Tracking")
74
+ self.add_constant_key("TTBLTRCK", "fixed angle on sun")
50
75
 
51
76
  @key_function("VISP_011")
52
77
  def current_modstate(self, key: str):
@@ -72,6 +97,8 @@ class VispHeadersInputDarkFrames(VispHeaders):
72
97
  num_modstates: int,
73
98
  exp_time: float = 1.0,
74
99
  readout_exp_time: float = 2.0,
100
+ ip_start_time="2022-11-28T13:44:00",
101
+ ip_end_time="2022-11-28T13:45:00",
75
102
  **kwargs,
76
103
  ):
77
104
  ################################################
@@ -84,13 +111,13 @@ class VispHeadersInputDarkFrames(VispHeaders):
84
111
  array_shape,
85
112
  time_delta,
86
113
  num_modstates_header_value=num_modstates,
114
+ ip_start_time=ip_start_time,
115
+ ip_end_time=ip_end_time,
87
116
  **kwargs,
88
117
  )
89
118
  self.add_constant_key("DKIST004", TaskName.dark.value.lower())
90
119
  self.add_constant_key("DKIST008", 1)
91
120
  self.add_constant_key("DKIST009", 1)
92
- self.add_constant_key("DKIST011", "2022-11-28T13:44:00")
93
- self.add_constant_key("DKIST012", "2022-11-28T13:45:00")
94
121
  self.add_constant_key("VISP_019", 1) # Num raster steps
95
122
  self.add_constant_key("VISP_020", 1) # Current raster step
96
123
  self.add_constant_key("ID___004")
@@ -100,6 +127,12 @@ class VispHeadersInputDarkFrames(VispHeaders):
100
127
  self.add_constant_key("CAM__004", exp_time)
101
128
  self.add_constant_key("CAM__005", readout_exp_time)
102
129
  self.add_constant_key("CAM__014", 10) # Num frames per FPA
130
+ self.add_constant_key("TELSCAN", "Raster")
131
+ self.add_constant_key("PAC__002", "lamp")
132
+ self.add_constant_key("PAC__003", "on")
133
+ self.add_constant_key("PAC__004", "Sapphire Polarizer")
134
+ self.add_constant_key("PAC__006", "SiO2 OC")
135
+ self.add_constant_key("PAC__008", "FieldStop (5arcmin)")
103
136
 
104
137
  @key_function("VISP_011")
105
138
  def current_modstate(self, key: str) -> int:
@@ -114,6 +147,8 @@ class VispHeadersInputLampGainFrames(VispHeaders):
114
147
  num_modstates: int,
115
148
  exp_time: float = 10.0,
116
149
  readout_exp_time: float = 20.0,
150
+ ip_start_time="2022-11-28T13:46:00",
151
+ ip_end_time="2022-11-28T13:47:00",
117
152
  **kwargs,
118
153
  ):
119
154
  ################################################
@@ -126,14 +161,14 @@ class VispHeadersInputLampGainFrames(VispHeaders):
126
161
  array_shape,
127
162
  time_delta,
128
163
  num_modstates_header_value=num_modstates,
164
+ ip_start_time=ip_start_time,
165
+ ip_end_time=ip_end_time,
129
166
  **kwargs,
130
167
  )
131
168
  self.add_constant_key("DKIST004", TaskName.gain.value.lower())
132
169
  self.add_constant_key("PAC__002", "lamp")
133
170
  self.add_constant_key("DKIST008", 1)
134
171
  self.add_constant_key("DKIST009", 1)
135
- self.add_constant_key("DKIST011", "2022-11-28T13:46:00")
136
- self.add_constant_key("DKIST012", "2022-11-28T13:47:00")
137
172
  self.add_constant_key("VISP_019", 1)
138
173
  self.add_constant_key("VISP_020", 1)
139
174
  self.add_constant_key("PAC__003", "on")
@@ -155,6 +190,8 @@ class VispHeadersInputSolarGainFrames(VispHeaders):
155
190
  num_modstates: int,
156
191
  exp_time: float = 20.0,
157
192
  readout_exp_time: float = 40.0,
193
+ ip_start_time="2022-11-28T13:48:00",
194
+ ip_end_time="2022-11-28T13:49:00",
158
195
  **kwargs,
159
196
  ):
160
197
  ################################################
@@ -167,16 +204,20 @@ class VispHeadersInputSolarGainFrames(VispHeaders):
167
204
  array_shape,
168
205
  time_delta,
169
206
  num_modstates_header_value=num_modstates,
207
+ ip_start_time=ip_start_time,
208
+ ip_end_time=ip_end_time,
170
209
  **kwargs,
171
210
  )
172
211
  self.add_constant_key("DKIST004", TaskName.gain.value.lower())
173
212
  self.add_constant_key("DKIST008", 1)
174
213
  self.add_constant_key("DKIST009", 1)
175
- self.add_constant_key("DKIST011", "2022-11-28T13:48:00")
176
- self.add_constant_key("DKIST012", "2022-11-28T13:49:00")
177
214
  self.add_constant_key("VISP_019", 1)
178
215
  self.add_constant_key("VISP_020", 1)
179
216
  self.add_constant_key("PAC__002", "clear")
217
+ self.add_constant_key("PAC__003", "off")
218
+ self.add_constant_key("PAC__004", "clear")
219
+ self.add_constant_key("PAC__006", "clear")
220
+ self.add_constant_key("PAC__008", "FieldStop (5arcmin)")
180
221
  self.add_constant_key("TELSCAN", "Raster")
181
222
  self.add_constant_key("ID___004")
182
223
  self.add_constant_key("CAM__004", exp_time)
@@ -197,6 +238,8 @@ class VispHeadersInputPolcalFrames(VispHeaders):
197
238
  num_cs_steps: int = 1,
198
239
  exp_time: float = 0.01,
199
240
  readout_exp_time: float = 0.02,
241
+ ip_start_time="2022-11-28T13:50:00",
242
+ ip_end_time="2022-11-28T13:51:00",
200
243
  **kwargs,
201
244
  ):
202
245
  ################################################
@@ -209,6 +252,8 @@ class VispHeadersInputPolcalFrames(VispHeaders):
209
252
  array_shape,
210
253
  time_delta,
211
254
  num_modstates_header_value=num_modstates,
255
+ ip_start_time=ip_start_time,
256
+ ip_end_time=ip_end_time,
212
257
  **kwargs,
213
258
  )
214
259
  self.index_to_modstate = list(range(1, num_modstates + 1)) * num_cs_steps
@@ -219,8 +264,6 @@ class VispHeadersInputPolcalFrames(VispHeaders):
219
264
  self.add_constant_key("DKIST004", TaskName.polcal.value.lower())
220
265
  self.add_constant_key("DKIST008", 1)
221
266
  self.add_constant_key("DKIST009", 1)
222
- self.add_constant_key("DKIST011", "2022-11-28T13:50:00")
223
- self.add_constant_key("DKIST012", "2022-11-28T13:51:00")
224
267
  self.add_constant_key("VISP_019", 1)
225
268
  self.add_constant_key("VISP_020", 1)
226
269
  self.add_constant_key("TELSCAN", "Raster")
@@ -269,16 +312,23 @@ class VispHeadersInputPolcalDarkFrames(VispHeaders):
269
312
  num_modstates: int,
270
313
  exp_time: float = 0.01,
271
314
  readout_exp_time: float = 0.02,
315
+ ip_start_time="2022-11-28T13:50:00",
316
+ ip_end_time="2022-11-28T13:51:00",
272
317
  **kwargs,
273
318
  ):
274
319
  num_frames = num_modstates
275
320
  dataset_shape = (num_frames, *array_shape[-2:])
276
- super().__init__(dataset_shape, array_shape, time_delta, **kwargs)
321
+ super().__init__(
322
+ dataset_shape,
323
+ array_shape,
324
+ time_delta,
325
+ ip_start_time=ip_start_time,
326
+ ip_end_time=ip_end_time,
327
+ **kwargs,
328
+ )
277
329
  self.add_constant_key("DKIST004", TaskName.polcal.value.lower())
278
330
  self.add_constant_key("DKIST008", 1)
279
331
  self.add_constant_key("DKIST009", 1)
280
- self.add_constant_key("DKIST011", "2022-11-28T13:50:00")
281
- self.add_constant_key("DKIST012", "2022-11-28T13:51:00")
282
332
  self.add_constant_key("VISP_019", 1)
283
333
  self.add_constant_key("VISP_020", 1)
284
334
  self.add_constant_key("TELSCAN", "Raster")
@@ -301,16 +351,23 @@ class VispHeadersInputPolcalGainFrames(VispHeaders):
301
351
  num_modstates: int,
302
352
  exp_time: float = 0.01,
303
353
  readout_exp_time: float = 0.02,
354
+ ip_start_time="2022-11-28T13:50:00",
355
+ ip_end_time="2022-11-28T13:51:00",
304
356
  **kwargs,
305
357
  ):
306
358
  num_frames = num_modstates
307
359
  dataset_shape = (num_frames, *array_shape[-2:])
308
- super().__init__(dataset_shape, array_shape, time_delta, **kwargs)
360
+ super().__init__(
361
+ dataset_shape,
362
+ array_shape,
363
+ time_delta,
364
+ ip_start_time=ip_start_time,
365
+ ip_end_time=ip_end_time,
366
+ **kwargs,
367
+ )
309
368
  self.add_constant_key("DKIST004", TaskName.polcal.value.lower())
310
369
  self.add_constant_key("DKIST008", 1)
311
370
  self.add_constant_key("DKIST009", 1)
312
- self.add_constant_key("DKIST011", "2022-11-28T13:50:00")
313
- self.add_constant_key("DKIST012", "2022-11-28T13:51:00")
314
371
  self.add_constant_key("VISP_019", 1)
315
372
  self.add_constant_key("VISP_020", 1)
316
373
  self.add_constant_key("TELSCAN", "Raster")
@@ -336,6 +393,9 @@ class VispHeadersValidObserveFrames(VispHeaders):
336
393
  exp_time: float = 15.0,
337
394
  readout_exp_time: float = 30.0,
338
395
  abort_last_step: bool = False,
396
+ ip_start_time="2022-11-28T13:55:00",
397
+ ip_end_time="2022-11-28T13:56:00",
398
+ grating_constant=316,
339
399
  **kwargs,
340
400
  ):
341
401
  ################################################
@@ -349,7 +409,15 @@ class VispHeadersValidObserveFrames(VispHeaders):
349
409
  num_frames -= num_dropped_frames
350
410
 
351
411
  dataset_shape = (num_frames, *array_shape[-2:])
352
- super().__init__(dataset_shape, array_shape, time_delta, **kwargs)
412
+ super().__init__(
413
+ dataset_shape,
414
+ array_shape,
415
+ time_delta,
416
+ ip_start_time=ip_start_time,
417
+ ip_end_time=ip_end_time,
418
+ grating_constant=grating_constant,
419
+ **kwargs,
420
+ )
353
421
 
354
422
  self.index_to_map = sum(
355
423
  [[map_num + 1] * num_modstates * num_raster_steps for map_num in range(num_maps)], []
@@ -370,8 +438,6 @@ class VispHeadersValidObserveFrames(VispHeaders):
370
438
 
371
439
  self.num_raster_steps = num_raster_steps
372
440
  self.add_constant_key("DKIST004", TaskName.observe.value.lower())
373
- self.add_constant_key("DKIST011", "2022-11-28T13:55:00") # IP start time
374
- self.add_constant_key("DKIST012", "2022-11-28T13:56:00") # IP end time
375
441
  self.add_constant_key("ID___004")
376
442
  self.add_constant_key("WAVELNTH", 656.28)
377
443
  self.add_constant_key("EXPER_ID", "EXPERIMENT ID")
@@ -418,6 +484,8 @@ class VispHeadersValidCalibratedFrames(VispHeaders):
418
484
  exp_time: float = 15.0,
419
485
  readout_exp_time: float = 30.0,
420
486
  wcs_axis_names: tuple[str, str] | None = None,
487
+ ip_start_time="2022-11-28T13:55:00",
488
+ ip_end_time="2022-11-28T13:56:00",
421
489
  **kwargs,
422
490
  ):
423
491
  ################################################
@@ -431,7 +499,13 @@ class VispHeadersValidCalibratedFrames(VispHeaders):
431
499
  num_frames = num_maps * num_raster_steps * num_stokes
432
500
  dataset_shape = (num_frames, *array_shape[-2:])
433
501
  super().__init__(
434
- dataset_shape, array_shape, time_delta, polarimeter_mode=polarimeter_mode, **kwargs
502
+ dataset_shape,
503
+ array_shape,
504
+ time_delta,
505
+ polarimeter_mode=polarimeter_mode,
506
+ ip_start_time=ip_start_time,
507
+ ip_end_time=ip_end_time,
508
+ **kwargs,
435
509
  )
436
510
 
437
511
  stokes_list = ["I", "Q", "U", "V"][:num_stokes]
@@ -445,8 +519,6 @@ class VispHeadersValidCalibratedFrames(VispHeaders):
445
519
 
446
520
  self.num_raster_steps = num_raster_steps
447
521
  self.add_constant_key("DKIST004", TaskName.observe.value.lower())
448
- self.add_constant_key("DKIST011", "2022-11-28T13:55:00") # IP start time
449
- self.add_constant_key("DKIST012", "2022-11-28T13:56:00") # IP end time
450
522
  self.add_constant_key("ID___004")
451
523
  self.add_constant_key("WAVELNTH", 656.28)
452
524
  self.add_constant_key("EXPER_ID", "EXPERIMENT ID")
@@ -37,15 +37,15 @@ from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers impor
37
37
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveInstPolCal
38
38
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveLampCal
39
39
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SaveSolarCal
40
- from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
41
- set_observe_wavelength_task,
42
- )
43
40
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SetNumModstates
44
41
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SetObserveExpTime
45
42
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
46
43
  SetObserveIpStartTime,
47
44
  )
48
45
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import SetPolarimeterMode
46
+ from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
47
+ set_observe_wavelength_task,
48
+ )
49
49
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import tag_inputs_task
50
50
  from dkist_processing_visp.tests.local_trial_workflows.local_trial_helpers import (
51
51
  translate_122_to_214l0_task,
@@ -74,6 +74,7 @@ class CreateInputDatasetParameterDocument(WorkflowTaskBase):
74
74
  relative_path=relative_path,
75
75
  tags=VispTag.input_dataset_parameters(),
76
76
  encoder=basemodel_encoder,
77
+ overwrite=True,
77
78
  )
78
79
  logger.info(f"Wrote input dataset parameter doc to {relative_path}")
79
80
 
@@ -99,21 +100,6 @@ class CreateInputDatasetParameterDocument(WorkflowTaskBase):
99
100
  return parameters_list
100
101
 
101
102
 
102
- def setup_APM_config() -> None:
103
- mesh_config = {
104
- "system-monitoring-log-apm": {
105
- "mesh_address": "system-monitoring-log-apm.service.sim.consul",
106
- "mesh_port": 8200,
107
- },
108
- "automated-processing-scratch-inventory": {"mesh_address": "localhost", "mesh_port": 6379},
109
- "internal-api-gateway": {"mesh_address": "localhost", "mesh_port": 80},
110
- }
111
- apm_options = {"TRANSACTION_MAX_SPANS": 10000}
112
- os.environ["MESH_CONFIG"] = json.dumps(mesh_config)
113
- os.environ["ELASTIC_APM_ENABLED"] = "true"
114
- os.environ["ELASTIC_APM_OTHER_OPTIONS"] = json.dumps(apm_options)
115
-
116
-
117
103
  def main(
118
104
  scratch_path: str,
119
105
  suffix: str = "FITS",
@@ -127,11 +113,8 @@ def main(
127
113
  load_geometric: bool = False,
128
114
  load_solar: bool = False,
129
115
  load_inst_pol: bool = False,
130
- use_apm: bool = False,
131
116
  dummy_wavelength: float = 630.0,
132
117
  ):
133
- if use_apm:
134
- setup_APM_config()
135
118
  with ManualProcessing(
136
119
  workflow_path=scratch_path,
137
120
  recipe_run_id=recipe_run_id,
@@ -264,7 +247,6 @@ if __name__ == "__main__":
264
247
  help="Load instrument polarization calibration from previously saved run",
265
248
  action="store_true",
266
249
  )
267
- parser.add_argument("-A", "--use-apm", help="Send APM spans to SIM", action="store_true")
268
250
  args = parser.parse_args()
269
251
  sys.exit(
270
252
  main(
@@ -280,6 +262,5 @@ if __name__ == "__main__":
280
262
  load_geometric=args.load_geometric,
281
263
  load_solar=args.load_solar,
282
264
  load_inst_pol=args.load_inst_pol,
283
- use_apm=args.use_apm,
284
265
  )
285
266
  )