dkist-processing-common 10.8.1rc1__py3-none-any.whl → 10.8.3__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.
- dkist_processing_common/codecs/fits.py +6 -12
- dkist_processing_common/manual.py +5 -3
- dkist_processing_common/models/fried_parameter.py +41 -0
- dkist_processing_common/models/graphql.py +3 -13
- dkist_processing_common/models/parameters.py +28 -65
- dkist_processing_common/parsers/quality.py +1 -0
- dkist_processing_common/tasks/mixin/input_dataset.py +166 -0
- dkist_processing_common/tasks/mixin/metadata_store.py +4 -7
- dkist_processing_common/tasks/mixin/quality/_metrics.py +19 -14
- dkist_processing_common/tasks/quality_metrics.py +1 -1
- dkist_processing_common/tasks/transfer_input_data.py +70 -61
- dkist_processing_common/tasks/write_l1.py +29 -3
- dkist_processing_common/tests/conftest.py +7 -24
- dkist_processing_common/tests/test_codecs.py +0 -38
- dkist_processing_common/tests/test_fried_parameter.py +27 -0
- dkist_processing_common/tests/test_input_dataset.py +308 -79
- dkist_processing_common/tests/test_parameters.py +22 -71
- dkist_processing_common/tests/test_quality_mixin.py +32 -22
- dkist_processing_common/tests/test_transfer_input_data.py +45 -131
- dkist_processing_common/tests/test_write_l1.py +143 -10
- {dkist_processing_common-10.8.1rc1.dist-info → dkist_processing_common-10.8.3.dist-info}/METADATA +2 -2
- {dkist_processing_common-10.8.1rc1.dist-info → dkist_processing_common-10.8.3.dist-info}/RECORD +24 -27
- {dkist_processing_common-10.8.1rc1.dist-info → dkist_processing_common-10.8.3.dist-info}/WHEEL +1 -1
- changelog/235.feature.rst +0 -3
- changelog/235.misc.1.rst +0 -2
- changelog/235.misc.rst +0 -1
- dkist_processing_common/codecs/array.py +0 -19
- dkist_processing_common/codecs/basemodel.py +0 -21
- dkist_processing_common/models/input_dataset.py +0 -113
- {dkist_processing_common-10.8.1rc1.dist-info → dkist_processing_common-10.8.3.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from copy import copy
|
|
2
3
|
from datetime import datetime
|
|
4
|
+
from pathlib import Path
|
|
3
5
|
from typing import Any
|
|
4
6
|
from uuid import uuid4
|
|
5
7
|
|
|
6
8
|
import pytest
|
|
7
9
|
|
|
8
|
-
from dkist_processing_common.codecs.basemodel import basemodel_decoder
|
|
9
|
-
from dkist_processing_common.models.input_dataset import InputDatasetPartDocumentList
|
|
10
10
|
from dkist_processing_common.models.tags import Tag
|
|
11
|
+
from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetMixin
|
|
12
|
+
from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetObject
|
|
13
|
+
from dkist_processing_common.tests.conftest import create_parameter_files
|
|
14
|
+
from dkist_processing_common.tests.conftest import InputDatasetTask
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
def input_dataset_frames_part_factory(bucket_count: int = 1) -> list[dict]:
|
|
@@ -43,9 +47,7 @@ def input_dataset_parameters_part_factory(
|
|
|
43
47
|
]
|
|
44
48
|
if has_date:
|
|
45
49
|
for data in result:
|
|
46
|
-
|
|
47
|
-
for item in param_list:
|
|
48
|
-
item["parameterValueStartDate"] = datetime(2022, 9, 14).isoformat()
|
|
50
|
+
data["parameterValueStartDate"] = datetime(2022, 9, 14).isoformat()[:10]
|
|
49
51
|
if has_file:
|
|
50
52
|
for data in result:
|
|
51
53
|
param_list = data["parameterValues"]
|
|
@@ -64,42 +66,99 @@ def input_dataset_parameters_part_factory(
|
|
|
64
66
|
@pytest.mark.parametrize(
|
|
65
67
|
"input_dataset_parts",
|
|
66
68
|
[
|
|
69
|
+
pytest.param((None, Tag.input_dataset_observe_frames()), id="empty"),
|
|
67
70
|
pytest.param(
|
|
68
71
|
(input_dataset_frames_part_factory(), Tag.input_dataset_observe_frames()),
|
|
69
|
-
id="
|
|
72
|
+
id="single_bucket",
|
|
70
73
|
),
|
|
71
74
|
pytest.param(
|
|
72
75
|
(input_dataset_frames_part_factory(bucket_count=2), Tag.input_dataset_observe_frames()),
|
|
73
|
-
id="
|
|
76
|
+
id="multi_bucket",
|
|
74
77
|
),
|
|
78
|
+
],
|
|
79
|
+
)
|
|
80
|
+
def test_input_dataset_observe_frames_part_document(
|
|
81
|
+
task_with_input_dataset, input_dataset_parts: tuple[Any, str]
|
|
82
|
+
):
|
|
83
|
+
"""
|
|
84
|
+
Given: A task with an input dataset observe frames part document tagged as such
|
|
85
|
+
When: Accessing the document via the InputDatasetMixIn
|
|
86
|
+
Then: The contents of the file are returned
|
|
87
|
+
"""
|
|
88
|
+
doc_part, _ = input_dataset_parts
|
|
89
|
+
task = task_with_input_dataset
|
|
90
|
+
assert task.input_dataset_observe_frames_part_document == doc_part
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@pytest.mark.parametrize(
|
|
94
|
+
"input_dataset_parts",
|
|
95
|
+
[
|
|
96
|
+
pytest.param((None, Tag.input_dataset_calibration_frames()), id="empty"),
|
|
75
97
|
pytest.param(
|
|
76
98
|
(input_dataset_frames_part_factory(), Tag.input_dataset_calibration_frames()),
|
|
77
|
-
id="
|
|
99
|
+
id="single_bucket",
|
|
78
100
|
),
|
|
79
101
|
pytest.param(
|
|
80
102
|
(
|
|
81
103
|
input_dataset_frames_part_factory(bucket_count=2),
|
|
82
104
|
Tag.input_dataset_calibration_frames(),
|
|
83
105
|
),
|
|
84
|
-
id="
|
|
106
|
+
id="multi_bucket",
|
|
107
|
+
),
|
|
108
|
+
],
|
|
109
|
+
)
|
|
110
|
+
def test_input_dataset_calibration_frames_part_document(
|
|
111
|
+
task_with_input_dataset, input_dataset_parts: tuple[Any, str]
|
|
112
|
+
):
|
|
113
|
+
"""
|
|
114
|
+
Given: A task with an input dataset calibration frames part document tagged as such
|
|
115
|
+
When: Accessing the document via the InputDatasetMixIn
|
|
116
|
+
Then: The contents of the file are returned
|
|
117
|
+
"""
|
|
118
|
+
doc_part, _ = input_dataset_parts
|
|
119
|
+
task = task_with_input_dataset
|
|
120
|
+
assert task.input_dataset_calibration_frames_part_document == doc_part
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@pytest.mark.parametrize(
|
|
124
|
+
"input_dataset_parts",
|
|
125
|
+
[
|
|
126
|
+
pytest.param((None, Tag.input_dataset_parameters()), id="empty"),
|
|
127
|
+
pytest.param(
|
|
128
|
+
(input_dataset_parameters_part_factory(), Tag.input_dataset_parameters()),
|
|
129
|
+
id="single_param_no_date",
|
|
130
|
+
),
|
|
131
|
+
pytest.param(
|
|
132
|
+
(
|
|
133
|
+
input_dataset_parameters_part_factory(parameter_count=2),
|
|
134
|
+
Tag.input_dataset_parameters(),
|
|
135
|
+
),
|
|
136
|
+
id="multi_param_no_date",
|
|
137
|
+
),
|
|
138
|
+
pytest.param(
|
|
139
|
+
(input_dataset_parameters_part_factory(has_date=True), Tag.input_dataset_parameters()),
|
|
140
|
+
id="single_param_with_date",
|
|
141
|
+
),
|
|
142
|
+
pytest.param(
|
|
143
|
+
(
|
|
144
|
+
input_dataset_parameters_part_factory(parameter_count=2, has_date=True),
|
|
145
|
+
Tag.input_dataset_parameters(),
|
|
146
|
+
),
|
|
147
|
+
id="multi_param_with_date",
|
|
85
148
|
),
|
|
86
149
|
],
|
|
87
150
|
)
|
|
88
|
-
def
|
|
151
|
+
def test_input_dataset_parameters_part_document(
|
|
89
152
|
task_with_input_dataset, input_dataset_parts: tuple[Any, str]
|
|
90
153
|
):
|
|
91
154
|
"""
|
|
92
|
-
Given: A task with an input dataset
|
|
93
|
-
When:
|
|
94
|
-
Then: The
|
|
155
|
+
Given: A task with an input dataset parameters part document tagged as such
|
|
156
|
+
When: Accessing the document via the InputDatasetMixIn
|
|
157
|
+
Then: The contents of the file are returned
|
|
95
158
|
"""
|
|
96
|
-
doc_part,
|
|
159
|
+
doc_part, _ = input_dataset_parts
|
|
97
160
|
task = task_with_input_dataset
|
|
98
|
-
|
|
99
|
-
task.read(tags=tag, decoder=basemodel_decoder, model=InputDatasetPartDocumentList)
|
|
100
|
-
)
|
|
101
|
-
frames = [frames.model_dump() for frames in doc_from_file.doc_list]
|
|
102
|
-
assert frames == doc_part
|
|
161
|
+
assert task.input_dataset_parameters_part_document == doc_part
|
|
103
162
|
|
|
104
163
|
|
|
105
164
|
@pytest.mark.parametrize(
|
|
@@ -115,15 +174,24 @@ def test_input_dataset_frames_part_document(
|
|
|
115
174
|
pytest.param(
|
|
116
175
|
[
|
|
117
176
|
(input_dataset_frames_part_factory(), Tag.input_dataset_observe_frames()),
|
|
177
|
+
(None, Tag.input_dataset_calibration_frames()),
|
|
118
178
|
],
|
|
119
179
|
id="observe1_cal0_single_bucket",
|
|
120
180
|
),
|
|
121
181
|
pytest.param(
|
|
122
182
|
[
|
|
183
|
+
(None, Tag.input_dataset_observe_frames()),
|
|
123
184
|
(input_dataset_frames_part_factory(), Tag.input_dataset_calibration_frames()),
|
|
124
185
|
],
|
|
125
186
|
id="observe0_cal1_single_bucket",
|
|
126
187
|
),
|
|
188
|
+
pytest.param(
|
|
189
|
+
[
|
|
190
|
+
(None, Tag.input_dataset_observe_frames()),
|
|
191
|
+
(None, Tag.input_dataset_calibration_frames()),
|
|
192
|
+
],
|
|
193
|
+
id="observe0_cal0_single_bucket",
|
|
194
|
+
),
|
|
127
195
|
pytest.param(
|
|
128
196
|
[
|
|
129
197
|
(
|
|
@@ -143,11 +211,13 @@ def test_input_dataset_frames_part_document(
|
|
|
143
211
|
input_dataset_frames_part_factory(bucket_count=2),
|
|
144
212
|
Tag.input_dataset_observe_frames(),
|
|
145
213
|
),
|
|
214
|
+
(None, Tag.input_dataset_calibration_frames()),
|
|
146
215
|
],
|
|
147
216
|
id="observe1_cal0_multi_bucket",
|
|
148
217
|
),
|
|
149
218
|
pytest.param(
|
|
150
219
|
[
|
|
220
|
+
(None, Tag.input_dataset_observe_frames()),
|
|
151
221
|
(
|
|
152
222
|
input_dataset_frames_part_factory(bucket_count=2),
|
|
153
223
|
Tag.input_dataset_calibration_frames(),
|
|
@@ -155,17 +225,21 @@ def test_input_dataset_frames_part_document(
|
|
|
155
225
|
],
|
|
156
226
|
id="observe0_cal1_multi_bucket",
|
|
157
227
|
),
|
|
228
|
+
pytest.param(
|
|
229
|
+
[
|
|
230
|
+
(None, Tag.input_dataset_observe_frames()),
|
|
231
|
+
(None, Tag.input_dataset_calibration_frames()),
|
|
232
|
+
],
|
|
233
|
+
id="observe0_cal0_multi_bucket",
|
|
234
|
+
),
|
|
158
235
|
],
|
|
159
236
|
)
|
|
160
|
-
def
|
|
161
|
-
task_with_input_dataset, input_dataset_parts: list[tuple[Any, str]]
|
|
162
|
-
):
|
|
237
|
+
def test_input_dataset_frames(task_with_input_dataset, input_dataset_parts: list[tuple[Any, str]]):
|
|
163
238
|
"""
|
|
164
|
-
Given:
|
|
165
|
-
When:
|
|
166
|
-
Then:
|
|
239
|
+
Given: a task with the InputDatasetMixin
|
|
240
|
+
When: getting the frames in the input dataset
|
|
241
|
+
Then: it matches the frames used to create the input dataset
|
|
167
242
|
"""
|
|
168
|
-
# Given
|
|
169
243
|
doc_parts = [part for part, _ in input_dataset_parts]
|
|
170
244
|
task = task_with_input_dataset
|
|
171
245
|
expected = []
|
|
@@ -173,29 +247,7 @@ def test_input_dataset_frames_combination(
|
|
|
173
247
|
if part:
|
|
174
248
|
expected.extend(flatten_frame_parts(part))
|
|
175
249
|
expected_set = set(expected)
|
|
176
|
-
|
|
177
|
-
frames = []
|
|
178
|
-
observe_frames = next(
|
|
179
|
-
task.read(
|
|
180
|
-
tags=Tag.input_dataset_observe_frames(),
|
|
181
|
-
decoder=basemodel_decoder,
|
|
182
|
-
model=InputDatasetPartDocumentList,
|
|
183
|
-
),
|
|
184
|
-
None,
|
|
185
|
-
)
|
|
186
|
-
frames += observe_frames.doc_list if observe_frames else []
|
|
187
|
-
calibration_frames = next(
|
|
188
|
-
task.read(
|
|
189
|
-
tags=Tag.input_dataset_calibration_frames(),
|
|
190
|
-
decoder=basemodel_decoder,
|
|
191
|
-
model=InputDatasetPartDocumentList,
|
|
192
|
-
),
|
|
193
|
-
None,
|
|
194
|
-
)
|
|
195
|
-
frames += calibration_frames.doc_list if calibration_frames else []
|
|
196
|
-
# Then
|
|
197
|
-
frames_objects = sum([f.input_dataset_objects for f in frames], [])
|
|
198
|
-
actual = [(frame.bucket, frame.object_key) for frame in frames_objects]
|
|
250
|
+
actual = [(frame.bucket, frame.object_key) for frame in task.input_dataset_frames]
|
|
199
251
|
actual_set = set(actual)
|
|
200
252
|
assert len(actual) == len(actual_set)
|
|
201
253
|
assert actual_set.difference(expected_set) == set()
|
|
@@ -204,45 +256,114 @@ def test_input_dataset_frames_combination(
|
|
|
204
256
|
@pytest.mark.parametrize(
|
|
205
257
|
"input_dataset_parts",
|
|
206
258
|
[
|
|
259
|
+
pytest.param((None, Tag.input_dataset_parameters()), id="empty"),
|
|
207
260
|
pytest.param(
|
|
208
261
|
(input_dataset_parameters_part_factory(), Tag.input_dataset_parameters()),
|
|
209
262
|
id="single_param_no_date_no_file",
|
|
210
263
|
),
|
|
211
264
|
pytest.param(
|
|
212
265
|
(input_dataset_parameters_part_factory(has_file=True), Tag.input_dataset_parameters()),
|
|
213
|
-
id="
|
|
266
|
+
id="single_param_no_date",
|
|
214
267
|
),
|
|
215
268
|
pytest.param(
|
|
216
|
-
(
|
|
217
|
-
|
|
269
|
+
(
|
|
270
|
+
input_dataset_parameters_part_factory(parameter_count=2, has_file=True),
|
|
271
|
+
Tag.input_dataset_parameters(),
|
|
272
|
+
),
|
|
273
|
+
id="multi_param_no_date",
|
|
218
274
|
),
|
|
219
275
|
pytest.param(
|
|
220
276
|
(
|
|
221
|
-
input_dataset_parameters_part_factory(
|
|
277
|
+
input_dataset_parameters_part_factory(parameter_value_count=2, has_file=True),
|
|
222
278
|
Tag.input_dataset_parameters(),
|
|
223
279
|
),
|
|
224
|
-
id="
|
|
280
|
+
id="multi_param_values_no_date",
|
|
225
281
|
),
|
|
226
282
|
pytest.param(
|
|
227
283
|
(
|
|
228
|
-
input_dataset_parameters_part_factory(
|
|
284
|
+
input_dataset_parameters_part_factory(has_date=True, has_file=True),
|
|
229
285
|
Tag.input_dataset_parameters(),
|
|
230
286
|
),
|
|
231
|
-
id="
|
|
287
|
+
id="single_param_with_date",
|
|
232
288
|
),
|
|
233
289
|
pytest.param(
|
|
234
290
|
(
|
|
235
|
-
input_dataset_parameters_part_factory(
|
|
291
|
+
input_dataset_parameters_part_factory(
|
|
292
|
+
parameter_count=2, has_date=True, has_file=True
|
|
293
|
+
),
|
|
236
294
|
Tag.input_dataset_parameters(),
|
|
237
295
|
),
|
|
238
|
-
id="
|
|
296
|
+
id="multi_param_with_date",
|
|
297
|
+
),
|
|
298
|
+
],
|
|
299
|
+
)
|
|
300
|
+
def test_input_dataset_parameters(
|
|
301
|
+
task_with_input_dataset, input_dataset_parts: list[tuple[Any, str]]
|
|
302
|
+
):
|
|
303
|
+
"""
|
|
304
|
+
Given: a task with the InputDatasetMixin
|
|
305
|
+
When: getting the parameters in the input dataset
|
|
306
|
+
Then: the names of the parameters match the keys in the returned dictionary
|
|
307
|
+
"""
|
|
308
|
+
task = task_with_input_dataset
|
|
309
|
+
doc_part, _ = input_dataset_parts
|
|
310
|
+
doc_part = doc_part or [] # None case parsing of expected values
|
|
311
|
+
create_parameter_files(task, doc_part)
|
|
312
|
+
expected_parameters = {item["parameterName"]: item["parameterValues"] for item in doc_part}
|
|
313
|
+
for key, values in task.input_dataset_parameters.items():
|
|
314
|
+
assert key in expected_parameters
|
|
315
|
+
expected_values = expected_parameters[key]
|
|
316
|
+
# Iterate through multiple values if they exist
|
|
317
|
+
for value in values:
|
|
318
|
+
# Find the matching expected value for this value object
|
|
319
|
+
expected_value = [
|
|
320
|
+
item
|
|
321
|
+
for item in expected_values
|
|
322
|
+
if value.parameter_value_id == item["parameterValueId"]
|
|
323
|
+
]
|
|
324
|
+
# Make sure there's only one value
|
|
325
|
+
assert len(expected_value) == 1
|
|
326
|
+
# Now check the value
|
|
327
|
+
expected_value = expected_value[0]
|
|
328
|
+
assert value.parameter_value == json.loads(
|
|
329
|
+
expected_value["parameterValue"], object_hook=task._decode_parameter_value
|
|
330
|
+
)
|
|
331
|
+
expected_date = expected_value.get("parameterValueStartDate", datetime(1, 1, 1))
|
|
332
|
+
assert value.parameter_value_start_date == expected_date
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@pytest.mark.parametrize(
|
|
336
|
+
"input_dataset_parts",
|
|
337
|
+
[
|
|
338
|
+
pytest.param((None, Tag.input_dataset_parameters()), id="empty"),
|
|
339
|
+
pytest.param(
|
|
340
|
+
(input_dataset_parameters_part_factory(), Tag.input_dataset_parameters()),
|
|
341
|
+
id="single_param_no_date_no_file",
|
|
342
|
+
),
|
|
343
|
+
pytest.param(
|
|
344
|
+
(input_dataset_parameters_part_factory(has_file=True), Tag.input_dataset_parameters()),
|
|
345
|
+
id="single_param_no_date",
|
|
239
346
|
),
|
|
240
347
|
pytest.param(
|
|
241
348
|
(
|
|
242
349
|
input_dataset_parameters_part_factory(parameter_count=2, has_file=True),
|
|
243
350
|
Tag.input_dataset_parameters(),
|
|
244
351
|
),
|
|
245
|
-
id="
|
|
352
|
+
id="multi_param_no_date",
|
|
353
|
+
),
|
|
354
|
+
pytest.param(
|
|
355
|
+
(
|
|
356
|
+
input_dataset_parameters_part_factory(parameter_value_count=2, has_file=True),
|
|
357
|
+
Tag.input_dataset_parameters(),
|
|
358
|
+
),
|
|
359
|
+
id="multi_param_values_no_date",
|
|
360
|
+
),
|
|
361
|
+
pytest.param(
|
|
362
|
+
(
|
|
363
|
+
input_dataset_parameters_part_factory(has_date=True, has_file=True),
|
|
364
|
+
Tag.input_dataset_parameters(),
|
|
365
|
+
),
|
|
366
|
+
id="single_param_with_date",
|
|
246
367
|
),
|
|
247
368
|
pytest.param(
|
|
248
369
|
(
|
|
@@ -251,30 +372,138 @@ def test_input_dataset_frames_combination(
|
|
|
251
372
|
),
|
|
252
373
|
Tag.input_dataset_parameters(),
|
|
253
374
|
),
|
|
254
|
-
id="
|
|
375
|
+
id="multi_param_with_date",
|
|
255
376
|
),
|
|
256
377
|
],
|
|
257
378
|
)
|
|
258
|
-
def
|
|
379
|
+
def test_input_dataset_parameter_objects(
|
|
380
|
+
task_with_input_dataset, input_dataset_parts: list[tuple[Any, str]]
|
|
381
|
+
):
|
|
259
382
|
"""
|
|
260
|
-
Given:
|
|
261
|
-
When:
|
|
262
|
-
Then:
|
|
383
|
+
Given: a task with the InputDatasetMixin
|
|
384
|
+
When: getting the parameters objects in the input dataset
|
|
385
|
+
Then: the InputDatsetObjects returned by the task method match the objects defined by the input
|
|
386
|
+
dataset doc part
|
|
263
387
|
"""
|
|
264
|
-
doc_part, tag = input_dataset_parts
|
|
265
388
|
task = task_with_input_dataset
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
389
|
+
doc_part, _ = input_dataset_parts
|
|
390
|
+
doc_part = doc_part or [] # None case parsing of expected values
|
|
391
|
+
|
|
392
|
+
# Create a list of InputDatasetObjects from the input dataset doc part
|
|
393
|
+
expected_parameters = list()
|
|
394
|
+
for param_item in doc_part:
|
|
395
|
+
param_values_list = param_item["parameterValues"]
|
|
396
|
+
for param_value_dict in param_values_list:
|
|
397
|
+
if "__file__" in param_value_dict["parameterValue"]:
|
|
398
|
+
file_dict = json.loads(
|
|
399
|
+
param_value_dict["parameterValue"], object_hook=task._decode_parameter_value
|
|
400
|
+
)
|
|
401
|
+
expected_parameters.append(
|
|
402
|
+
InputDatasetObject(
|
|
403
|
+
bucket=file_dict["bucket"], object_key=file_dict["objectKey"]
|
|
404
|
+
)
|
|
405
|
+
)
|
|
406
|
+
# Check that each InputDatasetObject returned by the task is in the list of expected parameters
|
|
407
|
+
input_dataset_parameter_objects = task.input_dataset_parameter_objects
|
|
408
|
+
assert len(input_dataset_parameter_objects) == len(expected_parameters)
|
|
409
|
+
for input_dataset_object in input_dataset_parameter_objects:
|
|
410
|
+
assert input_dataset_object in expected_parameters
|
|
269
411
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
412
|
+
|
|
413
|
+
@pytest.mark.parametrize(
|
|
414
|
+
"input_parameter_dict",
|
|
415
|
+
[
|
|
416
|
+
{"bucket": "data", "objectKey": "parameters/805c46/714ff939158b4253859cde5e5d6f62c3.dat"},
|
|
417
|
+
{
|
|
418
|
+
"__file__": {
|
|
419
|
+
"bucket": "data",
|
|
420
|
+
"objectKey": "parameters/805c46/714ff939158b4253859cde5e5d6f62c3.dat",
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
{"key_name_1": "value_1", "key_name_2": "value_2", "key_name_3": "value_3"},
|
|
424
|
+
],
|
|
425
|
+
)
|
|
426
|
+
def test_convert_parameter_file_to_path(recipe_run_id, input_parameter_dict: dict):
|
|
427
|
+
"""
|
|
428
|
+
Given: a parameter value field to be json decoded
|
|
429
|
+
When: passing the parameter value string to the json decoder hook
|
|
430
|
+
Then: the hook passes non-file parameter strings without change and modifies file parameter strings
|
|
431
|
+
by replacing the __file__ dict in the value string with a bucket field, an objectKey field
|
|
432
|
+
and adds a param_path field and an is_file field
|
|
433
|
+
"""
|
|
434
|
+
# Initial test with no tags
|
|
435
|
+
with InputDatasetTask(
|
|
436
|
+
recipe_run_id=recipe_run_id,
|
|
437
|
+
workflow_name="workflow_name",
|
|
438
|
+
workflow_version="workflow_version",
|
|
439
|
+
) as task:
|
|
440
|
+
# Test with no tags...
|
|
441
|
+
input_dict = input_parameter_dict
|
|
442
|
+
output_dict = task._decode_parameter_value(input_dict)
|
|
443
|
+
if "__file__" not in input_dict:
|
|
444
|
+
assert input_dict == output_dict
|
|
445
|
+
else:
|
|
446
|
+
value_dict = input_dict["__file__"]
|
|
447
|
+
assert output_dict["bucket"] == value_dict["bucket"]
|
|
448
|
+
assert output_dict["objectKey"] == value_dict["objectKey"]
|
|
449
|
+
assert output_dict["is_file"]
|
|
450
|
+
assert output_dict["param_path"] is None
|
|
451
|
+
# Test with tags
|
|
452
|
+
if "__file__" not in input_dict:
|
|
453
|
+
output_dict = task._decode_parameter_value(input_dict)
|
|
454
|
+
assert input_dict == output_dict
|
|
455
|
+
else:
|
|
456
|
+
# Create the destination path
|
|
457
|
+
param_path = input_dict["__file__"]["objectKey"]
|
|
458
|
+
destination_path = task.scratch.absolute_path(param_path)
|
|
459
|
+
if not destination_path.parent.exists():
|
|
460
|
+
destination_path.parent.mkdir(parents=True, exist_ok=True)
|
|
461
|
+
destination_path.write_text(data="")
|
|
462
|
+
task.tag(path=destination_path, tags=Tag.parameter(destination_path.name))
|
|
463
|
+
output_dict = task._decode_parameter_value(input_dict)
|
|
464
|
+
value_dict = input_dict["__file__"]
|
|
465
|
+
assert output_dict["bucket"] == value_dict["bucket"]
|
|
466
|
+
assert output_dict["objectKey"] == value_dict["objectKey"]
|
|
467
|
+
assert output_dict["is_file"]
|
|
468
|
+
assert output_dict["param_path"] == destination_path
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
@pytest.mark.parametrize(
|
|
472
|
+
"input_dataset_parts",
|
|
473
|
+
[
|
|
474
|
+
pytest.param(
|
|
475
|
+
[
|
|
476
|
+
(input_dataset_frames_part_factory(), Tag.input_dataset_observe_frames()),
|
|
477
|
+
(input_dataset_frames_part_factory(), Tag.input_dataset_observe_frames()),
|
|
478
|
+
],
|
|
479
|
+
id="observe",
|
|
480
|
+
),
|
|
481
|
+
pytest.param(
|
|
482
|
+
[
|
|
483
|
+
(input_dataset_frames_part_factory(), Tag.input_dataset_calibration_frames()),
|
|
484
|
+
(input_dataset_frames_part_factory(), Tag.input_dataset_calibration_frames()),
|
|
485
|
+
],
|
|
486
|
+
id="calibration",
|
|
487
|
+
),
|
|
488
|
+
pytest.param(
|
|
489
|
+
[
|
|
490
|
+
(input_dataset_frames_part_factory(), Tag.input_dataset_parameters()),
|
|
491
|
+
(input_dataset_frames_part_factory(), Tag.input_dataset_parameters()),
|
|
492
|
+
],
|
|
493
|
+
id="params",
|
|
494
|
+
),
|
|
495
|
+
],
|
|
496
|
+
)
|
|
497
|
+
def test_multiple_input_dataset_parts(
|
|
498
|
+
task_with_input_dataset, input_dataset_parts: list[tuple[Any, str]]
|
|
499
|
+
):
|
|
500
|
+
"""
|
|
501
|
+
Given: a task with the InputDatasetMixin and multiple tagged input datasets
|
|
502
|
+
When: reading the input dataset document
|
|
503
|
+
Then: an error is raised
|
|
504
|
+
"""
|
|
505
|
+
task = task_with_input_dataset
|
|
506
|
+
with pytest.raises(ValueError):
|
|
507
|
+
task.input_dataset_parameters_part_document
|
|
508
|
+
task.input_dataset_observe_frames_part_document
|
|
509
|
+
task.input_dataset_calibration_frames_part_document
|
|
@@ -18,22 +18,22 @@ import numpy as np
|
|
|
18
18
|
import pytest
|
|
19
19
|
from astropy.io import fits
|
|
20
20
|
|
|
21
|
-
from dkist_processing_common.codecs.array import array_encoder
|
|
22
|
-
from dkist_processing_common.codecs.fits import fits_hdulist_encoder
|
|
23
21
|
from dkist_processing_common.models.parameters import ParameterArmIdMixin
|
|
24
22
|
from dkist_processing_common.models.parameters import ParameterBase
|
|
25
23
|
from dkist_processing_common.models.parameters import ParameterWavelengthMixin
|
|
26
24
|
from dkist_processing_common.models.tags import Tag
|
|
27
25
|
from dkist_processing_common.tasks import WorkflowTaskBase
|
|
28
|
-
from dkist_processing_common.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
FITS_FILE = "fits.dat"
|
|
32
|
-
NP_FILE = "np.npy"
|
|
26
|
+
from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetMixin
|
|
33
27
|
|
|
34
28
|
|
|
35
29
|
@pytest.fixture
|
|
36
|
-
def input_dataset_parameters():
|
|
30
|
+
def input_dataset_parameters(tmp_path):
|
|
31
|
+
fits_file_path = tmp_path / "fits.dat"
|
|
32
|
+
phdu = fits.PrimaryHDU(np.ones((3, 3)) * 3)
|
|
33
|
+
ihdu = fits.ImageHDU(np.ones((4, 4)) * 4)
|
|
34
|
+
fits.HDUList([phdu, ihdu]).writeto(fits_file_path)
|
|
35
|
+
np_file_path = tmp_path / "np.npy"
|
|
36
|
+
np.save(np_file_path, np.ones((3, 3)) * 4)
|
|
37
37
|
return [
|
|
38
38
|
{
|
|
39
39
|
"parameterName": "basic_param",
|
|
@@ -106,15 +106,7 @@ def input_dataset_parameters():
|
|
|
106
106
|
"parameterValues": [
|
|
107
107
|
{
|
|
108
108
|
"parameterValueId": 1,
|
|
109
|
-
"parameterValue": json.dumps(
|
|
110
|
-
{
|
|
111
|
-
"__file__": {
|
|
112
|
-
"bucket": "not_used",
|
|
113
|
-
"objectKey": "not_used",
|
|
114
|
-
"tag": Tag.parameter(FITS_FILE),
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
),
|
|
109
|
+
"parameterValue": json.dumps({"param_path": str(fits_file_path)}),
|
|
118
110
|
}
|
|
119
111
|
],
|
|
120
112
|
},
|
|
@@ -123,15 +115,7 @@ def input_dataset_parameters():
|
|
|
123
115
|
"parameterValues": [
|
|
124
116
|
{
|
|
125
117
|
"parameterValueId": 1,
|
|
126
|
-
"parameterValue": json.dumps(
|
|
127
|
-
{
|
|
128
|
-
"__file__": {
|
|
129
|
-
"bucket": "not_used",
|
|
130
|
-
"objectKey": "not_used",
|
|
131
|
-
"tag": Tag.parameter(NP_FILE),
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
),
|
|
118
|
+
"parameterValue": json.dumps({"param_path": str(np_file_path)}),
|
|
135
119
|
}
|
|
136
120
|
],
|
|
137
121
|
},
|
|
@@ -145,14 +129,16 @@ def input_dataset_parts(input_dataset_parameters) -> tuple[Any, str]:
|
|
|
145
129
|
|
|
146
130
|
@pytest.fixture()
|
|
147
131
|
def task_class_with_parameters(parameter_class) -> Type[WorkflowTaskBase]:
|
|
148
|
-
class TaskWithParameters(WorkflowTaskBase):
|
|
132
|
+
class TaskWithParameters(WorkflowTaskBase, InputDatasetMixin):
|
|
149
133
|
def __init__(self, recipe_run_id: int, workflow_name: str, workflow_version: str):
|
|
150
134
|
super().__init__(
|
|
151
135
|
recipe_run_id=recipe_run_id,
|
|
152
136
|
workflow_name=workflow_name,
|
|
153
137
|
workflow_version=workflow_version,
|
|
154
138
|
)
|
|
155
|
-
self.parameters = parameter_class(
|
|
139
|
+
self.parameters = parameter_class(
|
|
140
|
+
input_dataset_parameters=self.input_dataset_parameters
|
|
141
|
+
)
|
|
156
142
|
|
|
157
143
|
def run(self) -> None:
|
|
158
144
|
pass
|
|
@@ -163,21 +149,11 @@ def task_class_with_parameters(parameter_class) -> Type[WorkflowTaskBase]:
|
|
|
163
149
|
@pytest.fixture()
|
|
164
150
|
def task_with_parameters(task_with_input_dataset, task_class_with_parameters):
|
|
165
151
|
task_class = task_class_with_parameters
|
|
166
|
-
|
|
152
|
+
return task_class(
|
|
167
153
|
recipe_run_id=task_with_input_dataset.recipe_run_id,
|
|
168
154
|
workflow_name=task_with_input_dataset.workflow_name,
|
|
169
155
|
workflow_version=task_with_input_dataset.workflow_version,
|
|
170
|
-
)
|
|
171
|
-
phdu = fits.PrimaryHDU(np.ones((3, 3)) * 3)
|
|
172
|
-
ihdu = fits.ImageHDU(np.ones((4, 4)) * 4)
|
|
173
|
-
task.write(
|
|
174
|
-
data=fits.HDUList([phdu, ihdu]),
|
|
175
|
-
tags=Tag.parameter(FITS_FILE),
|
|
176
|
-
encoder=fits_hdulist_encoder,
|
|
177
|
-
)
|
|
178
|
-
task.write(data=np.ones((3, 3)) * 4, tags=Tag.parameter(NP_FILE), encoder=array_encoder)
|
|
179
|
-
yield task
|
|
180
|
-
task._purge()
|
|
156
|
+
)
|
|
181
157
|
|
|
182
158
|
|
|
183
159
|
class FilledParametersNoObsTime(ParameterBase):
|
|
@@ -206,18 +182,18 @@ class FilledParametersWithObsTime(ParameterBase):
|
|
|
206
182
|
|
|
207
183
|
@property
|
|
208
184
|
def fits_file_parameter(self):
|
|
209
|
-
|
|
210
|
-
return self._load_param_value_from_fits(
|
|
185
|
+
param_dict = self._find_most_recent_past_value("fits_file_parameter")
|
|
186
|
+
return self._load_param_value_from_fits(param_dict)
|
|
211
187
|
|
|
212
188
|
@property
|
|
213
189
|
def non_primary_fits_file_parameter(self):
|
|
214
|
-
|
|
215
|
-
return self._load_param_value_from_fits(
|
|
190
|
+
param_dict = self._find_most_recent_past_value("fits_file_parameter")
|
|
191
|
+
return self._load_param_value_from_fits(param_dict, hdu=1)
|
|
216
192
|
|
|
217
193
|
@property
|
|
218
194
|
def numpy_file_parameter(self):
|
|
219
|
-
|
|
220
|
-
return self._load_param_value_from_numpy_save(
|
|
195
|
+
param_dict = self._find_most_recent_past_value("numpy_file_parameter")
|
|
196
|
+
return self._load_param_value_from_numpy_save(param_dict)
|
|
221
197
|
|
|
222
198
|
|
|
223
199
|
def parameter_class_with_obs_ip_start_time():
|
|
@@ -367,28 +343,3 @@ def test_mixins_error_with_no_arg():
|
|
|
367
343
|
"""
|
|
368
344
|
with pytest.raises(TypeError):
|
|
369
345
|
parameters = FilledWavelengthParameters(input_dataset_parameters={"foo": []})
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
@pytest.mark.parametrize(
|
|
373
|
-
("input_dataset_parts", "parameter_class"),
|
|
374
|
-
[
|
|
375
|
-
pytest.param(
|
|
376
|
-
[
|
|
377
|
-
(input_dataset_frames_part_factory(), Tag.input_dataset_parameters()),
|
|
378
|
-
(input_dataset_frames_part_factory(), Tag.input_dataset_parameters()),
|
|
379
|
-
],
|
|
380
|
-
parameter_class_with_obs_ip_start_time(),
|
|
381
|
-
id="two_param_docs",
|
|
382
|
-
),
|
|
383
|
-
],
|
|
384
|
-
)
|
|
385
|
-
def test_multiple_input_dataset_parameter_parts(
|
|
386
|
-
request, input_dataset_parts: list[tuple[Any, str]], parameter_class
|
|
387
|
-
):
|
|
388
|
-
"""
|
|
389
|
-
Given: a task with multiple tagged input dataset parameter docs
|
|
390
|
-
When: initializing the parameter base
|
|
391
|
-
Then: an error is raised
|
|
392
|
-
"""
|
|
393
|
-
with pytest.raises(ValueError, match="more than one parameter file"):
|
|
394
|
-
request.getfixturevalue("task_with_parameters")
|