forked from iterorganization/IMAS-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_identifiers.py
More file actions
304 lines (258 loc) · 11.1 KB
/
Copy pathtest_identifiers.py
File metadata and controls
304 lines (258 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
import importlib.metadata
from packaging.version import Version
import pytest
from imas.dd_zip import dd_identifiers
from imas.ids_factory import IDSFactory
from imas.ids_identifiers import IDSIdentifier, identifiers
requires_dd4_1 = pytest.mark.skipif(
Version(importlib.metadata.version("imas_data_dictionaries")) < Version("4.1.0"),
reason="Test requires DD 4.1.0 for additional identifier metadata",
)
def test_list_identifiers():
assert identifiers.identifiers == dd_identifiers()
# Check a known identifier, which we'll also use in more tests
assert "core_source_identifier" in identifiers.identifiers
def test_identifier_enum():
csid = identifiers.core_source_identifier
# Test item access
assert csid is identifiers["core_source_identifier"]
# Class and inheritance tests
assert csid.__name__ == "core_source_identifier"
assert csid.__qualname__ == "imas.ids_identifiers.core_source_identifier"
assert issubclass(csid, IDSIdentifier)
assert isinstance(csid.total, csid)
assert isinstance(csid.total, IDSIdentifier)
# Check access methods
assert csid.total is csid(1)
assert csid.total is csid["total"]
# Check attributes
assert csid.total.name == "total"
assert csid.total.index == csid.total.value == 1
assert isinstance(csid.total.description, str)
assert csid.total.description != ""
def test_identifier_struct_assignment(caplog):
csid = identifiers.core_source_identifier
cs = IDSFactory("3.39.0").core_sources()
cs.source.resize(3)
assert cs.source[0].identifier.metadata.identifier_enum is csid
# Test assignment options: identifier instance, index and name
cs.source[0].identifier = csid.total
cs.source[1].identifier = "total"
cs.source[2].identifier = 1
for source in cs.source:
assert source.identifier.name == "total"
assert source.identifier.index == 1
assert source.identifier.description == csid.total.description
# Test equality of identifier structure and enum:
assert source.identifier == csid.total
assert source.identifier != csid(0)
# Test fuzzy equality
caplog.clear()
# Empty description is okay
source.identifier.description = ""
assert source.identifier == csid.total
assert not caplog.records
# Incorrect description logs a warning
source.identifier.description = "XYZ"
assert source.identifier == csid.total
assert len(caplog.records) == 1
assert caplog.records[0].levelname == "WARNING"
source.identifier.description = ""
# Empty name is okay
source.identifier.name = ""
assert source.identifier == csid.total
# But non-matching name is not okay
source.identifier.name = "XYZ"
assert source.identifier != csid.total
def test_identifiers_with_aliases():
# Custom identifier XML, based on materials identifier, with some more features
custom_identifier_xml = """\
<?xml version="1.0"?>
<constants name="materials" identifier="yes" create_mapping_function="yes">
<header>
Materials used in the device mechanical structures
</header>
<int name="235U" alias="U_235" description="Uranium 235 isotope">20</int>
<int name="238U" alias="U_238" description="Uranium 238 isotope">21</int>
<int name="Diamond" description="Diamond">22</int>
<int name="CxHy" alias="alias1,alias2,3alias" description="Organic molecule">23</int>
</constants>
"""
identifier = IDSIdentifier._from_xml("custom_identifier", custom_identifier_xml)
assert len(identifier) == 4
# no aliases
assert identifier.Diamond.aliases == []
# 1 alias
assert identifier["235U"] is identifier.U_235
assert identifier["235U"].aliases == ["U_235"]
# 3 aliases
assert (
identifier.CxHy
is identifier.alias1
is identifier.alias2
is identifier["3alias"]
)
assert identifier.CxHy.aliases == ["alias1", "alias2", "3alias"]
@requires_dd4_1
def test_identifier_struct_assignment_with_aliases():
"""Test identifier struct assignment with aliases using materials_identifier."""
mid = identifiers.materials_identifier
# Create an actual IDS structure
wallids = IDSFactory().wall()
wallids.description_ggd.resize(1)
wallids.description_ggd[0].material.resize(1)
wallids.description_ggd[0].material[0].grid_subset.resize(1)
mat = wallids.description_ggd[0].material[0].grid_subset[0].identifiers
mat.names.extend([""] * 1)
mat.indices.resize(1)
mat.descriptions.extend([""] * 1)
mat.names[0] = mid.U_235.name
mat.indices[0] = 20
mat.descriptions[0] = "Uranium 235 isotope"
# Basic attribute checks
assert mat.names[0] == mid["235U"].name
assert mat.indices[0] == mid.U_235.index
# Modify material properties and test equality
mat.names[0] = "some_name"
assert mat.names[0] != mid.U_235.name
def test_identifier_aos_assignment():
cfid = identifiers.pf_active_coil_function_identifier
pfa = IDSFactory("3.39.0").pf_active()
pfa.coil.resize(1)
pfa.coil[0].function.resize(3)
assert pfa.coil[0].function.metadata.identifier_enum is cfid
# Test assignment options: identifier instance, index and name
pfa.coil[0].function[0] = cfid.flux
pfa.coil[0].function[1] = "flux"
pfa.coil[0].function[2] = 0
for function in pfa.coil[0].function:
assert function.name == "flux"
assert function.index == 0
assert function.description == cfid.flux.description
# Test equality of identifier structure and enum:
assert function == cfid.flux
assert function != cfid.b_field_shaping
assert pfa.coil[0].function[0] == cfid.flux
def test_invalid_identifier_assignment():
cfid = identifiers.pf_active_coil_function_identifier
cs = IDSFactory("3.39.0").core_sources()
cs.source.resize(1)
with pytest.raises(TypeError):
# Incorrect identifier type
cs.source[0].identifier = cfid.flux
with pytest.raises(ValueError):
cs.source[0].identifier = "identifier names never contain spaces"
with pytest.raises(ValueError):
# negative identifiers are reserved for user-defined identifiers
cs.source[0].identifier = -1
@requires_dd4_1
def test_identifier_aliases():
"""Test identifier enum aliases functionality."""
mid = identifiers.materials_identifier
# Test that alias points to the same object as the canonical name
assert mid.U_235 is mid["235U"]
assert mid.U_238 is mid["238U"]
assert mid.In_115 is mid["115In"]
assert mid.He_4 is mid["4He"]
# Test that both name and alias have the same properties
assert mid.U_235.name == "235U"
assert mid.U_235.index == mid["235U"].index
assert mid.U_235.description == mid["235U"].description
assert "U_235" in mid.U_235.aliases
assert isinstance(mid.U_235.aliases, list)
# Test accessing by any alias via bracket notation
for alias in mid.U_235.aliases:
assert mid[alias] is mid.U_235
@requires_dd4_1
def test_identifier_alias_equality():
"""Test that identifiers with aliases are equal when comparing names and aliases."""
mid = identifiers.materials_identifier
target = mid.U_235
# Test equality with canonical name
wallids = IDSFactory().wall()
wallids.description_ggd.resize(1)
wallids.description_ggd[0].material.resize(1)
wallids.description_ggd[0].material[0].grid_subset.resize(1)
mat = wallids.description_ggd[0].material[0].grid_subset[0].identifiers
mat.names.extend([""] * 1)
mat.names[0] = "235U"
assert mat.names[0] == target.name
# Test equality with alias name
wallids2 = IDSFactory().wall()
wallids2.description_ggd.resize(1)
wallids2.description_ggd[0].material.resize(1)
wallids2.description_ggd[0].material[0].grid_subset.resize(1)
mat2 = wallids2.description_ggd[0].material[0].grid_subset[0].identifiers
mat2.names.extend([""] * 1)
mat2.names[0] = mid["U_235"].name # Use alias as name
assert mat2.names[0] == target.name
# Test inequality when material has alias not matching canonical name
wallids3 = IDSFactory().wall()
wallids3.description_ggd.resize(1)
wallids3.description_ggd[0].material.resize(1)
wallids3.description_ggd[0].material[0].grid_subset.resize(1)
mat3 = wallids3.description_ggd[0].material[0].grid_subset[0].identifiers
mat3.names.extend([""] * 1)
mat3.names[0] = "test_name"
assert mat3.names[0] != target.name
# Test equality when index doesn't match
wallids4 = IDSFactory().wall()
wallids4.description_ggd.resize(1)
wallids4.description_ggd[0].material.resize(1)
wallids4.description_ggd[0].material[0].grid_subset.resize(1)
mat4 = wallids4.description_ggd[0].material[0].grid_subset[0].identifiers
mat4.names.extend([""] * 1)
mat4.indices.resize(1)
mat4.names[0] = "235U"
mat4.indices[0] = 999
assert mat4.indices[0] != target.index
assert mat4.names[0] == target.name
# Test equality for multiple names,indices and descriptions
wallids5 = IDSFactory().wall()
wallids5.description_ggd.resize(1)
wallids5.description_ggd[0].material.resize(1)
wallids5.description_ggd[0].material[0].grid_subset.resize(1)
mat5 = wallids5.description_ggd[0].material[0].grid_subset[0].identifiers
mat5.names.extend([""] * 3)
mat5.indices.resize(3)
mat5.descriptions.extend([""] * 3)
mat5.names[0] = "235U"
mat5.names[1] = "238U"
mat5.names[2] = mid.U_235.name # Use alias as name
mat5.indices[0] = 20
mat5.indices[1] = 21
mat5.indices[2] = 20
mat5.descriptions[0] = "Uranium 235 isotope"
mat5.descriptions[1] = "Uranium 238 isotope"
mat5.descriptions[2] = "Uranium 235 isotope"
assert mat5.names[0] == mid["235U"].name
assert mat5.names[1] == mid["238U"].name
assert mat5.names[2] == mid["U_235"].name
assert mat5.indices[0] == mid["235U"].index
assert mat5.indices[1] == mid["238U"].index
assert mat5.indices[2] == mid["U_235"].index
assert mat5.descriptions[0] == mid["235U"].description
assert mat5.descriptions[1] == mid["238U"].description
assert mat5.descriptions[2] == mid["U_235"].description
@requires_dd4_1
def test_identifier_alias_equality_non_ggd():
"""Test identifier aliases functionality on non-ggd material"""
mid = identifiers.materials_identifier
summary_ids = IDSFactory().summary()
summary_ids.wall.material = mid.U_235 # Use alias as enum
assert summary_ids.wall.material == mid["235U"]
assert summary_ids.wall.material == mid["U_235"]
summary_ids.wall.material.name = "U_235" # Use alias as name
assert summary_ids.wall.material == mid["235U"]
assert summary_ids.wall.material == mid["U_235"]
summary_ids.wall.material.name = "235U" # Use canonical name
assert summary_ids.wall.material == mid["235U"]
assert summary_ids.wall.material == mid["U_235"]
@requires_dd4_1
def test_identifier_units():
ppcid = identifiers.poloidal_plane_coordinates_identifier
assert ppcid.rectangular.units == "m,m"
assert ppcid.inverse.units == "m,rad"
# materials identifier doesn't have units (and I don't expect they'll ever get any)
mid = identifiers.materials_identifier
assert mid.W.units is None