dkist-processing-vbi 1.30.0__tar.gz → 1.30.2__tar.gz

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 (82) hide show
  1. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/CHANGELOG.rst +24 -0
  2. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/PKG-INFO +8 -8
  3. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/dark.py +1 -1
  4. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/gain.py +1 -1
  5. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/science.py +1 -1
  6. dkist_processing_vbi-1.30.2/dkist_processing_vbi/tasks/vbi_base.py +59 -0
  7. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/write_l1.py +1 -0
  8. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_dark.py +13 -12
  9. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_gain.py +12 -8
  10. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_science.py +10 -8
  11. dkist_processing_vbi-1.30.2/dkist_processing_vbi/tests/test_vbi_base.py +95 -0
  12. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi.egg-info/PKG-INFO +8 -8
  13. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi.egg-info/requires.txt +7 -7
  14. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/pyproject.toml +9 -9
  15. dkist_processing_vbi-1.30.0/dkist_processing_vbi/tasks/vbi_base.py +0 -31
  16. dkist_processing_vbi-1.30.0/dkist_processing_vbi/tests/test_vbi_base.py +0 -37
  17. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/.gitignore +0 -0
  18. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/.pre-commit-config.yaml +0 -0
  19. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/.readthedocs.yml +0 -0
  20. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/.snyk +0 -0
  21. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/README.rst +0 -0
  22. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/SCIENCE_CHANGELOG.rst +0 -0
  23. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/bitbucket-pipelines.yml +0 -0
  24. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/changelog/.gitempty +0 -0
  25. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/__init__.py +0 -0
  26. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/config.py +0 -0
  27. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/models/__init__.py +0 -0
  28. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/models/constants.py +0 -0
  29. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/models/filter.py +0 -0
  30. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/models/fits_access.py +0 -0
  31. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/models/parameters.py +0 -0
  32. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/models/tags.py +0 -0
  33. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/parsers/__init__.py +0 -0
  34. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/parsers/mosaic_repeats.py +0 -0
  35. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/parsers/spatial_step_pattern.py +0 -0
  36. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/parsers/vbi_l0_fits_access.py +0 -0
  37. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/parsers/vbi_l1_fits_access.py +0 -0
  38. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/__init__.py +0 -0
  39. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/assemble_movie.py +0 -0
  40. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/make_movie_frames.py +0 -0
  41. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/parse.py +0 -0
  42. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/process_summit_processed.py +0 -0
  43. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tasks/quality_metrics.py +0 -0
  44. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/__init__.py +0 -0
  45. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/conftest.py +0 -0
  46. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/local_trial_workflows/__init__.py +0 -0
  47. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/local_trial_workflows/l0_to_l1.py +0 -0
  48. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_assemble_movie.py +0 -0
  49. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_fits_access.py +0 -0
  50. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_make_movie_frames.py +0 -0
  51. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_parse_l0.py +0 -0
  52. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_parse_summit.py +0 -0
  53. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_process_summit.py +0 -0
  54. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_quality_metrics.py +0 -0
  55. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_spatial_step_pattern.py +0 -0
  56. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_vbi_constants.py +0 -0
  57. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_workflows.py +0 -0
  58. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/tests/test_write_l1.py +0 -0
  59. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/workflows/__init__.py +0 -0
  60. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/workflows/l0_processing.py +0 -0
  61. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/workflows/summit_data_processing.py +0 -0
  62. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi/workflows/trial_workflows.py +0 -0
  63. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi.egg-info/SOURCES.txt +0 -0
  64. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi.egg-info/dependency_links.txt +0 -0
  65. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/dkist_processing_vbi.egg-info/top_level.txt +0 -0
  66. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/Makefile +0 -0
  67. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/changelog.rst +0 -0
  68. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/conf.py +0 -0
  69. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/index.rst +0 -0
  70. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/l0_to_l1_vbi_no-speckle-full-trial.rst +0 -0
  71. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/l0_to_l1_vbi_no-speckle.rst +0 -0
  72. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/l0_to_l1_vbi_summit-calibrated-full-trial.rst +0 -0
  73. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/l0_to_l1_vbi_summit-calibrated.rst +0 -0
  74. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/landing_page.rst +0 -0
  75. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/make.bat +0 -0
  76. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/requirements.txt +0 -0
  77. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/requirements_table.rst +0 -0
  78. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/docs/scientific_changelog.rst +0 -0
  79. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/licenses/LICENSE.rst +0 -0
  80. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/science_towncrier.sh +0 -0
  81. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/setup.cfg +0 -0
  82. {dkist_processing_vbi-1.30.0 → dkist_processing_vbi-1.30.2}/towncrier_science.toml +0 -0
