dkist-processing-common 10.5.4__py3-none-any.whl → 12.1.0rc1__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 (122) hide show
  1. changelog/280.misc.rst +1 -0
  2. changelog/282.feature.2.rst +2 -0
  3. changelog/282.feature.rst +2 -0
  4. changelog/284.feature.rst +1 -0
  5. changelog/285.feature.rst +2 -0
  6. changelog/285.misc.rst +2 -0
  7. changelog/286.feature.rst +2 -0
  8. changelog/287.misc.rst +1 -0
  9. dkist_processing_common/__init__.py +1 -0
  10. dkist_processing_common/_util/constants.py +1 -0
  11. dkist_processing_common/_util/graphql.py +1 -0
  12. dkist_processing_common/_util/scratch.py +9 -9
  13. dkist_processing_common/_util/tags.py +1 -0
  14. dkist_processing_common/codecs/array.py +20 -0
  15. dkist_processing_common/codecs/asdf.py +9 -3
  16. dkist_processing_common/codecs/basemodel.py +22 -0
  17. dkist_processing_common/codecs/bytes.py +1 -0
  18. dkist_processing_common/codecs/fits.py +37 -9
  19. dkist_processing_common/codecs/iobase.py +1 -0
  20. dkist_processing_common/codecs/json.py +1 -0
  21. dkist_processing_common/codecs/path.py +1 -0
  22. dkist_processing_common/codecs/quality.py +1 -1
  23. dkist_processing_common/codecs/str.py +1 -0
  24. dkist_processing_common/config.py +64 -25
  25. dkist_processing_common/manual.py +6 -8
  26. dkist_processing_common/models/constants.py +373 -37
  27. dkist_processing_common/models/dkist_location.py +27 -0
  28. dkist_processing_common/models/fits_access.py +48 -0
  29. dkist_processing_common/models/flower_pot.py +231 -9
  30. dkist_processing_common/models/fried_parameter.py +41 -0
  31. dkist_processing_common/models/graphql.py +66 -75
  32. dkist_processing_common/models/input_dataset.py +117 -0
  33. dkist_processing_common/models/message.py +1 -1
  34. dkist_processing_common/models/message_queue_binding.py +1 -1
  35. dkist_processing_common/models/metric_code.py +2 -0
  36. dkist_processing_common/models/parameters.py +65 -28
  37. dkist_processing_common/models/quality.py +50 -5
  38. dkist_processing_common/models/tags.py +23 -21
  39. dkist_processing_common/models/task_name.py +3 -2
  40. dkist_processing_common/models/telemetry.py +28 -0
  41. dkist_processing_common/models/wavelength.py +3 -1
  42. dkist_processing_common/parsers/average_bud.py +46 -0
  43. dkist_processing_common/parsers/cs_step.py +13 -12
  44. dkist_processing_common/parsers/dsps_repeat.py +6 -4
  45. dkist_processing_common/parsers/experiment_id_bud.py +12 -4
  46. dkist_processing_common/parsers/id_bud.py +42 -27
  47. dkist_processing_common/parsers/l0_fits_access.py +5 -3
  48. dkist_processing_common/parsers/l1_fits_access.py +51 -23
  49. dkist_processing_common/parsers/lookup_bud.py +125 -0
  50. dkist_processing_common/parsers/near_bud.py +21 -20
  51. dkist_processing_common/parsers/observing_program_id_bud.py +24 -0
  52. dkist_processing_common/parsers/proposal_id_bud.py +13 -5
  53. dkist_processing_common/parsers/quality.py +2 -0
  54. dkist_processing_common/parsers/retarder.py +32 -0
  55. dkist_processing_common/parsers/single_value_single_key_flower.py +6 -1
  56. dkist_processing_common/parsers/task.py +8 -6
  57. dkist_processing_common/parsers/time.py +178 -72
  58. dkist_processing_common/parsers/unique_bud.py +21 -22
  59. dkist_processing_common/parsers/wavelength.py +5 -3
  60. dkist_processing_common/tasks/__init__.py +3 -2
  61. dkist_processing_common/tasks/assemble_movie.py +4 -3
  62. dkist_processing_common/tasks/base.py +59 -60
  63. dkist_processing_common/tasks/l1_output_data.py +54 -53
  64. dkist_processing_common/tasks/mixin/globus.py +24 -27
  65. dkist_processing_common/tasks/mixin/interservice_bus.py +1 -0
  66. dkist_processing_common/tasks/mixin/metadata_store.py +108 -243
  67. dkist_processing_common/tasks/mixin/object_store.py +22 -0
  68. dkist_processing_common/tasks/mixin/quality/__init__.py +1 -0
  69. dkist_processing_common/tasks/mixin/quality/_base.py +8 -1
  70. dkist_processing_common/tasks/mixin/quality/_metrics.py +166 -14
  71. dkist_processing_common/tasks/output_data_base.py +4 -3
  72. dkist_processing_common/tasks/parse_l0_input_data.py +277 -15
  73. dkist_processing_common/tasks/quality_metrics.py +9 -9
  74. dkist_processing_common/tasks/teardown.py +7 -7
  75. dkist_processing_common/tasks/transfer_input_data.py +67 -69
  76. dkist_processing_common/tasks/trial_catalog.py +77 -17
  77. dkist_processing_common/tasks/trial_output_data.py +16 -17
  78. dkist_processing_common/tasks/write_l1.py +102 -72
  79. dkist_processing_common/tests/conftest.py +32 -173
  80. dkist_processing_common/tests/mock_metadata_store.py +271 -0
  81. dkist_processing_common/tests/test_assemble_movie.py +4 -4
  82. dkist_processing_common/tests/test_assemble_quality.py +32 -4
  83. dkist_processing_common/tests/test_base.py +5 -19
  84. dkist_processing_common/tests/test_codecs.py +103 -12
  85. dkist_processing_common/tests/test_constants.py +15 -0
  86. dkist_processing_common/tests/test_dkist_location.py +15 -0
  87. dkist_processing_common/tests/test_fits_access.py +56 -19
  88. dkist_processing_common/tests/test_flower_pot.py +147 -5
  89. dkist_processing_common/tests/test_fried_parameter.py +27 -0
  90. dkist_processing_common/tests/test_input_dataset.py +78 -361
  91. dkist_processing_common/tests/test_interservice_bus.py +1 -0
  92. dkist_processing_common/tests/test_interservice_bus_mixin.py +1 -1
  93. dkist_processing_common/tests/test_manual_processing.py +33 -0
  94. dkist_processing_common/tests/test_output_data_base.py +5 -7
  95. dkist_processing_common/tests/test_parameters.py +71 -22
  96. dkist_processing_common/tests/test_parse_l0_input_data.py +115 -32
  97. dkist_processing_common/tests/test_publish_catalog_messages.py +2 -24
  98. dkist_processing_common/tests/test_quality.py +1 -0
  99. dkist_processing_common/tests/test_quality_mixin.py +255 -23
  100. dkist_processing_common/tests/test_scratch.py +2 -1
  101. dkist_processing_common/tests/test_stems.py +511 -168
  102. dkist_processing_common/tests/test_submit_dataset_metadata.py +3 -7
  103. dkist_processing_common/tests/test_tags.py +1 -0
  104. dkist_processing_common/tests/test_task_name.py +1 -1
  105. dkist_processing_common/tests/test_task_parsing.py +17 -7
  106. dkist_processing_common/tests/test_teardown.py +28 -24
  107. dkist_processing_common/tests/test_transfer_input_data.py +270 -125
  108. dkist_processing_common/tests/test_transfer_l1_output_data.py +2 -3
  109. dkist_processing_common/tests/test_trial_catalog.py +83 -8
  110. dkist_processing_common/tests/test_trial_output_data.py +46 -73
  111. dkist_processing_common/tests/test_workflow_task_base.py +8 -10
  112. dkist_processing_common/tests/test_write_l1.py +298 -76
  113. dkist_processing_common-12.1.0rc1.dist-info/METADATA +265 -0
  114. dkist_processing_common-12.1.0rc1.dist-info/RECORD +134 -0
  115. {dkist_processing_common-10.5.4.dist-info → dkist_processing_common-12.1.0rc1.dist-info}/WHEEL +1 -1
  116. docs/conf.py +1 -0
  117. docs/index.rst +1 -1
  118. docs/landing_page.rst +13 -0
  119. dkist_processing_common/tasks/mixin/input_dataset.py +0 -166
  120. dkist_processing_common-10.5.4.dist-info/METADATA +0 -175
  121. dkist_processing_common-10.5.4.dist-info/RECORD +0 -112
  122. {dkist_processing_common-10.5.4.dist-info → dkist_processing_common-12.1.0rc1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.4
2
+ Name: dkist-processing-common
3
+ Version: 12.1.0rc1
4
+ Summary: Common task classes used by the DKIST science data processing pipelines
5
+ Author-email: NSO / AURA <dkistdc@nso.edu>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://nso.edu/dkist/data-center/
8
+ Project-URL: Repository, https://bitbucket.org/dkistdc/dkist-processing-common/
9
+ Project-URL: Documentation, https://docs.dkist.nso.edu/projects/common
10
+ Project-URL: Help, https://nso.atlassian.net/servicedesk/customer/portal/5
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Python: >=3.13
15
+ Description-Content-Type: text/x-rst
16
+ Requires-Dist: asdf<4.0.0,>=3.5.0
17
+ Requires-Dist: astropy>=7.0.0
18
+ Requires-Dist: dkist-fits-specifications<5.0,>=4.0.0
19
+ Requires-Dist: dkist-header-validator<6.0,>=5.0.0
20
+ Requires-Dist: dkist-processing-core==7.0.1
21
+ Requires-Dist: dkist-processing-pac<4.0,>=3.1
22
+ Requires-Dist: dkist-service-configuration<5.0,>=4.2.0
23
+ Requires-Dist: dkist-spectral-lines<4.0,>=3.0.0
24
+ Requires-Dist: solar-wavelength-calibration<3.0,>=2.0.0
25
+ Requires-Dist: globus-sdk<5.0.0,>=4.0.0
26
+ Requires-Dist: gqlclient[pydantic]==1.2.3
27
+ Requires-Dist: sqids==0.5.1
28
+ Requires-Dist: matplotlib>=3.4
29
+ Requires-Dist: moviepy>=2.0.0
30
+ Requires-Dist: numpy>=1.26.4
31
+ Requires-Dist: object-clerk==1.0.0
32
+ Requires-Dist: pandas>=1.4.2
33
+ Requires-Dist: pillow>=10.2.0
34
+ Requires-Dist: pydantic>=2.7.2
35
+ Requires-Dist: redis==6.4.0
36
+ Requires-Dist: requests>=2.23
37
+ Requires-Dist: scipy>=1.15.1
38
+ Requires-Dist: sunpy>=3.0.0
39
+ Requires-Dist: talus==1.3.4
40
+ Provides-Extra: test
41
+ Requires-Dist: pytest; extra == "test"
42
+ Requires-Dist: pytest-xdist; extra == "test"
43
+ Requires-Dist: pytest-cov; extra == "test"
44
+ Requires-Dist: pytest-mock; extra == "test"
45
+ Requires-Dist: hypothesis; extra == "test"
46
+ Requires-Dist: towncrier; extra == "test"
47
+ Requires-Dist: dkist-data-simulator>=5.2.6; extra == "test"
48
+ Requires-Dist: dkist-processing-common[inventory]; extra == "test"
49
+ Requires-Dist: dkist-processing-common[asdf]; extra == "test"
50
+ Requires-Dist: dkist-processing-common[quality]; extra == "test"
51
+ Provides-Extra: docs
52
+ Requires-Dist: sphinx; extra == "docs"
53
+ Requires-Dist: sphinx-astropy; extra == "docs"
54
+ Requires-Dist: sphinx-changelog; extra == "docs"
55
+ Requires-Dist: sphinx-autoapi!=3.1.0; extra == "docs"
56
+ Requires-Dist: pytest; extra == "docs"
57
+ Requires-Dist: towncrier<22.12.0; extra == "docs"
58
+ Requires-Dist: dkist-sphinx-theme; extra == "docs"
59
+ Provides-Extra: inventory
60
+ Requires-Dist: dkist-inventory<2.0,>=1.11.2; extra == "inventory"
61
+ Provides-Extra: asdf
62
+ Requires-Dist: dkist-inventory[asdf]<2.0,>=1.11.2; extra == "asdf"
63
+ Provides-Extra: quality
64
+ Requires-Dist: dkist-quality<3.0,>=2.0.0; extra == "quality"
65
+
66
+ dkist-processing-common
67
+ =======================
68
+
69
+ |codecov|
70
+
71
+ This repository works in concert with `dkist-processing-core <https://pypi.org/project/dkist-processing-core/>`_ and `dkist-processing-*instrument*` to
72
+ form the DKIST calibration processing stack.
73
+
74
+ Usage
75
+ -----
76
+
77
+ The classes in this repository should be used as the base of any DKIST processing pipeline tasks. Science tasks should subclass `ScienceTaskL0ToL1Base`.
78
+
79
+ Each class is built on an abstract base class with the `run` method left for a developer to fill out with the required steps that the task should take.
80
+ This class is then used as the callable object for the workflow and scheduling engine.
81
+
82
+ Example
83
+ -------
84
+
85
+ .. code-block:: python
86
+
87
+ from dkist_processing_common.tasks.base import ScienceTaskL0ToL1Base
88
+
89
+
90
+ class RemoveArtifacts(ScienceTaskL0ToL1Base):
91
+ def run(self):
92
+ # task code here
93
+ total = 2 + 5
94
+
95
+ Deployment
96
+ ----------
97
+
98
+ dkist-processing-common is deployed to `PyPI <https://pypi.org/project/dkist-processing-common/>`_
99
+
100
+ Environment Variables
101
+ ---------------------
102
+
103
+ .. list-table::
104
+ :widths: 10 90
105
+ :header-rows: 1
106
+
107
+ * - Variable
108
+ - Field Info
109
+ * - LOGURU_LEVEL
110
+ - annotation=str required=False default='INFO' alias_priority=2 validation_alias='LOGURU_LEVEL' description='Log level for the application'
111
+ * - MESH_CONFIG
112
+ - annotation=dict[str, MeshService] required=False default_factory=dict alias_priority=2 validation_alias='MESH_CONFIG' description='Service mesh configuration' examples=[{'upstream_service_name': {'mesh_address': 'localhost', 'mesh_port': 6742}}]
113
+ * - RETRY_CONFIG
114
+ - annotation=RetryConfig required=False default_factory=RetryConfig description='Retry configuration for the service'
115
+ * - OTEL_SERVICE_NAME
116
+ - annotation=str required=False default='unknown-service-name' alias_priority=2 validation_alias='OTEL_SERVICE_NAME' description='Service name for OpenTelemetry'
117
+ * - DKIST_SERVICE_VERSION
118
+ - annotation=str required=False default='unknown-service-version' alias_priority=2 validation_alias='DKIST_SERVICE_VERSION' description='Service version for OpenTelemetry'
119
+ * - NOMAD_ALLOC_ID
120
+ - annotation=str required=False default='unknown-allocation-id' alias_priority=2 validation_alias='NOMAD_ALLOC_ID' description='Nomad allocation ID for OpenTelemetry'
121
+ * - NOMAD_ALLOC_NAME
122
+ - annotation=str required=False default='unknown-allocation-name' alias='NOMAD_ALLOC_NAME' alias_priority=2 description='Allocation name for the deployed container the task is running on.'
123
+ * - NOMAD_GROUP_NAME
124
+ - annotation=str required=False default='unknown-allocation-group' alias='NOMAD_GROUP_NAME' alias_priority=2 description='Allocation group for the deployed container the task is running on'
125
+ * - OTEL_EXPORTER_OTLP_TRACES_INSECURE
126
+ - annotation=bool required=False default=True description='Use insecure connection for OTLP traces'
127
+ * - OTEL_EXPORTER_OTLP_METRICS_INSECURE
128
+ - annotation=bool required=False default=True description='Use insecure connection for OTLP metrics'
129
+ * - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
130
+ - annotation=Union[str, NoneType] required=False default=None description='OTLP traces endpoint. Overrides mesh configuration' examples=['localhost:4317']
131
+ * - OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
132
+ - annotation=Union[str, NoneType] required=False default=None description='OTLP metrics endpoint. Overrides mesh configuration' examples=['localhost:4317']
133
+ * - OTEL_PYTHON_DISABLED_INSTRUMENTATIONS
134
+ - annotation=list[str] required=False default_factory=list description='List of instrumentations to disable. https://opentelemetry.io/docs/zero-code/python/configuration/' examples=[['pika', 'requests']]
135
+ * - OTEL_PYTHON_FASTAPI_EXCLUDED_URLS
136
+ - annotation=str required=False default='health' description='Comma separated list of URLs to exclude from OpenTelemetry instrumentation in FastAPI.' examples=['client/.*/info,healthcheck']
137
+ * - SYSTEM_METRIC_INSTRUMENTATION_CONFIG
138
+ - annotation=Union[dict[str, bool], NoneType] required=False default=None description='Configuration for system metric instrumentation. https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/system_metrics/system_metrics.html' examples=[{'system.memory.usage': ['used', 'free', 'cached'], 'system.cpu.time': ['idle', 'user', 'system', 'irq'], 'system.network.io': ['transmit', 'receive'], 'process.runtime.memory': ['rss', 'vms'], 'process.runtime.cpu.time': ['user', 'system'], 'process.runtime.context_switches': ['involuntary', 'voluntary']}]
139
+ * - ISB_USERNAME
140
+ - annotation=str required=False default='guest' description='Username for the interservice-bus.'
141
+ * - ISB_PASSWORD
142
+ - annotation=str required=False default='guest' description='Password for the interservice-bus.'
143
+ * - ISB_EXCHANGE
144
+ - annotation=str required=False default='master.direct.x' description='Exchange for the interservice-bus.'
145
+ * - ISB_QUEUE_TYPE
146
+ - annotation=str required=False default='classic' description='Queue type for the interservice-bus.' examples=['quorum', 'classic']
147
+ * - BUILD_VERSION
148
+ - annotation=str required=False default='dev' description='Fallback build version for workflow tasks.'
149
+ * - MAX_FILE_DESCRIPTORS
150
+ - annotation=int required=False default=1024 description='Maximum number of file descriptors to allow the process.'
151
+ * - GQL_AUTH_TOKEN
152
+ - annotation=Union[str, NoneType] required=False default='dev' description='The auth token for the metadata-store-api.'
153
+ * - OBJECT_STORE_ACCESS_KEY
154
+ - annotation=Union[str, NoneType] required=False default=None description='The access key for the object store.'
155
+ * - OBJECT_STORE_SECRET_KEY
156
+ - annotation=Union[str, NoneType] required=False default=None description='The secret key for the object store.'
157
+ * - OBJECT_STORE_USE_SSL
158
+ - annotation=bool required=False default=False description='Whether to use SSL for the object store connection.'
159
+ * - MULTIPART_THRESHOLD
160
+ - annotation=Union[int, NoneType] required=False default=None description='Multipart threshold for the object store.'
161
+ * - S3_CLIENT_CONFIG
162
+ - annotation=Union[dict, NoneType] required=False default=None description='S3 client configuration for the object store.'
163
+ * - S3_UPLOAD_CONFIG
164
+ - annotation=Union[dict, NoneType] required=False default=None description='S3 upload configuration for the object store.'
165
+ * - S3_DOWNLOAD_CONFIG
166
+ - annotation=Union[dict, NoneType] required=False default=None description='S3 download configuration for the object store.'
167
+ * - GLOBUS_MAX_RETRIES
168
+ - annotation=int required=False default=5 description='Max retries for transient errors on calls to the globus api.'
169
+ * - GLOBUS_INBOUND_CLIENT_CREDENTIALS
170
+ - annotation=list[GlobusClientCredential] required=False default_factory=list description='Globus client credentials for inbound transfers.' examples=[[{'client_id': 'id1', 'client_secret': 'secret1'}, {'client_id': 'id2', 'client_secret': 'secret2'}]]
171
+ * - GLOBUS_OUTBOUND_CLIENT_CREDENTIALS
172
+ - annotation=list[GlobusClientCredential] required=False default_factory=list description='Globus client credentials for outbound transfers.' examples=[[{'client_id': 'id3', 'client_secret': 'secret3'}, {'client_id': 'id4', 'client_secret': 'secret4'}]]
173
+ * - OBJECT_STORE_ENDPOINT
174
+ - annotation=Union[str, NoneType] required=False default=None description='Object store Globus Endpoint ID.'
175
+ * - SCRATCH_ENDPOINT
176
+ - annotation=Union[str, NoneType] required=False default=None description='Scratch Globus Endpoint ID.'
177
+ * - SCRATCH_BASE_PATH
178
+ - annotation=str required=False default='scratch/' description='Base path for scratch storage.'
179
+ * - SCRATCH_INVENTORY_DB_COUNT
180
+ - annotation=int required=False default=16 description='Number of databases in the scratch inventory (redis).'
181
+ * - DOCS_BASE_URL
182
+ - annotation=str required=False default='my_test_url' description='Base URL for the documentation site.'
183
+
184
+ Development
185
+ -----------
186
+
187
+ There are two prerequisites for test execution on a local machine:
188
+
189
+
190
+ * Redis. A running instance of redis on the local machine is required. The tests will use the default host ip of localhost and port of 6379 to connect to the database.
191
+
192
+ * RabbitMQ. A running instance of rabbitmq on the local machine is required. The tests will use the default host of localhost and a port of 5672 to connect to the interservice bus.
193
+
194
+
195
+ To run the tests locally, clone the repository and install the package in editable mode with the test extras.
196
+
197
+
198
+ .. code-block:: bash
199
+
200
+ git clone git@bitbucket.org:dkistdc/dkist-processing-common.git
201
+ cd dkist-processing-common
202
+ pre-commit install
203
+ pip install -e .[test]
204
+ # Redis must be running
205
+ pytest -v --cov dkist_processing_common
206
+
207
+ Changelog
208
+ #########
209
+
210
+ When you make **any** change to this repository it **MUST** be accompanied by a changelog file.
211
+ The changelog for this repository uses the `towncrier <https://github.com/twisted/towncrier>`__ package.
212
+ Entries in the changelog for the next release are added as individual files (one per change) to the ``changelog/`` directory.
213
+
214
+ Writing a Changelog Entry
215
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
216
+
217
+ A changelog entry accompanying a change should be added to the ``changelog/`` directory.
218
+ The name of a file in this directory follows a specific template::
219
+
220
+ <PULL REQUEST NUMBER>.<TYPE>[.<COUNTER>].rst
221
+
222
+ The fields have the following meanings:
223
+
224
+ * ``<PULL REQUEST NUMBER>``: This is the number of the pull request, so people can jump from the changelog entry to the diff on BitBucket.
225
+ * ``<TYPE>``: This is the type of the change and must be one of the values described below.
226
+ * ``<COUNTER>``: This is an optional field, if you make more than one change of the same type you can append a counter to the subsequent changes, i.e. ``100.bugfix.rst`` and ``100.bugfix.1.rst`` for two bugfix changes in the same PR.
227
+
228
+ The list of possible types is defined the the towncrier section of ``pyproject.toml``, the types are:
229
+
230
+ * ``feature``: This change is a new code feature.
231
+ * ``bugfix``: This is a change which fixes a bug.
232
+ * ``doc``: A documentation change.
233
+ * ``removal``: A deprecation or removal of public API.
234
+ * ``misc``: Any small change which doesn't fit anywhere else, such as a change to the package infrastructure.
235
+
236
+
237
+ Rendering the Changelog at Release Time
238
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
239
+
240
+ When you are about to tag a release first you must run ``towncrier`` to render the changelog.
241
+ The steps for this are as follows:
242
+
243
+ * Run `towncrier build --version vx.y.z` using the version number you want to tag.
244
+ * Agree to have towncrier remove the fragments.
245
+ * Add and commit your changes.
246
+ * Tag the release.
247
+
248
+ **NOTE:** If you forget to add a Changelog entry to a tagged release (either manually or automatically with ``towncrier``)
249
+ then the Bitbucket pipeline will fail. To be able to use the same tag you must delete it locally and on the remote branch:
250
+
251
+ .. code-block:: bash
252
+
253
+ # First, actually update the CHANGELOG and commit the update
254
+ git commit
255
+
256
+ # Delete tags
257
+ git tag -d vWHATEVER.THE.VERSION
258
+ git push --delete origin vWHATEVER.THE.VERSION
259
+
260
+ # Re-tag with the same version
261
+ git tag vWHATEVER.THE.VERSION
262
+ git push --tags origin main
263
+
264
+ .. |codecov| image:: https://codecov.io/bb/dkistdc/dkist-processing-common/graph/badge.svg?token=3QSLGSEF3O
265
+ :target: https://codecov.io/bb/dkistdc/dkist-processing-common
@@ -0,0 +1,134 @@
1
+ changelog/.gitempty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ changelog/280.misc.rst,sha256=6k9RYfsyA5YMk2-FNPn1ou0FCqacpBfYA_2uGr6D9I8,107
3
+ changelog/282.feature.2.rst,sha256=6OfMMb7pzbStUmHA4YldfprALhPR5Uc_qZrKh9VdenE,176
4
+ changelog/282.feature.rst,sha256=WHCYqxTGJlTrrjttCqRnZizIx2CEz34mLYisW36zJRo,201
5
+ changelog/284.feature.rst,sha256=Um3KupQuiTtX9tpLE4zLk3TW_wc3ZoCGxmFA-dGQJdU,120
6
+ changelog/285.feature.rst,sha256=FdvhAXvf1je9xLNSgZMl32TYomFibMKd1k6cf8ihkXI,142
7
+ changelog/285.misc.rst,sha256=7ie7VKD5yTMjbXs1V-jO2I2_vsCJ49WSK2g-B37NWFs,180
8
+ changelog/286.feature.rst,sha256=Dzqo-mB_plyAhUZGuOJ_e0fXNoRLmwgfXrjfi1hqGHg,189
9
+ changelog/287.misc.rst,sha256=mqc5FFqdtMFrZETadk6m_wkgtoH8kvJjnR-IGMYXDBY,52
10
+ dkist_processing_common/__init__.py,sha256=GQ9EBnYhkOnt-qODclAoLS_g5YVhurxfg1tjVtI9rDI,320
11
+ dkist_processing_common/config.py,sha256=f511KVpK24sQO4dDr4L6PMj5dz0jmWgnx2Y-3DpV0cw,5991
12
+ dkist_processing_common/manual.py,sha256=bIVVyLsbXMh-g_2L3kGROL-1TtJe0_XviHsp7Br31x8,7023
13
+ dkist_processing_common/_util/__init__.py,sha256=xf6JNpMKQgbhE2Jivymt-WO0WF6PpGt9rl604YpuTWk,92
14
+ dkist_processing_common/_util/constants.py,sha256=0_bWLsvusHD8GrTx4B6V7AieKAaFbN9crcAALaS8x5Q,3245
15
+ dkist_processing_common/_util/graphql.py,sha256=XDphwUGOLseuipjv33sbj4G2wU3__YDoEf9R0lMGc5Q,3421
16
+ dkist_processing_common/_util/scratch.py,sha256=Te8RR4zbvrpbDK5x9Q3McauUxnKlFudJ505CzyPPk9I,10364
17
+ dkist_processing_common/_util/tags.py,sha256=z5zIVA-FVO5nLfB95fqtiLxIXfe-J-vr_d5dbakJons,6221
18
+ dkist_processing_common/codecs/__init__.py,sha256=du1iitvsudSSOMENSywXmXSLOlvIocJsPbvfEcyqFNc,159
19
+ dkist_processing_common/codecs/array.py,sha256=N5rsBlcyA1tJi1Wl7oBSJOsnjzpQXnr6jkLTup-UJGQ,576
20
+ dkist_processing_common/codecs/asdf.py,sha256=gA0yf524jhbr97TNHoDTq4D6ZSMth7mpFOTh_6IcNuA,1047
21
+ dkist_processing_common/codecs/basemodel.py,sha256=bdhpJXICLEPiNyekQKzNmJsmLtAvg94C-yp-uAiFTW0,815
22
+ dkist_processing_common/codecs/bytes.py,sha256=-nRujIfAqwSkxj-5S8cDVgwLd64FJKapHv8fZBshOVo,496
23
+ dkist_processing_common/codecs/fits.py,sha256=Eh9vLIqajlUfcfHcVfc7DbcM1K6Mx4CBqhg020PRCfM,3080
24
+ dkist_processing_common/codecs/iobase.py,sha256=ESDUDy5eAPdb0nPRCt041iLbJzV3Ch4nrXkRQJgQCXE,978
25
+ dkist_processing_common/codecs/json.py,sha256=Cbg4fQMZKlYG0sI5Q-XRagheQNSR2ruqe7KjgTsW6wM,940
26
+ dkist_processing_common/codecs/path.py,sha256=znnBvIS529AsryJaARPWpKaX7_zhsb_-CLjUNLDfW-o,198
27
+ dkist_processing_common/codecs/quality.py,sha256=FWoqtsdurmlgx2YtbtLo5C0H3G7e3b8CeUsfCoKnvqQ,3090
28
+ dkist_processing_common/codecs/str.py,sha256=Xqt5k8IhLc95KiiNiFwB1JWcVVc6T8AfcLrpovyZL2U,680
29
+ dkist_processing_common/fonts/Lato-Regular.ttf,sha256=1jbkaDIx-THtoiLViOlE0IK_0726AvkovuRhwPGFslE,656568
30
+ dkist_processing_common/fonts/__init__.py,sha256=hBvZRtkoGRPlNDWCK-ZePXdSIlThCcjwBDfYaamVgAw,101
31
+ dkist_processing_common/models/__init__.py,sha256=6LMqemdzVZ87fRrpAsbEnTtWZ02_Gu_oajsUlwGRH_Q,74
32
+ dkist_processing_common/models/constants.py,sha256=-UAJh7fz3BhPX4zaRRbQj1J-YnxVMuuvDWxLFmOll5Q,20184
33
+ dkist_processing_common/models/dkist_location.py,sha256=6Nk0wvv4R8ptlrV7BXon7abq4YLvmTdUmPsDN5G8nWc,971
34
+ dkist_processing_common/models/fits_access.py,sha256=imKqL4-_g6gTR-IeIjZ6qkMhQX3JujdrKFrTd9gOXnw,5605
35
+ dkist_processing_common/models/flower_pot.py,sha256=bSmnfN1r5ASx_E9GtvFzdT7lciLCpMy80TeSLztakZk,12289
36
+ dkist_processing_common/models/fried_parameter.py,sha256=ro_H2Eo3I88lRf1wJjZfTc_XOjhgLt4whIQR_sjAFbM,1609
37
+ dkist_processing_common/models/graphql.py,sha256=QsKLbytpw_Qg9pJASscA7dZRfDbHLkpLZaWeqaHUDvo,5133
38
+ dkist_processing_common/models/input_dataset.py,sha256=19w_ydrxdzjJgpnhFELqUomr7GixURjzLOaX41ipOKk,4173
39
+ dkist_processing_common/models/message.py,sha256=ZEsPQalo5aKTOHfc5I15mNCe1KQcfJ3ivU7XBf8wnkM,1684
40
+ dkist_processing_common/models/message_queue_binding.py,sha256=Y4otwkkePrLRSjlrya8nlEaBvCCUgfGZAWZF9XqCQ9Y,1012
41
+ dkist_processing_common/models/metric_code.py,sha256=WSLF9yqcVzk9L9u8WBhgtpUYUWYsG4ZFWFRFtezdUCM,848
42
+ dkist_processing_common/models/parameters.py,sha256=9An3SxUEBI-oYHjICQ_q-IIScTfpvVeAFH7jLzBzzWI,9649
43
+ dkist_processing_common/models/quality.py,sha256=TmDVbvPbfl5CIIs1ioD5guLUoEOFTfiJESvDjLTLl5s,3981
44
+ dkist_processing_common/models/tags.py,sha256=0YqiDrismOSds_3XtFBb2dfv0gjMs6CgRv2dJKsSthI,12082
45
+ dkist_processing_common/models/task_name.py,sha256=uAl7qTK4Xx1nqPAhNAe5nAXqxwPwQzAq58YmoccX6xQ,567
46
+ dkist_processing_common/models/telemetry.py,sha256=XVcLNgHCZsP9L7oYiklyLUoqQtWt_xjEkuf70Kbudz4,839
47
+ dkist_processing_common/models/wavelength.py,sha256=4UhRVoNvCHZitXo5S1oRdewadbmGfmDK6wetMV06POA,967
48
+ dkist_processing_common/parsers/__init__.py,sha256=XJQzHtPb78F6-qXXKXjyztc0x-aHVlgv1C_l4dR88tI,67
49
+ dkist_processing_common/parsers/average_bud.py,sha256=mTlrBlo7Pe5WnNmui4wQC24-8QY5hmhHJWvhg9vMrOw,1413
50
+ dkist_processing_common/parsers/cs_step.py,sha256=6SCSbCgVhEGxJIIrCBByWCmIad_vuje28jECFZ6qlZI,6454
51
+ dkist_processing_common/parsers/dsps_repeat.py,sha256=Jg6oI9-PtFQbQHbGul6_eiRzBKr0Z2HIGOitG0G5CD4,1642
52
+ dkist_processing_common/parsers/experiment_id_bud.py,sha256=LUehIqB56hmDwARph1itSUsPenFHScfrrRuZmcCi4xA,960
53
+ dkist_processing_common/parsers/id_bud.py,sha256=ShHj7bHiPAmMdUW56WfwPTRrCEnBuLu8v45Aaxocd-M,2242
54
+ dkist_processing_common/parsers/l0_fits_access.py,sha256=Ol3eo8yyNbGqbN2whhD2jBNoqhOrlwmH8DbMmCLtNk0,1033
55
+ dkist_processing_common/parsers/l1_fits_access.py,sha256=BWojvcFl_RmkrRWHe1WxDCsPeexervlRFPothuXAyoI,4410
56
+ dkist_processing_common/parsers/lookup_bud.py,sha256=IpDtwCsJRiOanDTpoaav3dZXe55WZpYWTnyxIiEWxvk,4047
57
+ dkist_processing_common/parsers/near_bud.py,sha256=_JeH2QODlDDjbdzp7U6B8ROmP2gvXzZrf0MItVnjTT4,3893
58
+ dkist_processing_common/parsers/observing_program_id_bud.py,sha256=foESQTMShcp-aPGZFcLEdXIdi5Y6vFeus-W447olQEc,884
59
+ dkist_processing_common/parsers/proposal_id_bud.py,sha256=VvVoYM-MUivra2fMZOSAOgGQslLROZxFuwHnuAZyAjc,942
60
+ dkist_processing_common/parsers/quality.py,sha256=hhCT-bHODOYSp9jvgsiWfYcLYtQCSWgfuy0xZnkYXwo,1141
61
+ dkist_processing_common/parsers/retarder.py,sha256=zsOohfMMmK49CnJw1hYavAvCs9WQ4oLEHhiM6v8FnV8,1405
62
+ dkist_processing_common/parsers/single_value_single_key_flower.py,sha256=Xy0_55H2VInGkMKSPOQjcYiMW0DFlDOn27n5jC2PKzE,1358
63
+ dkist_processing_common/parsers/task.py,sha256=nuGxDl5_gjbi07jMOrCPD5J9L51lyZZ6VS25FuDC3V8,3990
64
+ dkist_processing_common/parsers/time.py,sha256=4-ifDUFLh-rp5bqmirWSEerqQWGevcfOKQK5iSclbR0,11047
65
+ dkist_processing_common/parsers/unique_bud.py,sha256=RN3Q3IQFUVLlFCWZnS-M_skdBSowb9L8S0lXN1KHwSE,3152
66
+ dkist_processing_common/parsers/wavelength.py,sha256=P5C9mG8DAKK3GB3vWNRBI5l7pAW68lJK-kw-4eqERuQ,612
67
+ dkist_processing_common/tasks/__init__.py,sha256=l23ctjNsKJbHbbqaZBMeOPaOtw0hmITEljI_JJ-CVsU,627
68
+ dkist_processing_common/tasks/assemble_movie.py,sha256=1ixDG-f4ODt0vywqVccG3aodLljVO5OGlvuMO9EEvcU,12767
69
+ dkist_processing_common/tasks/base.py,sha256=itAHCvzcodo-q8_AjpWoRaM86BlcjWDpCIiUP7uwmP0,13236
70
+ dkist_processing_common/tasks/l1_output_data.py,sha256=LxGnOSfG0wRQi5r3OuSQueZYSSUG27GBeCDjmg9HCpo,10380
71
+ dkist_processing_common/tasks/output_data_base.py,sha256=r1Bu3FX5zTVj66GTMWtaV_NdhxjyjSm661Bt2Mxmfi4,3685
72
+ dkist_processing_common/tasks/parse_l0_input_data.py,sha256=xcWmwSKwxEeManltCFrqVG224Vk-BYRE6g32VOK--rI,19241
73
+ dkist_processing_common/tasks/quality_metrics.py,sha256=cvGF6tJ8yAvxOvkeG3tWxYwL885BrFW5X3V7_MSzL-A,12481
74
+ dkist_processing_common/tasks/teardown.py,sha256=rwT9lWINVDF11-az_nx-Z5ykMTX_SJCchobpU6sErgk,2360
75
+ dkist_processing_common/tasks/transfer_input_data.py,sha256=4TJqlDjTc503QFvzSmMert99r9KHDwyd72r1kHAVhQA,5879
76
+ dkist_processing_common/tasks/trial_catalog.py,sha256=Yf-BKNCT_OHwJsxxZP8p2eRW04CcY0tw5_YIe1e9RQY,10535
77
+ dkist_processing_common/tasks/trial_output_data.py,sha256=pUdrNlAzuir4AUdfax5_MOplB-A9NrXErMJmAwtJmLA,6811
78
+ dkist_processing_common/tasks/write_l1.py,sha256=Xy834RTp3F95kLcW4ba5gfHMUocfZd82ZQQKnvQcP2M,23204
79
+ dkist_processing_common/tasks/mixin/__init__.py,sha256=-g-DQbU7m1bclJYuFe3Yh757V-35GIDTbstardKQ7nU,68
80
+ dkist_processing_common/tasks/mixin/globus.py,sha256=ugejtZ_MR5LesQYuXM1uICd_yWDE7cZZr0qnWCh75R8,6732
81
+ dkist_processing_common/tasks/mixin/interservice_bus.py,sha256=M6R922l7gJSmmU_vswUXxy-c5DWNrIRjQu9H9CSgGfU,1081
82
+ dkist_processing_common/tasks/mixin/metadata_store.py,sha256=GLfh0a0ehuRC8Uml59PfLExuoxGRj6tzNMytlO5jZf4,9106
83
+ dkist_processing_common/tasks/mixin/object_store.py,sha256=l2sPzolmKsuYvUocHayT7PScliiFRIV12qIFYtCLII8,3888
84
+ dkist_processing_common/tasks/mixin/quality/__init__.py,sha256=GOI_PBUxTmYp5IIuYFbwpA5Vx0jUwpdBBYYrnZMTh0E,384
85
+ dkist_processing_common/tasks/mixin/quality/_base.py,sha256=qt9TZZ140skFWFmabrjlGdm60OLWEfx_xZAaohr6dLM,8492
86
+ dkist_processing_common/tasks/mixin/quality/_metrics.py,sha256=TtM6V7qy0U6ofFmjXNoJKkaECoPSfJsU4Ziu1UQgPZs,60457
87
+ dkist_processing_common/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
+ dkist_processing_common/tests/conftest.py,sha256=Tm-Yq956EAafpDtu1d7JjdVY0Unp9e4z9ak-yf4wnH4,22320
89
+ dkist_processing_common/tests/mock_metadata_store.py,sha256=i41xu5AY4A566YT0qSzhP7qpR0wZp_EFH-OFcAsV4vQ,9591
90
+ dkist_processing_common/tests/test_assemble_movie.py,sha256=dyVhowxB-Kc6GuxlDs74UrPtK9fwdUL7y5haA3Bidz0,4065
91
+ dkist_processing_common/tests/test_assemble_quality.py,sha256=-F22jMY6mPy65VZ1TZY2r1vsxMXOPmZHArGx70OD3BA,17832
92
+ dkist_processing_common/tests/test_base.py,sha256=gsyBG2R6Ufx7CzbHeGMagUwM9yCfpN4gCSZ6-aH2q48,6643
93
+ dkist_processing_common/tests/test_codecs.py,sha256=WpF15UYklpNRgETI4EwXsgbNzxMcHlelfpprBbupC0I,23907
94
+ dkist_processing_common/tests/test_constants.py,sha256=I_KcJs7ScCn53GYhEO6qjWrrnfZuyC1IVYOy87Pjlg4,6565
95
+ dkist_processing_common/tests/test_cs_step.py,sha256=RA0QD3D8eaL3YSOL_gIJ9wkngy14RQ2jbD-05KAziW4,2408
96
+ dkist_processing_common/tests/test_dkist_location.py,sha256=-_OoSw4SZDLFyIuOltHvM6PQjxm5hTiJQsiTGZ8Sadc,456
97
+ dkist_processing_common/tests/test_fits_access.py,sha256=a50B4IAAH5NH5zeudTqyy0b5uWKJwJuzQLUdK1LoOHM,12832
98
+ dkist_processing_common/tests/test_flower_pot.py,sha256=ykt7H2HF2hq4fln0GojYbFPwZKzIO7B9Rp6tJCE5Fn4,7447
99
+ dkist_processing_common/tests/test_fried_parameter.py,sha256=iXtlQIifZ6cDOkEi-YDgP3oAlss2loq08Uohgvy1byQ,1295
100
+ dkist_processing_common/tests/test_input_dataset.py,sha256=wnQbZxBYywG5CEXces2WWk6I0QA7HjStaYSTVVbe5r0,8499
101
+ dkist_processing_common/tests/test_interservice_bus.py,sha256=QrBeZ8dh497h6nxA8-aVUIGDcSj8y9DIXIk9I_HkXr0,3001
102
+ dkist_processing_common/tests/test_interservice_bus_mixin.py,sha256=IptJkW7Qeu2Y742NKXEgkok2VdS600keLgCD3Y9iw3A,4131
103
+ dkist_processing_common/tests/test_manual_processing.py,sha256=iHF7yQPlar9niYAGXtFv28Gw3Undlds38yMfszk4ccY,1037
104
+ dkist_processing_common/tests/test_output_data_base.py,sha256=D8b1XKvbE3C5cGOiHq58yJ2pzQL3iL0wLZy_AkDdB9Y,3085
105
+ dkist_processing_common/tests/test_parameters.py,sha256=CUEUIGBPMCUXPll0G0UxFDbMXi8lmnjRwXBarGX1PAQ,14033
106
+ dkist_processing_common/tests/test_parse_l0_input_data.py,sha256=7yn1VGwC3S-0JOYIMflNHhaXEnPhwjJtewD2WxBgugM,13239
107
+ dkist_processing_common/tests/test_publish_catalog_messages.py,sha256=7WRsEwoLHGeaCmLTAW4tU_BlZw0e3hwx65uWSGzfuYE,2393
108
+ dkist_processing_common/tests/test_quality.py,sha256=IPz7liXcmoqWIsY78oX07Ui0nWHxoUH2FbKGEmMle7E,10258
109
+ dkist_processing_common/tests/test_quality_mixin.py,sha256=L-_kSIKs8A48LGt9QaItZWZqIcRF0MhBCAZQZYdSflk,55575
110
+ dkist_processing_common/tests/test_scratch.py,sha256=WO8C1VJlkcC5IzST9Hj08CyyrINwYcN8pyteD9x38xs,16482
111
+ dkist_processing_common/tests/test_stems.py,sha256=sNRNsyBdQYSk8a70MPLJ99hX7mA-vbIoUcN9srmQe_o,39917
112
+ dkist_processing_common/tests/test_submit_dataset_metadata.py,sha256=-UicRcyRQAC9H3sbTYlJaH4-Yn6jKNyQEZhzZxojzqw,3543
113
+ dkist_processing_common/tests/test_tags.py,sha256=w5gmVfp3Ck92KNV80lJQRMz0OYgTYzWtwVUFWv1b5i8,5024
114
+ dkist_processing_common/tests/test_task_name.py,sha256=kqFr59XX2K87xzfTlClzDV4-Je1dx72LvdaJ22UE8UU,1233
115
+ dkist_processing_common/tests/test_task_parsing.py,sha256=2_OOmeZQWD17XAd_ECYmodJzD_iRIBKjCYdGh38BOx4,4421
116
+ dkist_processing_common/tests/test_teardown.py,sha256=DaliHSGsiQBZaFkf5wb3XBo6rHNPmx2bmQtVymYeBN4,5601
117
+ dkist_processing_common/tests/test_transfer_input_data.py,sha256=eyAAWXpTHQ8aew87-MncWpYBn4DAZrTSOL3LvlQfR5Q,12611
118
+ dkist_processing_common/tests/test_transfer_l1_output_data.py,sha256=PVGDJBEUk4kAeu8ivrhlCE7yd29R18t9kZLFx-mpBwY,2063
119
+ dkist_processing_common/tests/test_trial_catalog.py,sha256=CxjtVABE5Fw2EvyXR56IJ3PPi9QvEOjccH0OzzRWk30,9424
120
+ dkist_processing_common/tests/test_trial_output_data.py,sha256=fu3iGNV_FI8LOacezyt4HvXnxY3g1_UiBuRI63yz5Oo,11977
121
+ dkist_processing_common/tests/test_workflow_task_base.py,sha256=LTVusltNrsGUOvw9G323am4CXebgE4tJhP6gZCcS0CQ,10457
122
+ dkist_processing_common/tests/test_write_l1.py,sha256=alN-lozKEm6vKNdhtvzjnuPqv-NjHyUg16Op7SkMH-c,27964
123
+ docs/Makefile,sha256=qnlVz6PuBqE39NfHWuUnHhNEA-EFgT2-WJNNNy9ttfk,4598
124
+ docs/changelog.rst,sha256=S2jPASsWlQxSlAPqdvNrYvhk9k3FcFWNXFNDYXBSjl4,120
125
+ docs/conf.py,sha256=7W2iHKs3J5RhAz0JZafC_UnfMvcpZN7j4LLUmQtk2D0,1891
126
+ docs/index.rst,sha256=MiOh8Sdi2q5Gej4Cfuw-HXbp0zrJotakprq-GDvhlrQ,116
127
+ docs/landing_page.rst,sha256=aPAuXFhBx73lEZ59B6E6JXxkK0LlxzD0n-HXqHrfumQ,746
128
+ docs/make.bat,sha256=mBAhtURwhQ7yc95pqwJzlhqBSvRknr1aqZ5s8NKvdKs,4513
129
+ docs/requirements.txt,sha256=Kbl_X4c7RQZw035YTeNB63We6I7pvXFU4T0Uflp2yDY,29
130
+ licenses/LICENSE.rst,sha256=piZaQplkzOMmH1NXg6QIdo9wwo9pPCoHkvm2-DmH76E,1462
131
+ dkist_processing_common-12.1.0rc1.dist-info/METADATA,sha256=Sv5XyrgF8y0Gx_38hkXIqvcBsPKip3ug5Lfl0mP6lUs,14214
132
+ dkist_processing_common-12.1.0rc1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
133
+ dkist_processing_common-12.1.0rc1.dist-info/top_level.txt,sha256=LJhd1W-Vn90K8HnQDIE4r52YDpUjjMWDnllAWHBByW0,48
134
+ dkist_processing_common-12.1.0rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
docs/conf.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Configuration file for the Sphinx documentation builder."""
2
+
2
3
  # -- stdlib imports ------------------------------------------------------------
3
4
  import importlib
4
5
  import sys
docs/index.rst CHANGED
@@ -1,4 +1,4 @@
1
- .. include:: ../README.rst
1
+ .. include:: landing_page.rst
2
2
 
3
3
  .. toctree::
4
4
  :maxdepth: 2
docs/landing_page.rst ADDED
@@ -0,0 +1,13 @@
1
+ Overview
2
+ ========
3
+
4
+ The `dkist-processing-common` code repository is a library that works with
5
+ `dkist-processing-core <https://docs.dkist.nso.edu/projects/core/>`_ and
6
+ `dkist-processing-*instrument*` to form the DKIST calibration processing stack.
7
+
8
+ The classes in this library are used as the base of all DKIST processing pipeline
9
+ tasks. Task classes used in instrument pipelines are built on an abstract base class
10
+ defined here. Developers implement a `run` method with the required steps that the
11
+ task should take for a particular application. The class with its `run` method
12
+ is then used as the callable object for the workflow and scheduling engine
13
+ (which is managed by `dkist-processing-core <https://docs.dkist.nso.edu/projects/core/>`_).
@@ -1,166 +0,0 @@
1
- """Mixin for a WorkflowDataTaskBase subclass which implements input data set access functionality."""
2
- import json
3
- from dataclasses import dataclass
4
- from datetime import datetime
5
- from itertools import chain
6
- from pathlib import Path
7
- from typing import Any
8
-
9
- from dkist_processing_common.models.tags import Tag
10
- from dkist_processing_common.tasks.base import tag_type_hint
11
-
12
-
13
- frames_part_type_hint = list[dict[str, str | list[str]]] | None
14
-
15
-
16
- @dataclass
17
- class InputDatasetParameterValue:
18
- """Data structure for a de-serialized input dataset parameter value."""
19
-
20
- parameter_value_id: int
21
- parameter_value: Any = None
22
- parameter_value_start_date: datetime | None = None
23
-
24
-
25
- @dataclass
26
- class InputDatasetObject:
27
- """Data structure for a de-serialized input dataset frame."""
28
-
29
- bucket: str
30
- object_key: str
31
-
32
-
33
- class InputDatasetMixin:
34
- """Mixin for WorkflowDataTaskBase that accesses downloaded input dataset part documents."""
35
-
36
- def _input_dataset_part_document(self, tags: tag_type_hint):
37
- """Get the input dataset document part and deserialize it."""
38
- paths: list[Path] = list(self.read(tags=tags))
39
- if not paths:
40
- return
41
- if len(paths) > 1:
42
- raise ValueError(
43
- f"There are more than one input dataset part documents to parse for {tags=}"
44
- )
45
- p = paths[0]
46
- with p.open(mode="rb") as f:
47
- return json.load(f)
48
-
49
- @property
50
- def input_dataset_observe_frames_part_document(self) -> frames_part_type_hint:
51
- """Get the 'observe frames' part of the input dataset."""
52
- return self._input_dataset_part_document(tags=Tag.input_dataset_observe_frames())
53
-
54
- @property
55
- def input_dataset_calibration_frames_part_document(self) -> frames_part_type_hint:
56
- """Get the 'calibration frames' part of the input dataset."""
57
- return self._input_dataset_part_document(tags=Tag.input_dataset_calibration_frames())
58
-
59
- @property
60
- def input_dataset_parameters_part_document(
61
- self,
62
- ) -> list[dict[str, str | list[dict[str, int | str]]]] | None:
63
- """Get the 'parameters' part of the input dataset."""
64
- return self._input_dataset_part_document(tags=Tag.input_dataset_parameters())
65
-
66
- @property
67
- def input_dataset_frames(self) -> list[InputDatasetObject]:
68
- """Get the list of frames for this input dataset."""
69
- result = []
70
- observe_frames = self.input_dataset_observe_frames_part_document or []
71
- calibration_frames = self.input_dataset_calibration_frames_part_document or []
72
- for frame_set in chain(observe_frames, calibration_frames):
73
- for key in frame_set.get("object_keys", list()):
74
- result.append(InputDatasetObject(bucket=frame_set["bucket"], object_key=key))
75
- return result
76
-
77
- @property
78
- def input_dataset_parameters(self) -> dict[str, list[InputDatasetParameterValue]]:
79
- """Get the input dataset parameters."""
80
- parameters = self.input_dataset_parameters_part_document or []
81
- result = dict()
82
- for p in parameters:
83
- result.update(self._input_dataset_parse_parameter(p))
84
- return result
85
-
86
- @property
87
- def input_dataset_parameter_objects(self) -> list[InputDatasetObject]:
88
- """Parse the parameter object locations out of the set of all parameters."""
89
- result = []
90
- for value_list in self.input_dataset_parameters.values():
91
- for value in value_list:
92
- param_value = value.parameter_value
93
- if isinstance(param_value, dict) and param_value.get("is_file", False):
94
- result.append(
95
- InputDatasetObject(
96
- bucket=param_value["bucket"], object_key=param_value["objectKey"]
97
- )
98
- )
99
- return result
100
-
101
- def _input_dataset_parse_parameter(
102
- self, parameter: dict
103
- ) -> dict[str, list[InputDatasetParameterValue]]:
104
- name: str = parameter["parameterName"]
105
- raw_values: list[dict] = parameter["parameterValues"]
106
- values = self._input_dataset_parse_parameter_values(raw_values=raw_values)
107
- return {name: values}
108
-
109
- def _input_dataset_parse_parameter_values(
110
- self, raw_values: list[dict[str, Any]]
111
- ) -> list[InputDatasetParameterValue]:
112
- values = list()
113
- for v in raw_values:
114
- parsed_value = InputDatasetParameterValue(parameter_value_id=v["parameterValueId"])
115
- parsed_value.parameter_value = self._input_dataset_parse_parameter_value(
116
- raw_parameter_value=v["parameterValue"]
117
- )
118
- if d := v.get("parameterValueStartDate"):
119
- parsed_value.parameter_value_start_date = datetime.fromisoformat(d)
120
- else:
121
- parsed_value.parameter_value_start_date = datetime(1, 1, 1)
122
- values.append(parsed_value)
123
- return values
124
-
125
- def _input_dataset_parse_parameter_value(self, raw_parameter_value: str) -> Any:
126
- """Return the json decoding of the parameter value."""
127
- return json.loads(raw_parameter_value, object_hook=self._decode_parameter_value)
128
-
129
- def _decode_parameter_value(self, param_dict: dict):
130
- """Decode a parameter value."""
131
- if "__file__" in param_dict:
132
- return self._convert_parameter_file_value_to_path(param_dict)
133
- # Nothing to do here, so return control back to json.loads()
134
- return param_dict
135
-
136
- def _convert_parameter_file_value_to_path(self, param_dict: dict):
137
- """
138
- Decode a parameter file value.
139
-
140
- Note: for parameters that are files, the string passed to json.loads() looks like this:
141
- '{ "__file__":
142
- {
143
- "bucket": "data",
144
- "objectKey": "parameters/parameter_name/uuid.dat"
145
- }
146
- }'
147
-
148
- In this hook, we remove the outer __file__ dict and return the inner dict with the addition of
149
- a key and value for the file path. Because the file path is dependent on the existence of a tag,
150
- if no tag is found, None is returned for the path. This use case will occur when we construct
151
- the list of files to be transferred and tagged by the TransferL0Data task.
152
- """
153
- file_dict = param_dict["__file__"]
154
- object_key = file_dict["objectKey"]
155
- parameter_tag = Tag.parameter(Path(object_key).name)
156
- paths = list(self.read(tags=parameter_tag))
157
- num_paths = len(paths)
158
- if num_paths == 1:
159
- param_path = paths[0]
160
- elif num_paths == 0:
161
- param_path = None
162
- else:
163
- raise ValueError(f"Found multiple paths for {parameter_tag = }.")
164
- file_dict["param_path"] = param_path
165
- file_dict["is_file"] = True
166
- return file_dict