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.
- changelog/280.misc.rst +1 -0
- changelog/282.feature.2.rst +2 -0
- changelog/282.feature.rst +2 -0
- changelog/284.feature.rst +1 -0
- changelog/285.feature.rst +2 -0
- changelog/285.misc.rst +2 -0
- changelog/286.feature.rst +2 -0
- changelog/287.misc.rst +1 -0
- dkist_processing_common/__init__.py +1 -0
- dkist_processing_common/_util/constants.py +1 -0
- dkist_processing_common/_util/graphql.py +1 -0
- dkist_processing_common/_util/scratch.py +9 -9
- dkist_processing_common/_util/tags.py +1 -0
- dkist_processing_common/codecs/array.py +20 -0
- dkist_processing_common/codecs/asdf.py +9 -3
- dkist_processing_common/codecs/basemodel.py +22 -0
- dkist_processing_common/codecs/bytes.py +1 -0
- dkist_processing_common/codecs/fits.py +37 -9
- dkist_processing_common/codecs/iobase.py +1 -0
- dkist_processing_common/codecs/json.py +1 -0
- dkist_processing_common/codecs/path.py +1 -0
- dkist_processing_common/codecs/quality.py +1 -1
- dkist_processing_common/codecs/str.py +1 -0
- dkist_processing_common/config.py +64 -25
- dkist_processing_common/manual.py +6 -8
- dkist_processing_common/models/constants.py +373 -37
- dkist_processing_common/models/dkist_location.py +27 -0
- dkist_processing_common/models/fits_access.py +48 -0
- dkist_processing_common/models/flower_pot.py +231 -9
- dkist_processing_common/models/fried_parameter.py +41 -0
- dkist_processing_common/models/graphql.py +66 -75
- dkist_processing_common/models/input_dataset.py +117 -0
- dkist_processing_common/models/message.py +1 -1
- dkist_processing_common/models/message_queue_binding.py +1 -1
- dkist_processing_common/models/metric_code.py +2 -0
- dkist_processing_common/models/parameters.py +65 -28
- dkist_processing_common/models/quality.py +50 -5
- dkist_processing_common/models/tags.py +23 -21
- dkist_processing_common/models/task_name.py +3 -2
- dkist_processing_common/models/telemetry.py +28 -0
- dkist_processing_common/models/wavelength.py +3 -1
- dkist_processing_common/parsers/average_bud.py +46 -0
- dkist_processing_common/parsers/cs_step.py +13 -12
- dkist_processing_common/parsers/dsps_repeat.py +6 -4
- dkist_processing_common/parsers/experiment_id_bud.py +12 -4
- dkist_processing_common/parsers/id_bud.py +42 -27
- dkist_processing_common/parsers/l0_fits_access.py +5 -3
- dkist_processing_common/parsers/l1_fits_access.py +51 -23
- dkist_processing_common/parsers/lookup_bud.py +125 -0
- dkist_processing_common/parsers/near_bud.py +21 -20
- dkist_processing_common/parsers/observing_program_id_bud.py +24 -0
- dkist_processing_common/parsers/proposal_id_bud.py +13 -5
- dkist_processing_common/parsers/quality.py +2 -0
- dkist_processing_common/parsers/retarder.py +32 -0
- dkist_processing_common/parsers/single_value_single_key_flower.py +6 -1
- dkist_processing_common/parsers/task.py +8 -6
- dkist_processing_common/parsers/time.py +178 -72
- dkist_processing_common/parsers/unique_bud.py +21 -22
- dkist_processing_common/parsers/wavelength.py +5 -3
- dkist_processing_common/tasks/__init__.py +3 -2
- dkist_processing_common/tasks/assemble_movie.py +4 -3
- dkist_processing_common/tasks/base.py +59 -60
- dkist_processing_common/tasks/l1_output_data.py +54 -53
- dkist_processing_common/tasks/mixin/globus.py +24 -27
- dkist_processing_common/tasks/mixin/interservice_bus.py +1 -0
- dkist_processing_common/tasks/mixin/metadata_store.py +108 -243
- dkist_processing_common/tasks/mixin/object_store.py +22 -0
- dkist_processing_common/tasks/mixin/quality/__init__.py +1 -0
- dkist_processing_common/tasks/mixin/quality/_base.py +8 -1
- dkist_processing_common/tasks/mixin/quality/_metrics.py +166 -14
- dkist_processing_common/tasks/output_data_base.py +4 -3
- dkist_processing_common/tasks/parse_l0_input_data.py +277 -15
- dkist_processing_common/tasks/quality_metrics.py +9 -9
- dkist_processing_common/tasks/teardown.py +7 -7
- dkist_processing_common/tasks/transfer_input_data.py +67 -69
- dkist_processing_common/tasks/trial_catalog.py +77 -17
- dkist_processing_common/tasks/trial_output_data.py +16 -17
- dkist_processing_common/tasks/write_l1.py +102 -72
- dkist_processing_common/tests/conftest.py +32 -173
- dkist_processing_common/tests/mock_metadata_store.py +271 -0
- dkist_processing_common/tests/test_assemble_movie.py +4 -4
- dkist_processing_common/tests/test_assemble_quality.py +32 -4
- dkist_processing_common/tests/test_base.py +5 -19
- dkist_processing_common/tests/test_codecs.py +103 -12
- dkist_processing_common/tests/test_constants.py +15 -0
- dkist_processing_common/tests/test_dkist_location.py +15 -0
- dkist_processing_common/tests/test_fits_access.py +56 -19
- dkist_processing_common/tests/test_flower_pot.py +147 -5
- dkist_processing_common/tests/test_fried_parameter.py +27 -0
- dkist_processing_common/tests/test_input_dataset.py +78 -361
- dkist_processing_common/tests/test_interservice_bus.py +1 -0
- dkist_processing_common/tests/test_interservice_bus_mixin.py +1 -1
- dkist_processing_common/tests/test_manual_processing.py +33 -0
- dkist_processing_common/tests/test_output_data_base.py +5 -7
- dkist_processing_common/tests/test_parameters.py +71 -22
- dkist_processing_common/tests/test_parse_l0_input_data.py +115 -32
- dkist_processing_common/tests/test_publish_catalog_messages.py +2 -24
- dkist_processing_common/tests/test_quality.py +1 -0
- dkist_processing_common/tests/test_quality_mixin.py +255 -23
- dkist_processing_common/tests/test_scratch.py +2 -1
- dkist_processing_common/tests/test_stems.py +511 -168
- dkist_processing_common/tests/test_submit_dataset_metadata.py +3 -7
- dkist_processing_common/tests/test_tags.py +1 -0
- dkist_processing_common/tests/test_task_name.py +1 -1
- dkist_processing_common/tests/test_task_parsing.py +17 -7
- dkist_processing_common/tests/test_teardown.py +28 -24
- dkist_processing_common/tests/test_transfer_input_data.py +270 -125
- dkist_processing_common/tests/test_transfer_l1_output_data.py +2 -3
- dkist_processing_common/tests/test_trial_catalog.py +83 -8
- dkist_processing_common/tests/test_trial_output_data.py +46 -73
- dkist_processing_common/tests/test_workflow_task_base.py +8 -10
- dkist_processing_common/tests/test_write_l1.py +298 -76
- dkist_processing_common-12.1.0rc1.dist-info/METADATA +265 -0
- dkist_processing_common-12.1.0rc1.dist-info/RECORD +134 -0
- {dkist_processing_common-10.5.4.dist-info → dkist_processing_common-12.1.0rc1.dist-info}/WHEEL +1 -1
- docs/conf.py +1 -0
- docs/index.rst +1 -1
- docs/landing_page.rst +13 -0
- dkist_processing_common/tasks/mixin/input_dataset.py +0 -166
- dkist_processing_common-10.5.4.dist-info/METADATA +0 -175
- dkist_processing_common-10.5.4.dist-info/RECORD +0 -112
- {dkist_processing_common-10.5.4.dist-info → dkist_processing_common-12.1.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from astropy.coordinates import EarthLocation
|
|
3
|
+
|
|
4
|
+
from dkist_processing_common.models.dkist_location import location_of_dkist
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.flaky(max_reruns=10)
|
|
8
|
+
def test_location_of_dkist():
|
|
9
|
+
"""
|
|
10
|
+
Given: function for retrieving the dkist location on earth
|
|
11
|
+
When: Call function
|
|
12
|
+
Then: result is the same as what is in the astropy online database
|
|
13
|
+
"""
|
|
14
|
+
itrs = location_of_dkist
|
|
15
|
+
assert itrs == EarthLocation.of_site("dkist")
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
1
3
|
import numpy as np
|
|
2
4
|
import pytest
|
|
3
5
|
from astropy.io import fits
|
|
4
6
|
|
|
5
7
|
from dkist_processing_common.models.fits_access import FitsAccessBase
|
|
8
|
+
from dkist_processing_common.models.fits_access import MetadataKey
|
|
6
9
|
from dkist_processing_common.parsers.l0_fits_access import L0FitsAccess
|
|
7
10
|
from dkist_processing_common.parsers.l1_fits_access import L1FitsAccess
|
|
8
11
|
|
|
@@ -22,19 +25,21 @@ def hdu_with_complete_common_header(complete_common_header):
|
|
|
22
25
|
def hdu_with_special_keys(hdu_with_complete_common_header, request):
|
|
23
26
|
"""
|
|
24
27
|
An HDU with data and a header that includes variations on the special keys that make headers
|
|
25
|
-
different from
|
|
28
|
+
different from dicts.
|
|
29
|
+
|
|
30
|
+
The base complete_common_header already has history and comment cards so this fixture adds extras.
|
|
26
31
|
"""
|
|
27
32
|
add_special = request.param
|
|
28
33
|
hdu = hdu_with_complete_common_header
|
|
29
34
|
if add_special == "history":
|
|
30
35
|
hdu.header.add_history("test history")
|
|
31
|
-
return hdu
|
|
36
|
+
return hdu, request.param
|
|
32
37
|
if add_special == "comment":
|
|
33
|
-
hdu.header.
|
|
34
|
-
return hdu
|
|
38
|
+
hdu.header.add_comment("test comment")
|
|
39
|
+
return hdu, request.param
|
|
35
40
|
if add_special == "continue":
|
|
36
41
|
hdu.header["LONG_VAL"] = " " * 100
|
|
37
|
-
return hdu
|
|
42
|
+
return hdu, request.param
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
@pytest.fixture()
|
|
@@ -91,14 +96,15 @@ def hdu_with_no_data(complete_common_header):
|
|
|
91
96
|
|
|
92
97
|
|
|
93
98
|
@pytest.fixture()
|
|
94
|
-
def hdu_with_incomplete_common_header(
|
|
99
|
+
def hdu_with_incomplete_common_header(complete_common_header):
|
|
95
100
|
"""
|
|
96
|
-
An HDU with data and a header missing
|
|
101
|
+
An HDU with data and a header missing two of the expected common by-frame keywords
|
|
97
102
|
"""
|
|
103
|
+
incomplete_header = complete_common_header
|
|
104
|
+
incomplete_header.pop(MetadataKey.elevation)
|
|
105
|
+
incomplete_header.pop(MetadataKey.azimuth)
|
|
98
106
|
data = np.arange(9).reshape(3, 3)
|
|
99
|
-
hdu = fits.PrimaryHDU(data)
|
|
100
|
-
hdu.header["TELEVATN"] = 6.28
|
|
101
|
-
hdu.header["TAZIMUTH"] = 3.14
|
|
107
|
+
hdu = fits.PrimaryHDU(data, header=incomplete_header)
|
|
102
108
|
return hdu
|
|
103
109
|
|
|
104
110
|
|
|
@@ -125,19 +131,45 @@ def fits_file_path_with_data_in_imagehdu(tmp_path, complete_common_header):
|
|
|
125
131
|
return file_path
|
|
126
132
|
|
|
127
133
|
|
|
134
|
+
class MetadataKeyWithNaxisKeys(StrEnum):
|
|
135
|
+
naxis = "NAXIS"
|
|
136
|
+
naxis1 = "NAXIS1"
|
|
137
|
+
naxis2 = "NAXIS2"
|
|
138
|
+
|
|
139
|
+
|
|
128
140
|
class FitsAccessWithNaxisKeys(FitsAccessBase):
|
|
129
141
|
def __init__(self, hdu, name):
|
|
130
142
|
super().__init__(hdu, name)
|
|
131
|
-
self.naxis = self.header[
|
|
132
|
-
self.naxis1 = self.header[
|
|
133
|
-
self.naxis2 = self.header[
|
|
143
|
+
self.naxis = self.header[MetadataKeyWithNaxisKeys.naxis]
|
|
144
|
+
self.naxis1 = self.header[MetadataKeyWithNaxisKeys.naxis1]
|
|
145
|
+
self.naxis2 = self.header[MetadataKeyWithNaxisKeys.naxis2]
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_metadata_keys_in_access_bases(hdu_with_no_data):
|
|
149
|
+
"""
|
|
150
|
+
Given: a set of metadata key names in the MetadataKey sting enumeration
|
|
151
|
+
When: the FITS access classes define a set of attributes/properties
|
|
152
|
+
Then: the sets are the same and the values of the attributes/properties are correct
|
|
153
|
+
"""
|
|
154
|
+
all_metadata_key_names = {mk.name for mk in MetadataKey}
|
|
155
|
+
hdu = hdu_with_no_data
|
|
156
|
+
fits_obj = L0FitsAccess(hdu=hdu)
|
|
157
|
+
fits_access_defined_attributes = {
|
|
158
|
+
k for k, v in fits_obj.__dict__.items() if k not in ["_hdu", "name", "auto_squeeze"]
|
|
159
|
+
}
|
|
160
|
+
l0_access_properties = {k for k, v in L0FitsAccess.__dict__.items() if isinstance(v, property)}
|
|
161
|
+
l1_access_properties = {k for k, v in L1FitsAccess.__dict__.items() if isinstance(v, property)}
|
|
162
|
+
fits_access_properties = l0_access_properties | l1_access_properties
|
|
163
|
+
assert fits_access_defined_attributes | fits_access_properties == all_metadata_key_names
|
|
164
|
+
for key in fits_access_defined_attributes:
|
|
165
|
+
assert getattr(fits_obj, key) == fits_obj.header[MetadataKey[key]]
|
|
134
166
|
|
|
135
167
|
|
|
136
168
|
def test_from_single_hdu(hdu_with_complete_common_header):
|
|
137
169
|
"""
|
|
138
170
|
Given: an HDU with expected, common by-frame keywords
|
|
139
171
|
When: loading the HDU with the L0FitsAccess class
|
|
140
|
-
Then:
|
|
172
|
+
Then: values for common keywords are exposed as properties on the fits_obj class
|
|
141
173
|
"""
|
|
142
174
|
fits_obj = L0FitsAccess(hdu_with_complete_common_header)
|
|
143
175
|
assert fits_obj.elevation == 6.28
|
|
@@ -152,7 +184,7 @@ def test_l1_only_fits_access(hdu_with_complete_l1_only_header):
|
|
|
152
184
|
"""
|
|
153
185
|
Given: an HDU with 214 L1-only headers
|
|
154
186
|
When: loading the HDU with the L1FitsAccess class
|
|
155
|
-
Then: no errors are raised and
|
|
187
|
+
Then: no errors are raised and values are exposed
|
|
156
188
|
"""
|
|
157
189
|
fits_obj = L1FitsAccess(hdu_with_complete_l1_only_header)
|
|
158
190
|
assert fits_obj.elevation == 6.28
|
|
@@ -220,7 +252,7 @@ def test_as_subclass(hdu_with_complete_common_header):
|
|
|
220
252
|
class InstFitsAccess(L0FitsAccess):
|
|
221
253
|
def __init__(self, hdu, name):
|
|
222
254
|
super().__init__(hdu, name)
|
|
223
|
-
self.foo: str = self.header["
|
|
255
|
+
self.foo: str = self.header["VISP_012"]
|
|
224
256
|
|
|
225
257
|
fits_obj = InstFitsAccess(hdu_with_complete_common_header, name="foo")
|
|
226
258
|
assert fits_obj.foo == "bar"
|
|
@@ -282,11 +314,16 @@ def test_header_dict(hdu_with_special_keys):
|
|
|
282
314
|
"""
|
|
283
315
|
Given: A FitsAccess object with data and a header including special header keys
|
|
284
316
|
When: Accessing the header_dict method
|
|
285
|
-
Then: The object's header is successfully exported as a dict of the same length as the header
|
|
317
|
+
Then: The object's header is successfully exported as a dict of the same length as the header when accounting for multiple HISTORY or COMMENT cards
|
|
286
318
|
"""
|
|
287
|
-
|
|
319
|
+
hdu, added_header_key = hdu_with_special_keys
|
|
320
|
+
fits_obj = FitsAccessBase(hdu)
|
|
288
321
|
assert isinstance(fits_obj.header_dict, dict)
|
|
289
|
-
|
|
322
|
+
if added_header_key == "continue":
|
|
323
|
+
assert len(fits_obj.header_dict) == len(fits_obj.header)
|
|
324
|
+
if added_header_key in ["history", "comment"]:
|
|
325
|
+
# HISTORY and COMMENT keys get "squeezed"
|
|
326
|
+
assert len(fits_obj.header_dict) == len(fits_obj.header) - 1
|
|
290
327
|
|
|
291
328
|
|
|
292
329
|
@pytest.mark.parametrize(
|
|
@@ -4,11 +4,13 @@ from typing import Hashable
|
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
6
|
from dkist_processing_common.models.flower_pot import FlowerPot
|
|
7
|
+
from dkist_processing_common.models.flower_pot import ListStem
|
|
8
|
+
from dkist_processing_common.models.flower_pot import SetStem
|
|
7
9
|
from dkist_processing_common.models.flower_pot import SpilledDirt
|
|
8
10
|
from dkist_processing_common.models.flower_pot import Stem
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
@pytest.fixture
|
|
13
|
+
@pytest.fixture
|
|
12
14
|
def simple_flower():
|
|
13
15
|
class Flower(Stem):
|
|
14
16
|
def setter(self, value: Any) -> Any:
|
|
@@ -22,7 +24,7 @@ def simple_flower():
|
|
|
22
24
|
return Flower(stem_name="simple_flower")
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
@pytest.fixture
|
|
27
|
+
@pytest.fixture
|
|
26
28
|
def simple_flower_pot(simple_flower):
|
|
27
29
|
flower_pot = FlowerPot()
|
|
28
30
|
flower_pot.stems += [simple_flower]
|
|
@@ -30,16 +32,66 @@ def simple_flower_pot(simple_flower):
|
|
|
30
32
|
return flower_pot
|
|
31
33
|
|
|
32
34
|
|
|
33
|
-
@pytest.fixture
|
|
35
|
+
@pytest.fixture
|
|
34
36
|
def simple_key_values():
|
|
35
37
|
return {f"thing{i}": i for i in range(5)}
|
|
36
38
|
|
|
37
39
|
|
|
40
|
+
@pytest.fixture
|
|
41
|
+
def stem_bud():
|
|
42
|
+
class Bud(Stem):
|
|
43
|
+
def setter(self, value: int) -> int:
|
|
44
|
+
return value % 3
|
|
45
|
+
|
|
46
|
+
def getter(self, key: str) -> int:
|
|
47
|
+
return len(set(self.key_to_petal_dict.values()))
|
|
48
|
+
|
|
49
|
+
return Bud(stem_name="StemBud")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.fixture
|
|
53
|
+
def setstem_bud():
|
|
54
|
+
# Computes the same result as `stem_bud`
|
|
55
|
+
class SetBud(SetStem):
|
|
56
|
+
def setter(self, value: int) -> int:
|
|
57
|
+
return value % 3
|
|
58
|
+
|
|
59
|
+
def getter(self) -> int:
|
|
60
|
+
return len(self.value_set)
|
|
61
|
+
|
|
62
|
+
return SetBud(stem_name="SetStemBud")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@pytest.fixture
|
|
66
|
+
def liststem_bud():
|
|
67
|
+
# Highlights the difference between using a `set` and a `list` in these more efficient buds
|
|
68
|
+
class ListBud(ListStem):
|
|
69
|
+
def setter(self, value: int) -> int:
|
|
70
|
+
return value % 3
|
|
71
|
+
|
|
72
|
+
def getter(self) -> int:
|
|
73
|
+
return len(self.value_list)
|
|
74
|
+
|
|
75
|
+
return ListBud(stem_name="ListStemBud")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.fixture
|
|
79
|
+
def simple_bud_pot(stem_bud, setstem_bud, liststem_bud):
|
|
80
|
+
bud_pot = FlowerPot()
|
|
81
|
+
bud_pot.stems += [stem_bud, liststem_bud, setstem_bud]
|
|
82
|
+
return bud_pot
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@pytest.fixture
|
|
86
|
+
def bud_key_values():
|
|
87
|
+
return {f"DOESN'T_MATTER_THAT'S_THE_POINT_{i}": i for i in [0, 1, 3, 4]}
|
|
88
|
+
|
|
89
|
+
|
|
38
90
|
def test_simple_flower_pot(simple_flower_pot, simple_key_values):
|
|
39
91
|
"""
|
|
40
92
|
Given: A FlowerPot with a simple Flower
|
|
41
|
-
When: Updating
|
|
42
|
-
Then: The
|
|
93
|
+
When: Updating flower with key: value pairs
|
|
94
|
+
Then: The flower are correctly updated
|
|
43
95
|
"""
|
|
44
96
|
assert len(simple_flower_pot) == 1
|
|
45
97
|
|
|
@@ -51,6 +103,8 @@ def test_simple_flower_pot(simple_flower_pot, simple_key_values):
|
|
|
51
103
|
|
|
52
104
|
petals = sorted(list(flower.petals), key=lambda x: x.value)
|
|
53
105
|
assert len(petals) == 2
|
|
106
|
+
assert flower.bud.value == petals[0].value
|
|
107
|
+
assert flower.bud.keys == petals[0].keys
|
|
54
108
|
assert petals[0].value == 0
|
|
55
109
|
assert petals[0].keys == ["thing0", "thing2", "thing4"]
|
|
56
110
|
assert petals[1].value == 1
|
|
@@ -67,8 +121,12 @@ def test_cached_petal(simple_flower):
|
|
|
67
121
|
value1 = 4
|
|
68
122
|
simple_flower.update(key1, value1)
|
|
69
123
|
assert len(simple_flower.petals) == 1
|
|
124
|
+
|
|
125
|
+
# Assert twice to hit the cache
|
|
70
126
|
assert simple_flower.petals[0].value == value1 % 2 # % 2 because of simple_flower's `setter`
|
|
71
127
|
assert simple_flower.petals[0].keys == [key1]
|
|
128
|
+
assert simple_flower.petals[0].value == value1 % 2
|
|
129
|
+
assert simple_flower.petals[0].keys == [key1]
|
|
72
130
|
|
|
73
131
|
key2 = "thing2"
|
|
74
132
|
value2 = 3
|
|
@@ -79,6 +137,10 @@ def test_cached_petal(simple_flower):
|
|
|
79
137
|
assert sorted_petals[0].keys == [key1]
|
|
80
138
|
assert sorted_petals[1].value == value2 % 2
|
|
81
139
|
assert sorted_petals[1].keys == [key2]
|
|
140
|
+
assert sorted_petals[0].value == value1 % 2
|
|
141
|
+
assert sorted_petals[0].keys == [key1]
|
|
142
|
+
assert sorted_petals[1].value == value2 % 2
|
|
143
|
+
assert sorted_petals[1].keys == [key2]
|
|
82
144
|
|
|
83
145
|
|
|
84
146
|
def test_spilled_dirt_flower(simple_flower):
|
|
@@ -103,3 +165,83 @@ def test_unhashable_dirt(simple_flower_pot):
|
|
|
103
165
|
value = "never gonna get here"
|
|
104
166
|
with pytest.raises(TypeError):
|
|
105
167
|
simple_flower_pot.add_dirt(unhashable_key, value)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_buds(simple_bud_pot, bud_key_values):
|
|
171
|
+
"""
|
|
172
|
+
Given: A Flower pot with two Buds that compute the same thing; one a `Stem` and one a `SetStem`, and a `ListStem` bud
|
|
173
|
+
When: Updating the pot with key: value pairs
|
|
174
|
+
Then: The computed buds are correct and the `Stem` and `SetStem` buds match
|
|
175
|
+
"""
|
|
176
|
+
assert len(simple_bud_pot) == 3
|
|
177
|
+
|
|
178
|
+
assert simple_bud_pot[0].stem_name == "StemBud"
|
|
179
|
+
assert simple_bud_pot[1].stem_name == "ListStemBud"
|
|
180
|
+
assert simple_bud_pot[2].stem_name == "SetStemBud"
|
|
181
|
+
|
|
182
|
+
for k, m in bud_key_values.items():
|
|
183
|
+
simple_bud_pot.add_dirt(k, m)
|
|
184
|
+
|
|
185
|
+
assert simple_bud_pot[0].bud.value == 2
|
|
186
|
+
assert simple_bud_pot[1].bud.value == 4
|
|
187
|
+
assert simple_bud_pot[2].bud.value == simple_bud_pot[0].bud.value
|
|
188
|
+
|
|
189
|
+
assert len(simple_bud_pot[0].petals) == 1
|
|
190
|
+
assert simple_bud_pot[0].petals[0].value == 2
|
|
191
|
+
assert simple_bud_pot[0].petals[0].keys == [
|
|
192
|
+
f"DOESN'T_MATTER_THAT'S_THE_POINT_{i}" for i in [0, 1, 3, 4]
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
with pytest.raises(
|
|
196
|
+
AttributeError,
|
|
197
|
+
match="ListBud subclasses ListStem and therefore does not define the `petals` property",
|
|
198
|
+
):
|
|
199
|
+
_ = simple_bud_pot[1].petals
|
|
200
|
+
|
|
201
|
+
with pytest.raises(
|
|
202
|
+
AttributeError,
|
|
203
|
+
match="SetBud subclasses SetStem and therefore does not define the `petals` property",
|
|
204
|
+
):
|
|
205
|
+
_ = simple_bud_pot[2].petals
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_liststem_cached_bud(liststem_bud):
|
|
209
|
+
"""
|
|
210
|
+
Given: A `ListStem` instance and some different input values
|
|
211
|
+
When: Computing the `bud` property after each value is ingested
|
|
212
|
+
Then: The `bud` value correctly updates based on the state of the `ListStem` object
|
|
213
|
+
"""
|
|
214
|
+
key = "Who cares"
|
|
215
|
+
value1 = 3
|
|
216
|
+
liststem_bud.update(key, value1)
|
|
217
|
+
|
|
218
|
+
# Assert twice so we hit the cache
|
|
219
|
+
assert liststem_bud.bud.value == 1
|
|
220
|
+
assert liststem_bud.bud.value == 1
|
|
221
|
+
|
|
222
|
+
value2 = 1
|
|
223
|
+
liststem_bud.update(key, value2)
|
|
224
|
+
|
|
225
|
+
assert liststem_bud.bud.value == 2
|
|
226
|
+
assert liststem_bud.bud.value == 2
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def test_setstem_cached_bud(setstem_bud):
|
|
230
|
+
"""
|
|
231
|
+
Given: A `SetStem` instance and some different input values
|
|
232
|
+
When: Computing the `bud` property after each value is ingested
|
|
233
|
+
Then: The `bud` value correctly updates based on the state of the `SetStem` object
|
|
234
|
+
"""
|
|
235
|
+
key = "Who cares"
|
|
236
|
+
value1 = 3
|
|
237
|
+
setstem_bud.update(key, value1)
|
|
238
|
+
|
|
239
|
+
# Assert twice so we hit the cache
|
|
240
|
+
assert setstem_bud.bud.value == 1
|
|
241
|
+
assert setstem_bud.bud.value == 1
|
|
242
|
+
|
|
243
|
+
value2 = 1
|
|
244
|
+
setstem_bud.update(key, value2)
|
|
245
|
+
|
|
246
|
+
assert setstem_bud.bud.value == 2
|
|
247
|
+
assert setstem_bud.bud.value == 2
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from dkist_processing_common.models.fried_parameter import r0_valid
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize(
|
|
7
|
+
"r0, ao_lock, oob_shift, should_r0_exist",
|
|
8
|
+
[
|
|
9
|
+
pytest.param(0.2, True, 17, True, id="AO_LOCK_True_good_R0_good_oob"),
|
|
10
|
+
pytest.param(1, True, 17, False, id="AO_LOCK_True_bad_R0_good_oob"),
|
|
11
|
+
pytest.param(0.2, False, 17, False, id="AO_LOCK_False_good_R0_good_oob"),
|
|
12
|
+
pytest.param(1, False, 17, False, id="AO_LOCK_False_bad_R0_good_oob"),
|
|
13
|
+
pytest.param(0.2, True, 150, False, id="AO_LOCK_True_good_R0_bad_oob"),
|
|
14
|
+
pytest.param(1, True, 150, False, id="AO_LOCK_True_bad_R0_bad_oob"),
|
|
15
|
+
pytest.param(0.2, False, 150, False, id="AO_LOCK_False_good_R0_bad_oob"),
|
|
16
|
+
pytest.param(1, False, 150, False, id="AO_LOCK_False_bad_R0_bad_oob"),
|
|
17
|
+
pytest.param(0.2, None, 17, False, id="AO_LOCK_missing"),
|
|
18
|
+
pytest.param(0.2, True, None, True, id="OOBSHIFT_missing"),
|
|
19
|
+
],
|
|
20
|
+
)
|
|
21
|
+
def test_check_r0_valid(r0, ao_lock, oob_shift, should_r0_exist):
|
|
22
|
+
"""
|
|
23
|
+
:Given: values for r0, the ao_lock status, and the ao out of bound shift value
|
|
24
|
+
:When: checking for a valid state to use r0
|
|
25
|
+
:Then: valid conditions are marked True, invalid conditions marked False
|
|
26
|
+
"""
|
|
27
|
+
assert r0_valid(r0, ao_lock, oob_shift) == should_r0_exist
|