@@ -1,3 +1,27 @@
1
+ v1.30.2 (2026-05-04)
2
+ ====================
3
+
4
+ Features
5
+ --------
6
+
7
+ - Add `quality_write_intermediate_task_type_counts` method to `VbiTaskBase` workflow task. (`#201 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/201>`__)
8
+
9
+
10
+ Misc
11
+ ----
12
+
13
+ - Update dkist-processing-common to 14.0.2 which converts TASK_TYPES quality metric to the new methodology. (`#201 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/201>`__)
14
+
15
+
16
+ v1.30.1 (2026-05-04)
17
+ ====================
18
+
19
+ Bugfixes
20
+ --------
21
+
22
+ - Squeeze axes of length 1 out of VBI statistics calculations. (`#202 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/202>`__)
23
+
24
+
1
25
  v1.30.0 (2026-05-04)
2
26
  ====================
3
27
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-vbi
3
- Version: 1.30.0
3
+ Version: 1.30.2
4
4
  Summary: Processing code for the VBI instrument on DKIST
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/x-rst
16
- Requires-Dist: dkist-processing-common==14.0.1
16
+ Requires-Dist: dkist-processing-common==14.0.2
17
17
  Requires-Dist: dkist-processing-math==2.2.2
18
18
  Requires-Dist: dkist-header-validator==5.3.1
19
19
  Requires-Dist: dkist-fits-specifications==4.25.0
@@ -101,8 +101,8 @@ Requires-Dist: asyncpg==0.31.0; extra == "frozen"
101
101
  Requires-Dist: attrs==26.1.0; extra == "frozen"
102
102
  Requires-Dist: babel==2.18.0; extra == "frozen"
103
103
  Requires-Dist: billiard==4.2.4; extra == "frozen"
104
- Requires-Dist: boto3==1.43.2; extra == "frozen"
105
- Requires-Dist: botocore==1.43.2; extra == "frozen"
104
+ Requires-Dist: boto3==1.43.3; extra == "frozen"
105
+ Requires-Dist: botocore==1.43.3; extra == "frozen"
106
106
  Requires-Dist: cadwyn==5.4.6; extra == "frozen"
107
107
  Requires-Dist: celery==5.6.3; extra == "frozen"
108
108
  Requires-Dist: certifi==2026.4.22; extra == "frozen"
@@ -116,16 +116,16 @@ Requires-Dist: colorlog==6.10.1; extra == "frozen"
116
116
  Requires-Dist: contourpy==1.3.3; extra == "frozen"
117
117
  Requires-Dist: cron_descriptor==2.0.8; extra == "frozen"
118
118
  Requires-Dist: croniter==6.2.2; extra == "frozen"
119
- Requires-Dist: cryptography==47.0.0; extra == "frozen"
119
+ Requires-Dist: cryptography==48.0.0; extra == "frozen"
120
120
  Requires-Dist: cycler==0.12.1; extra == "frozen"
121
121
  Requires-Dist: decorator==5.2.1; extra == "frozen"
122
122
  Requires-Dist: dill==0.4.1; extra == "frozen"
123
123
  Requires-Dist: dkist-header-validator==5.3.1; extra == "frozen"
124
- Requires-Dist: dkist-processing-common==14.0.1; extra == "frozen"
124
+ Requires-Dist: dkist-processing-common==14.0.2; extra == "frozen"
125
125
  Requires-Dist: dkist-processing-core==7.2.1; extra == "frozen"
126
126
  Requires-Dist: dkist-processing-math==2.2.2; extra == "frozen"
127
127
  Requires-Dist: dkist-processing-pac==3.1.2; extra == "frozen"
128
- Requires-Dist: dkist-processing-vbi==1.30.0; extra == "frozen"
128
+ Requires-Dist: dkist-processing-vbi==1.30.2; extra == "frozen"
129
129
  Requires-Dist: dkist-service-configuration==4.3.0; extra == "frozen"
130
130
  Requires-Dist: dkist-spectral-lines==3.0.1; extra == "frozen"
131
131
  Requires-Dist: dkist_fits_specifications==4.25.0; extra == "frozen"
@@ -211,7 +211,7 @@ Requires-Dist: pathspec==1.1.1; extra == "frozen"
211
211
  Requires-Dist: pendulum==3.2.0; extra == "frozen"
212
212
  Requires-Dist: pika==1.3.2; extra == "frozen"
213
213
  Requires-Dist: pillow==10.4.0; extra == "frozen"
214
- Requires-Dist: pip==26.1; extra == "frozen"
214
+ Requires-Dist: pip==26.1.1; extra == "frozen"
215
215
  Requires-Dist: platformdirs==4.9.6; extra == "frozen"
216
216
  Requires-Dist: pluggy==1.6.0; extra == "frozen"
217
217
  Requires-Dist: pooch==1.9.0; extra == "frozen"
@@ -90,7 +90,7 @@ class DarkCalibration(VbiTaskBase, QualityMixin):
90
90
  with self.telemetry_span("Computing and logging quality metrics"):
91
91
  no_of_raw_dark_frames: int = self.count(tags=[VbiTag.input(), VbiTag.task_dark_frame()])
92
92
  unused_count = no_of_raw_dark_frames - total_dark_frames_used
93
- self.quality_store_task_type_counts(
93
+ self.quality_write_intermediate_task_type_counts(
94
94
  task_type=TaskName.dark.value,
95
95
  total_frames=no_of_raw_dark_frames,
96
96
  frames_not_used=unused_count,
@@ -113,7 +113,7 @@ class GainCalibration(VbiTaskBase, QualityMixin):
113
113
  VbiTag.task_gain_frame(),
114
114
  ],
115
115
  )
116
- self.quality_store_task_type_counts(
116
+ self.quality_write_intermediate_task_type_counts(
117
117
  task_type=TaskName.gain.value, total_frames=no_of_raw_gain_frames
118
118
  )
119
119
 
@@ -114,7 +114,7 @@ class ScienceCalibration(VbiTaskBase, QualityMixin):
114
114
  VbiTag.task_observe(),
115
115
  ],
116
116
  )
117
- self.quality_store_task_type_counts(
117
+ self.quality_write_intermediate_task_type_counts(
118
118
  task_type=TaskName.observe.value, total_frames=no_of_raw_obs_frames
119
119
  )
120
120
 
@@ -0,0 +1,59 @@
1
+ """VBI base task."""
2
+
3
+ from abc import ABC
4
+
5
+ from dkist_processing_common.codecs.basemodel import basemodel_encoder
6
+ from dkist_processing_common.models.metric_code import MetricCode
7
+ from dkist_processing_common.models.quality import TaskCount
8
+ from dkist_processing_common.tasks import WorkflowTaskBase
9
+
10
+ from dkist_processing_vbi.models.constants import VbiConstants
11
+ from dkist_processing_vbi.models.tags import VbiTag
12
+
13
+
14
+ class VbiTaskBase(WorkflowTaskBase, ABC):
15
+ """
16
+ Task class for base VBI tasks.
17
+
18
+ Parameters
19
+ ----------
20
+ recipe_run_id : int
21
+ id of the recipe run used to identify the workflow run this task is part of
22
+ workflow_name : str
23
+ name of the workflow to which this instance of the task belongs
24
+ workflow_version : str
25
+ version of the workflow to which this instance of the task belongs
26
+
27
+ """
28
+
29
+ # So tab completion shows all the ViSP constants
30
+ constants: VbiConstants
31
+
32
+ @property
33
+ def constants_model_class(self):
34
+ """Provide VBI constants access."""
35
+ return VbiConstants
36
+
37
+ def quality_write_intermediate_task_type_counts(
38
+ self, task_type: str, total_frames: int, frames_not_used: int = 0
39
+ ):
40
+ """
41
+ Write intermediate task type data.
42
+
43
+ Parameters
44
+ ----------
45
+ task_type:
46
+ task type as listed in the headers
47
+ total_frames:
48
+ total number of frames supplied of the given task type
49
+ frames_not_used:
50
+ if some frames aren't used, how many
51
+ """
52
+ task_count = TaskCount(
53
+ task_type=task_type,
54
+ total_frames=total_frames,
55
+ frames_not_used=frames_not_used,
56
+ )
57
+ self.write(
58
+ task_count, tags=VbiTag.quality(MetricCode.task_types), encoder=basemodel_encoder
59
+ )
@@ -197,6 +197,7 @@ class VbiWriteL1Frame(WriteL1Frame):
197
197
  y_axis_length = header["NAXIS1"]
198
198
  x_start = x_axis_length // 2 - central_patch_side_length // 2
199
199
  y_start = y_axis_length // 2 - central_patch_side_length // 2
200
+ data = np.squeeze(data) # remove any axis of length 1, if it exists
200
201
  central_patch_data = data[
201
202
  y_start : y_start + central_patch_side_length,
202
203
  x_start : x_start + central_patch_side_length,
@@ -1,11 +1,11 @@
1
- import json
2
-
3
1
  import numpy as np
4
2
  import pytest
5
3
  from astropy.io import fits
6
4
  from dkist_processing_common._util.scratch import WorkflowFileSystem
5
+ from dkist_processing_common.codecs.basemodel import basemodel_decoder
7
6
  from dkist_processing_common.codecs.fits import fits_array_decoder
8
7
  from dkist_processing_common.codecs.fits import fits_array_encoder
8
+ from dkist_processing_common.models.quality import TaskCount
9
9
  from dkist_processing_common.models.tags import Tag
10
10
 
11
11
  from dkist_processing_vbi.models.tags import VbiTag
@@ -100,13 +100,14 @@ def test_dark_calibration_task(dark_calibration_task, mocker, fake_gql_client):
100
100
 
101
101
  num_darks = dark_calibration_task.count(tags=[VbiTag.input(), VbiTag.task_dark_frame()])
102
102
 
103
- quality_files = list(dark_calibration_task.read(tags=[Tag.quality("TASK_TYPES")]))
104
- for file in quality_files:
105
- with file.open() as f:
106
- data = json.load(f)
107
- assert isinstance(data, dict)
108
- assert data["total_frames"] == num_darks
109
- assert (
110
- data["frames_not_used"]
111
- == dark_calibration_task.num_steps * dark_calibration_task.num_exp_per_step
112
- )
103
+ task_counts: list[TaskCount] = list(
104
+ dark_calibration_task.read(
105
+ tags=Tag.quality("TASK_TYPES"), decoder=basemodel_decoder, model=TaskCount
106
+ )
107
+ )
108
+ assert isinstance(task_counts, list)
109
+ assert len(task_counts) == 1
110
+ assert task_counts[0].task_type == "DARK"
111
+ assert task_counts[0].total_frames == num_darks
112
+ unused = dark_calibration_task.num_steps * dark_calibration_task.num_exp_per_step
113
+ assert task_counts[0].frames_not_used == unused
@@ -1,11 +1,11 @@
1
- import json
2
-
3
1
  import numpy as np
4
2
  import pytest
5
3
  from dkist_processing_common._util.scratch import WorkflowFileSystem
4
+ from dkist_processing_common.codecs.basemodel import basemodel_decoder
6
5
  from dkist_processing_common.codecs.fits import fits_array_decoder
7
6
  from dkist_processing_common.codecs.fits import fits_array_encoder
8
7
  from dkist_processing_common.codecs.fits import fits_hdulist_encoder
8
+ from dkist_processing_common.models.quality import TaskCount
9
9
  from dkist_processing_common.models.tags import Tag
10
10
 
11
11
  from dkist_processing_vbi.models.tags import VbiTag
@@ -94,9 +94,13 @@ def test_gain_calibration(gain_calibration_task, mocker, fake_gql_client):
94
94
  gain_calibration_task.read(tags=[VbiTag.input(), VbiTag.task_gain_frame()])
95
95
  )
96
96
 
97
- quality_files = list(gain_calibration_task.read(tags=[Tag.quality("TASK_TYPES")]))
98
- for file in quality_files:
99
- with file.open() as f:
100
- data = json.load(f)
101
- assert isinstance(data, dict)
102
- assert data["total_frames"] == len(input_gain_frames)
97
+ task_counts: list[TaskCount] = list(
98
+ gain_calibration_task.read(
99
+ tags=Tag.quality("TASK_TYPES"), decoder=basemodel_decoder, model=TaskCount
100
+ )
101
+ )
102
+ assert isinstance(task_counts, list)
103
+ assert len(task_counts) == 1
104
+ assert task_counts[0].task_type == "GAIN"
105
+ assert task_counts[0].total_frames == len(input_gain_frames)
106
+ assert task_counts[0].frames_not_used == 0
@@ -1,12 +1,12 @@
1
- import json
2
-
3
1
  import numpy as np
4
2
  import pytest
5
3
  from astropy.io import fits
6
4
  from dkist_processing_common._util.scratch import WorkflowFileSystem
5
+ from dkist_processing_common.codecs.basemodel import basemodel_decoder
7
6
  from dkist_processing_common.codecs.fits import fits_array_encoder
8
7
  from dkist_processing_common.codecs.fits import fits_hdu_decoder
9
8
  from dkist_processing_common.codecs.fits import fits_hdulist_encoder
9
+ from dkist_processing_common.models.quality import TaskCount
10
10
  from dkist_processing_common.models.tags import Tag
11
11
 
12
12
  from dkist_processing_vbi.models.tags import VbiTag
@@ -149,9 +149,11 @@ def test_science_calibration(science_calibration_task, mocker, fake_gql_client):
149
149
 
150
150
  input_obs_frames = list(task.read(tags=[VbiTag.input(), VbiTag.frame(), VbiTag.task_observe()]))
151
151
 
152
- quality_files = list(task.read(tags=[Tag.quality("TASK_TYPES")]))
153
- for file in quality_files:
154
- with file.open() as f:
155
- data = json.load(f)
156
- assert isinstance(data, dict)
157
- assert data["total_frames"] == len(input_obs_frames)
152
+ task_counts: list[TaskCount] = list(
153
+ task.read(tags=Tag.quality("TASK_TYPES"), decoder=basemodel_decoder, model=TaskCount)
154
+ )
155
+ assert isinstance(task_counts, list)
156
+ assert len(task_counts) == 1
157
+ assert task_counts[0].task_type == "OBSERVE"
158
+ assert task_counts[0].total_frames == len(input_obs_frames)
159
+ assert task_counts[0].frames_not_used == 0
@@ -0,0 +1,95 @@
1
+ import pytest
2
+ from dkist_processing_common.codecs.basemodel import basemodel_decoder
3
+ from dkist_processing_common.models.quality import TaskCount
4
+
5
+ from dkist_processing_vbi.tasks.vbi_base import VbiTaskBase
6
+
7
+
8
+ @pytest.fixture
9
+ def expected_constants_dict():
10
+ # Just make up a super simple db
11
+ return {"NUM_SPATIAL_STEPS": 4, "OBS_IP_START_TIME": "2022-11-28T13:54:00"}
12
+
13
+
14
+ @pytest.fixture(scope="function")
15
+ def vbi_science_task(recipe_run_id, expected_constants_dict):
16
+ class DummyTask(VbiTaskBase):
17
+ def run(self):
18
+ pass
19
+
20
+ task = DummyTask(
21
+ recipe_run_id=recipe_run_id,
22
+ workflow_name="vbi_dummy_task",
23
+ workflow_version="VX.Y",
24
+ )
25
+
26
+ task.constants._update(expected_constants_dict)
27
+ yield task
28
+ task._purge()
29
+
30
+
31
+ @pytest.fixture(scope="function")
32
+ def vbi_base_task(recipe_run_id):
33
+ class DummyTask(VbiTaskBase):
34
+ def run(self):
35
+ pass
36
+
37
+ task = DummyTask(
38
+ recipe_run_id=recipe_run_id,
39
+ workflow_name="vbi_dummy_task",
40
+ workflow_version="VX.Y",
41
+ )
42
+
43
+ yield task
44
+ task._purge()
45
+
46
+
47
+ def test_constants_init(vbi_science_task, expected_constants_dict):
48
+ """
49
+ Given: A VbiTaskBase with a populated backend ConstantsDb
50
+ When: Initializing the task
51
+ Then: The .constants attribute is loaded correctly
52
+ """
53
+ constants_obj = vbi_science_task.constants
54
+ for k, v in expected_constants_dict.items():
55
+ assert getattr(constants_obj, k.lower()) == v
56
+
57
+
58
+ @pytest.mark.parametrize(
59
+ "task_type, total_frames, frames_not_used",
60
+ [
61
+ pytest.param("one", 1, 1, id="simple"),
62
+ pytest.param("two", 2, 0, id="not_used_zero"),
63
+ pytest.param("three", 3, None, id="not_used_none"),
64
+ ],
65
+ )
66
+ def test_quality_write_intermediate_task_type_counts(
67
+ task_type: str, total_frames: int, frames_not_used: int | None, vbi_base_task
68
+ ):
69
+ """
70
+ Given: Valid intermediate task type count input
71
+ When: Running VbiTaskBase quality_write_intermediate_task_type_counts()
72
+ Then: A single TaskCount file gets created
73
+ """
74
+ # Given
75
+ task = vbi_base_task
76
+
77
+ # When
78
+ if frames_not_used is not None:
79
+ task.quality_write_intermediate_task_type_counts(task_type, total_frames, frames_not_used)
80
+ else:
81
+ task.quality_write_intermediate_task_type_counts(task_type, total_frames)
82
+
83
+ # Then
84
+ task_counts: list[TaskCount] = list(
85
+ task.read(tags="QUALITY_TASK_TYPES", decoder=basemodel_decoder, model=TaskCount)
86
+ )
87
+ assert isinstance(task_counts, list)
88
+ assert len(task_counts) == 1
89
+ task_count = task_counts[0]
90
+ assert task_count.task_type == str(task_type).upper()
91
+ assert task_count.total_frames == total_frames
92
+ if frames_not_used is not None:
93
+ assert task_count.frames_not_used == frames_not_used
94
+ else:
95
+ assert task_count.frames_not_used == 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-vbi
3
- Version: 1.30.0
3
+ Version: 1.30.2
4
4
  Summary: Processing code for the VBI instrument on DKIST
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/x-rst
16
- Requires-Dist: dkist-processing-common==14.0.1
16
+ Requires-Dist: dkist-processing-common==14.0.2
17
17
  Requires-Dist: dkist-processing-math==2.2.2
18
18
  Requires-Dist: dkist-header-validator==5.3.1
19
19
  Requires-Dist: dkist-fits-specifications==4.25.0
@@ -101,8 +101,8 @@ Requires-Dist: asyncpg==0.31.0; extra == "frozen"
101
101
  Requires-Dist: attrs==26.1.0; extra == "frozen"
102
102
  Requires-Dist: babel==2.18.0; extra == "frozen"
103
103
  Requires-Dist: billiard==4.2.4; extra == "frozen"
104
- Requires-Dist: boto3==1.43.2; extra == "frozen"
105
- Requires-Dist: botocore==1.43.2; extra == "frozen"
104
+ Requires-Dist: boto3==1.43.3; extra == "frozen"
105
+ Requires-Dist: botocore==1.43.3; extra == "frozen"
106
106
  Requires-Dist: cadwyn==5.4.6; extra == "frozen"
107
107
  Requires-Dist: celery==5.6.3; extra == "frozen"
108
108
  Requires-Dist: certifi==2026.4.22; extra == "frozen"
@@ -116,16 +116,16 @@ Requires-Dist: colorlog==6.10.1; extra == "frozen"
116
116
  Requires-Dist: contourpy==1.3.3; extra == "frozen"
117
117
  Requires-Dist: cron_descriptor==2.0.8; extra == "frozen"
118
118
  Requires-Dist: croniter==6.2.2; extra == "frozen"
119
- Requires-Dist: cryptography==47.0.0; extra == "frozen"
119
+ Requires-Dist: cryptography==48.0.0; extra == "frozen"
120
120
  Requires-Dist: cycler==0.12.1; extra == "frozen"
121
121
  Requires-Dist: decorator==5.2.1; extra == "frozen"
122
122
  Requires-Dist: dill==0.4.1; extra == "frozen"
123
123
  Requires-Dist: dkist-header-validator==5.3.1; extra == "frozen"
124
- Requires-Dist: dkist-processing-common==14.0.1; extra == "frozen"
124
+ Requires-Dist: dkist-processing-common==14.0.2; extra == "frozen"
125
125
  Requires-Dist: dkist-processing-core==7.2.1; extra == "frozen"
126
126
  Requires-Dist: dkist-processing-math==2.2.2; extra == "frozen"
127
127
  Requires-Dist: dkist-processing-pac==3.1.2; extra == "frozen"
128
- Requires-Dist: dkist-processing-vbi==1.30.0; extra == "frozen"
128
+ Requires-Dist: dkist-processing-vbi==1.30.2; extra == "frozen"
129
129
  Requires-Dist: dkist-service-configuration==4.3.0; extra == "frozen"
130
130
  Requires-Dist: dkist-spectral-lines==3.0.1; extra == "frozen"
131
131
  Requires-Dist: dkist_fits_specifications==4.25.0; extra == "frozen"
@@ -211,7 +211,7 @@ Requires-Dist: pathspec==1.1.1; extra == "frozen"
211
211
  Requires-Dist: pendulum==3.2.0; extra == "frozen"
212
212
  Requires-Dist: pika==1.3.2; extra == "frozen"
213
213
  Requires-Dist: pillow==10.4.0; extra == "frozen"
214
- Requires-Dist: pip==26.1; extra == "frozen"
214
+ Requires-Dist: pip==26.1.1; extra == "frozen"
215
215
  Requires-Dist: platformdirs==4.9.6; extra == "frozen"
216
216
  Requires-Dist: pluggy==1.6.0; extra == "frozen"
217
217
  Requires-Dist: pooch==1.9.0; extra == "frozen"
@@ -1,4 +1,4 @@
1
- dkist-processing-common==14.0.1
1
+ dkist-processing-common==14.0.2
2
2
  dkist-processing-math==2.2.2
3
3
  dkist-header-validator==5.3.1
4
4
  dkist-fits-specifications==4.25.0
@@ -71,8 +71,8 @@ asyncpg==0.31.0
71
71
  attrs==26.1.0
72
72
  babel==2.18.0
73
73
  billiard==4.2.4
74
- boto3==1.43.2
75
- botocore==1.43.2
74
+ boto3==1.43.3
75
+ botocore==1.43.3
76
76
  cadwyn==5.4.6
77
77
  celery==5.6.3
78
78
  certifi==2026.4.22
@@ -86,16 +86,16 @@ colorlog==6.10.1
86
86
  contourpy==1.3.3
87
87
  cron_descriptor==2.0.8
88
88
  croniter==6.2.2
89
- cryptography==47.0.0
89
+ cryptography==48.0.0
90
90
  cycler==0.12.1
91
91
  decorator==5.2.1
92
92
  dill==0.4.1
93
93
  dkist-header-validator==5.3.1
94
- dkist-processing-common==14.0.1
94
+ dkist-processing-common==14.0.2
95
95
  dkist-processing-core==7.2.1
96
96
  dkist-processing-math==2.2.2
97
97
  dkist-processing-pac==3.1.2
98
- dkist-processing-vbi==1.30.0
98
+ dkist-processing-vbi==1.30.2
99
99
  dkist-service-configuration==4.3.0
100
100
  dkist-spectral-lines==3.0.1
101
101
  dkist_fits_specifications==4.25.0
@@ -181,7 +181,7 @@ pathspec==1.1.1
181
181
  pendulum==3.2.0
182
182
  pika==1.3.2
183
183
  pillow==10.4.0
184
- pip==26.1
184
+ pip==26.1.1
185
185
  platformdirs==4.9.6
186
186
  pluggy==1.6.0
187
187
  pooch==1.9.0
@@ -9,8 +9,8 @@ exclude = ["build*"]
9
9
 
10
10
  [tool.dkist-dev-tools]
11
11
  # Most recently frozen version by dkist-dev-tools
12
- version = "1.30.0"
13
- date = 2026-05-04T09:29:02.126389
12
+ version = "1.30.2"
13
+ date = 2026-05-04T19:28:09.417804
14
14
 
15
15
  [project]
16
16
  dynamic = ["version"]
@@ -26,7 +26,7 @@ classifiers = [
26
26
  "Programming Language :: Python :: 3.13",
27
27
  ]
28
28
  dependencies = [
29
- "dkist-processing-common == 14.0.1",
29
+ "dkist-processing-common == 14.0.2",
30
30
  "dkist-processing-math == 2.2.2",
31
31
  "dkist-header-validator == 5.3.1",
32
32
  "dkist-fits-specifications == 4.25.0",
@@ -129,8 +129,8 @@ frozen = [
129
129
  "attrs == 26.1.0",
130
130
  "babel == 2.18.0",
131
131
  "billiard == 4.2.4",
132
- "boto3 == 1.43.2",
133
- "botocore == 1.43.2",
132
+ "boto3 == 1.43.3",
133
+ "botocore == 1.43.3",
134
134
  "cadwyn == 5.4.6",
135
135
  "celery == 5.6.3",
136
136
  "certifi == 2026.4.22",
@@ -144,16 +144,16 @@ frozen = [
144
144
  "contourpy == 1.3.3",
145
145
  "cron_descriptor == 2.0.8",
146
146
  "croniter == 6.2.2",
147
- "cryptography == 47.0.0",
147
+ "cryptography == 48.0.0",
148
148
  "cycler == 0.12.1",
149
149
  "decorator == 5.2.1",
150
150
  "dill == 0.4.1",
151
151
  "dkist-header-validator == 5.3.1",
152
- "dkist-processing-common == 14.0.1",
152
+ "dkist-processing-common == 14.0.2",
153
153
  "dkist-processing-core == 7.2.1",
154
154
  "dkist-processing-math == 2.2.2",
155
155
  "dkist-processing-pac == 3.1.2",
156
- "dkist-processing-vbi == 1.30.0",
156
+ "dkist-processing-vbi == 1.30.2",
157
157
  "dkist-service-configuration == 4.3.0",
158
158
  "dkist-spectral-lines == 3.0.1",
159
159
  "dkist_fits_specifications == 4.25.0",
@@ -239,7 +239,7 @@ frozen = [
239
239
  "pendulum == 3.2.0",
240
240
  "pika == 1.3.2",
241
241
  "pillow == 10.4.0",
242
- "pip == 26.1",
242
+ "pip == 26.1.1",
243
243
  "platformdirs == 4.9.6",
244
244
  "pluggy == 1.6.0",
245
245
  "pooch == 1.9.0",
@@ -1,31 +0,0 @@
1
- """VBI base task."""
2
-
3
- from abc import ABC
4
-
5
- from dkist_processing_common.tasks import WorkflowTaskBase
6
-
7
- from dkist_processing_vbi.models.constants import VbiConstants
8
-
9
-
10
- class VbiTaskBase(WorkflowTaskBase, ABC):
11
- """
12
- Task class for base VBI tasks.
13
-
14
- Parameters
15
- ----------
16
- recipe_run_id : int
17
- id of the recipe run used to identify the workflow run this task is part of
18
- workflow_name : str
19
- name of the workflow to which this instance of the task belongs
20
- workflow_version : str
21
- version of the workflow to which this instance of the task belongs
22
-
23
- """
24
-
25
- # So tab completion shows all the ViSP constants
26
- constants: VbiConstants
27
-
28
- @property
29
- def constants_model_class(self):
30
- """Provide VBI constants access."""
31
- return VbiConstants
@@ -1,37 +0,0 @@
1
- import pytest
2
-
3
- from dkist_processing_vbi.tasks.vbi_base import VbiTaskBase
4
-
5
-
6
- @pytest.fixture
7
- def expected_constants_dict():
8
- # Just make up a super simple db
9
- return {"NUM_SPATIAL_STEPS": 4, "OBS_IP_START_TIME": "2022-11-28T13:54:00"}
10
-
11
-
12
- @pytest.fixture(scope="function")
13
- def vbi_science_task(recipe_run_id, expected_constants_dict):
14
- class DummyTask(VbiTaskBase):
15
- def run(self):
16
- pass
17
-
18
- task = DummyTask(
19
- recipe_run_id=recipe_run_id,
20
- workflow_name="vbi_dummy_task",
21
- workflow_version="VX.Y",
22
- )
23
-
24
- task.constants._update(expected_constants_dict)
25
- yield task
26
- task._purge()
27
-
28
-
29
- def test_constants_init(vbi_science_task, expected_constants_dict):
30
- """
31
- Given: A VbiTaskBase with a populated backend ConstantsDb
32
- When: Initializing the task
33
- Then: The .constants attribute is loaded correctly
34
- """
35
- constants_obj = vbi_science_task.constants
36
- for k, v in expected_constants_dict.items():
37
- assert getattr(constants_obj, k.lower()) == v