imas-python 0.1.dev1618__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.

Potentially problematic release.


This version of imas-python might be problematic. Click here for more details.

Files changed (108) hide show
  1. imas/__init__.py +34 -0
  2. imas/__main__.py +17 -0
  3. imas/_util.py +260 -0
  4. imas/_version.py +16 -0
  5. imas/assets/IDSDef2MDSpreTree.xsl +161 -0
  6. imas/assets/IDS_fake_toplevel.xml +318 -0
  7. imas/assets/IDS_minimal.xml +37 -0
  8. imas/assets/IDS_minimal_2.xml +37 -0
  9. imas/assets/IDS_minimal_struct_array.xml +43 -0
  10. imas/assets/IDS_minimal_types.xml +169 -0
  11. imas/assets/ITER_134173_106_core_profiles.ids +2438 -0
  12. imas/assets/ITER_134173_106_equilibrium.ids +3172 -0
  13. imas/assets/README.md +5 -0
  14. imas/assets/core_profiles.ids +2438 -0
  15. imas/assets/equilibrium.ids +3172 -0
  16. imas/backends/__init__.py +12 -0
  17. imas/backends/db_entry_impl.py +122 -0
  18. imas/backends/imas_core/__init__.py +4 -0
  19. imas/backends/imas_core/al_context.py +391 -0
  20. imas/backends/imas_core/db_entry_al.py +405 -0
  21. imas/backends/imas_core/db_entry_helpers.py +200 -0
  22. imas/backends/imas_core/imas_interface.py +216 -0
  23. imas/backends/imas_core/mdsplus_model.py +367 -0
  24. imas/backends/imas_core/uda_support.py +56 -0
  25. imas/backends/netcdf/__init__.py +4 -0
  26. imas/backends/netcdf/db_entry_nc.py +176 -0
  27. imas/backends/netcdf/ids2nc.py +306 -0
  28. imas/backends/netcdf/nc2ids.py +302 -0
  29. imas/backends/netcdf/nc_metadata.py +357 -0
  30. imas/backends/netcdf/nc_validate.py +53 -0
  31. imas/command/cli.py +239 -0
  32. imas/command/db_analysis.py +290 -0
  33. imas/command/helpers.py +45 -0
  34. imas/command/timer.py +77 -0
  35. imas/db_entry.py +802 -0
  36. imas/dd_helpers.py +300 -0
  37. imas/dd_zip.py +297 -0
  38. imas/exception.py +107 -0
  39. imas/ids_base.py +149 -0
  40. imas/ids_convert.py +920 -0
  41. imas/ids_coordinates.py +400 -0
  42. imas/ids_data_type.py +115 -0
  43. imas/ids_defs.py +171 -0
  44. imas/ids_factory.py +108 -0
  45. imas/ids_identifiers.py +125 -0
  46. imas/ids_metadata.py +307 -0
  47. imas/ids_path.py +254 -0
  48. imas/ids_primitive.py +510 -0
  49. imas/ids_struct_array.py +233 -0
  50. imas/ids_structure.py +331 -0
  51. imas/ids_toplevel.py +381 -0
  52. imas/setup_logging.py +64 -0
  53. imas/test/test_all_dd_versions.py +28 -0
  54. imas/test/test_cli.py +44 -0
  55. imas/test/test_dbentry.py +104 -0
  56. imas/test/test_dd_helpers.py +134 -0
  57. imas/test/test_dd_zip.py +29 -0
  58. imas/test/test_deepcopy.py +25 -0
  59. imas/test/test_exception.py +12 -0
  60. imas/test/test_get_sample.py +388 -0
  61. imas/test/test_hash.py +188 -0
  62. imas/test/test_helpers.py +354 -0
  63. imas/test/test_identifiers.py +105 -0
  64. imas/test/test_ids2nc.py +166 -0
  65. imas/test/test_ids_ascii_data.py +39 -0
  66. imas/test/test_ids_convert.py +415 -0
  67. imas/test/test_ids_coordinates.py +165 -0
  68. imas/test/test_ids_data_type.py +40 -0
  69. imas/test/test_ids_factory.py +35 -0
  70. imas/test/test_ids_metadata.py +66 -0
  71. imas/test/test_ids_mixin.py +20 -0
  72. imas/test/test_ids_path.py +192 -0
  73. imas/test/test_ids_primitive.py +109 -0
  74. imas/test/test_ids_struct_array.py +89 -0
  75. imas/test/test_ids_structure.py +70 -0
  76. imas/test/test_ids_toplevel.py +55 -0
  77. imas/test/test_ids_validate.py +343 -0
  78. imas/test/test_latest_dd_autofill.py +74 -0
  79. imas/test/test_latest_dd_manual.py +38 -0
  80. imas/test/test_latest_dd_resample.py +102 -0
  81. imas/test/test_lazy_loading.py +201 -0
  82. imas/test/test_list_occurrences.py +82 -0
  83. imas/test/test_minimal.py +37 -0
  84. imas/test/test_minimal_conversion.py +44 -0
  85. imas/test/test_minimal_io.py +21 -0
  86. imas/test/test_minimal_struct_array_io.py +60 -0
  87. imas/test/test_minimal_types.py +436 -0
  88. imas/test/test_minimal_types_io.py +70 -0
  89. imas/test/test_minimal_types_io_automatic.py +66 -0
  90. imas/test/test_nbc_change.py +408 -0
  91. imas/test/test_nc_autofill.py +13 -0
  92. imas/test/test_nc_entry.py +28 -0
  93. imas/test/test_nc_metadata.py +153 -0
  94. imas/test/test_nc_validation.py +197 -0
  95. imas/test/test_snippets.py +25 -0
  96. imas/test/test_static_ids.py +39 -0
  97. imas/test/test_str_1d.py +99 -0
  98. imas/test/test_time_slicing.py +182 -0
  99. imas/test/test_uda_support.py +12 -0
  100. imas/test/test_util.py +209 -0
  101. imas/training.py +45 -0
  102. imas/util.py +526 -0
  103. imas_python-0.1.dev1618.dist-info/LICENSE.txt +165 -0
  104. imas_python-0.1.dev1618.dist-info/METADATA +288 -0
  105. imas_python-0.1.dev1618.dist-info/RECORD +108 -0
  106. imas_python-0.1.dev1618.dist-info/WHEEL +5 -0
  107. imas_python-0.1.dev1618.dist-info/entry_points.txt +3 -0
  108. imas_python-0.1.dev1618.dist-info/top_level.txt +1 -0
@@ -0,0 +1,436 @@
1
+ # A minimal testcase loading an IDS file and checking that the structure built is ok
2
+ from numbers import Complex, Integral, Number, Real
3
+
4
+ import numpy as np
5
+ import pytest
6
+
7
+ from imas.ids_data_type import IDSDataType
8
+ from imas.ids_factory import IDSFactory
9
+
10
+
11
+ @pytest.fixture
12
+ def minimal(ids_minimal_types):
13
+ return IDSFactory(xml_path=ids_minimal_types).new("minimal")
14
+
15
+
16
+ # The test_assign_* tests are testing IDSPrimitive.cast_value
17
+ sample_values = {
18
+ "str": ["0D string", ["list", "of", "strings"]],
19
+ "int": [1, *(np.ones((2,) * i, dtype=np.int32) for i in range(1, 4))],
20
+ "flt": [1.1, *(np.ones((2,) * i, dtype=np.float64) for i in range(1, 7))],
21
+ "cpx": [
22
+ 1.1 + 1.1j,
23
+ *(np.ones((2,) * i, dtype=np.complex128) * (1 + 1j) for i in range(1, 7)),
24
+ ],
25
+ }
26
+
27
+
28
+ def test_assign_str_0d(minimal, caplog):
29
+ caplog.set_level("INFO", "imas")
30
+
31
+ # Test auto-encoding
32
+ minimal.str_0d = b"123"
33
+ assert minimal.str_0d.value == "123"
34
+ assert len(caplog.records) == 1 # Should trigger a warning about auto-conversion
35
+
36
+ for name, values in sample_values.items():
37
+ for ndim, value in enumerate(values):
38
+ caplog.clear()
39
+ minimal.str_0d = value
40
+ # All values except sample_values["str"][0] should log a warning
41
+ assert len(caplog.records) == 0 if name == "str" and ndim == 0 else 1
42
+
43
+
44
+ def test_assign_str_1d(minimal, caplog):
45
+ caplog.set_level("INFO", "imas")
46
+
47
+ # Test auto-encoding
48
+ minimal.str_1d = [b"123", "456"]
49
+ assert minimal.str_1d.value == ["123", "456"]
50
+ assert len(caplog.records) > 0 # Should trigger a warning about auto-conversion
51
+
52
+ for name, values in sample_values.items():
53
+ for ndim, value in enumerate(values):
54
+ caplog.clear()
55
+ minimal.str_1d = value
56
+ # All values except sample_values["str"][1] should log a warning
57
+ if name == "str" and ndim == 1:
58
+ assert len(caplog.records) == 0
59
+ else:
60
+ assert len(caplog.records) > 0
61
+
62
+
63
+ # Prevent the expected numpy ComplexWarnings from cluttering pytest output
64
+ @pytest.mark.filterwarnings("ignore::numpy.ComplexWarning")
65
+ @pytest.mark.parametrize("typ, max_dim", [("flt", 6), ("cpx", 6), ("int", 3)])
66
+ def test_assign_numeric_types(minimal, caplog, typ, max_dim):
67
+ caplog.set_level("INFO", "imas")
68
+ for dim in range(max_dim + 1):
69
+ name = f"{typ}_{dim}d"
70
+
71
+ for other_typ, values in sample_values.items():
72
+ can_assign = (
73
+ other_typ == typ
74
+ or (other_typ != "str" and typ == "cpx") # Store float/int in complex
75
+ or (other_typ == "flt" and typ == "int") # Store float in int
76
+ or (other_typ == "int" and typ == "flt") # Store int in float
77
+ )
78
+ for other_ndim, value in enumerate(values):
79
+ # We attempt to store other_typ (uppercase) with dimension other_ndim in
80
+ # a variable of type typ (lowercase) and dimension dim
81
+ if dim == other_ndim and can_assign:
82
+ caplog.clear()
83
+ minimal[name].value = value
84
+ if typ == other_typ or (dim == 0 and other_typ == "int"):
85
+ assert len(caplog.records) == 0
86
+ else:
87
+ len(caplog.records) == 1
88
+ elif dim == other_ndim >= 1 and other_typ == "cpx":
89
+ # np allows casting of complex to float or int, but warns:
90
+ with pytest.warns(np.ComplexWarning):
91
+ caplog.clear()
92
+ minimal[name].value = value
93
+ assert len(caplog.records) == 1
94
+ else:
95
+ with pytest.raises(Exception) as excinfo:
96
+ minimal[name].value = value
97
+ assert excinfo.type in (ValueError, TypeError)
98
+
99
+
100
+ def test_load_minimal_types(minimal):
101
+ """Check if the standard datatypes are loaded correctly"""
102
+ assert minimal.flt_0d.data_type == "FLT_0D"
103
+ assert minimal.flt_1d.data_type == "FLT_1D"
104
+ assert minimal.flt_2d.data_type == "FLT_2D"
105
+ assert minimal.flt_3d.data_type == "FLT_3D"
106
+ assert minimal.flt_4d.data_type == "FLT_4D"
107
+ assert minimal.flt_5d.data_type == "FLT_5D"
108
+ assert minimal.flt_6d.data_type == "FLT_6D"
109
+
110
+ assert minimal.str_0d.data_type == "STR_0D"
111
+ assert minimal.str_1d.data_type == "STR_1D"
112
+
113
+ assert minimal.int_0d.data_type == "INT_0D"
114
+ assert minimal.int_1d.data_type == "INT_1D"
115
+ assert minimal.int_2d.data_type == "INT_2D"
116
+ assert minimal.int_3d.data_type == "INT_3D"
117
+
118
+
119
+ def test_load_minimal_types_legacy(minimal):
120
+ """Check if the legacy datatypes are loaded correctly"""
121
+ assert minimal.flt_type.data_type == "FLT_0D"
122
+ assert minimal.flt_1d_type.data_type == "FLT_1D"
123
+ assert minimal.int_type.data_type == "INT_0D"
124
+ assert minimal.str_type.data_type == "STR_0D"
125
+ assert minimal.str_1d_type.data_type == "STR_1D"
126
+
127
+
128
+ def test_numeric_array_value(minimal):
129
+ assert not minimal.flt_0d.has_value
130
+ assert not minimal.flt_1d.has_value
131
+
132
+ minimal.flt_0d.value = 7.4
133
+ assert minimal.flt_0d.has_value
134
+
135
+ minimal.flt_1d.value = [1.3, 3.4]
136
+ assert minimal.flt_1d.has_value
137
+
138
+
139
+ @pytest.mark.parametrize("tp", ["flt_0d", "cpx_0d", "int_0d", "str_0d"])
140
+ def test_ids_primitive_properties_0d(minimal, tp):
141
+ assert not minimal[tp].has_value
142
+ assert minimal[tp].shape == tuple()
143
+ assert minimal[tp].size == 1
144
+
145
+ minimal[tp] = 1
146
+ assert minimal[tp].has_value
147
+ assert minimal[tp].shape == tuple()
148
+ assert minimal[tp].size == 1
149
+
150
+ minimal[tp] = minimal[tp].metadata.data_type.default
151
+ assert not minimal[tp].has_value
152
+ assert minimal[tp].shape == tuple()
153
+ assert minimal[tp].size == 1
154
+
155
+
156
+ def test_ids_primitive_properties_str_1d(minimal):
157
+ assert minimal.str_1d.shape == (0,)
158
+ assert minimal.str_1d.size == 0
159
+ assert not minimal.str_1d.has_value
160
+
161
+ minimal.str_1d.value.append("1")
162
+ assert minimal.str_1d.has_value
163
+ assert minimal.str_1d.shape == (1,)
164
+ assert minimal.str_1d.size == 1
165
+
166
+ minimal.str_1d.value.pop()
167
+ assert not minimal.str_1d.has_value
168
+ assert minimal.str_1d.shape == (0,)
169
+ assert minimal.str_1d.size == 0
170
+
171
+
172
+ @pytest.mark.parametrize("typ, max_dim", [("flt", 6), ("cpx", 6), ("int", 3)])
173
+ def test_ids_primitive_properties_numeric_arrays(minimal, typ, max_dim):
174
+ for dim in range(1, max_dim + 1):
175
+ tp = f"{typ}_{dim}d"
176
+
177
+ assert not minimal[tp].has_value
178
+ assert minimal[tp].shape == (0,) * dim
179
+ assert minimal[tp].size == 0
180
+
181
+ new_size = (2,) * dim
182
+ minimal[tp].value = np.ones(new_size)
183
+ assert minimal[tp].has_value
184
+ assert minimal[tp].shape == new_size
185
+ assert minimal[tp].size == 2**dim
186
+
187
+ minimal[tp] = np.empty((0,) * dim)
188
+ assert not minimal[tp].has_value
189
+ assert minimal[tp].shape == (0,) * dim
190
+ assert minimal[tp].size == 0
191
+
192
+
193
+ def test_ducktype_str0d(minimal):
194
+ node = minimal.str_0d
195
+ node.value = "Test"
196
+ assert str(node) == "Test"
197
+ assert len(node) == 4
198
+ # Iteration
199
+ assert list(node) == ["T", "e", "s", "t"]
200
+ # A small selection of string manipulation functions
201
+ assert node.upper() == "TEST"
202
+ assert node.lower() == "test"
203
+ assert node.split("e") == ["T", "st"]
204
+ assert node.isprintable()
205
+ assert node.replace("es", "eapo") == "Teapot"
206
+ # Indexing and slicing
207
+ assert node[:3] == "Tes"
208
+ assert node[1:2] == node[1] == "e"
209
+ # Arithmetic
210
+ assert node + "!" == "Test!"
211
+ assert node * 2 == 2 * node == "TestTest"
212
+ # In place operation and __eq__
213
+ minimal.str_0d += "X"
214
+ assert node == node.value == "TestX"
215
+ # Contains
216
+ assert "estX" in node
217
+ # Check we haven't accidentally replaced `node` with an actual string
218
+ assert node is minimal.str_0d
219
+
220
+
221
+ def test_ducktype_str1d(minimal):
222
+ node = minimal.str_1d
223
+ assert len(node) == 0
224
+ # List operations and functions
225
+ node.append(1)
226
+ assert node == ["1"]
227
+ assert node.pop() == "1"
228
+ assert bool(node) is False
229
+ node[0:] = ["a", "b"]
230
+ assert node == ["a", "b"]
231
+ node.extend("cdefgh")
232
+ assert node == list("abcdefgh")
233
+ assert "d" in node
234
+ # Indexing and slicing
235
+ assert node[:3] == ["a", "b", "c"]
236
+ assert node[4] == "e"
237
+ node[5] = "X"
238
+ assert node == list("abcdeXgh")
239
+ # More functions
240
+ assert node.count("X") == node.count("a") == 1
241
+ assert len(node) == 8
242
+ node.clear()
243
+ assert node == []
244
+ node.value = [1, 2]
245
+ node.reverse()
246
+ assert node == ["2", "1"]
247
+ node.sort()
248
+ assert node == ["1", "2"]
249
+ # Iteration
250
+ assert tuple(node) == ("1", "2")
251
+ # Arithmetic
252
+ assert node + ["3"] == list("123")
253
+ assert node * 2 == 2 * node == list("1212")
254
+ # Check we haven't accidentally replaced `node` with an actual list
255
+ assert node is minimal.str_1d
256
+
257
+
258
+ def test_ducktype_int0d(minimal):
259
+ node = minimal.int_0d
260
+ node.value = 1
261
+ assert node == 1
262
+ assert int(node) == 1
263
+ assert float(node) == 1.0
264
+ assert complex(node) == 1.0 + 0.0j
265
+ assert str(node) == "1"
266
+ assert isinstance(node, Number)
267
+ assert isinstance(node, Integral)
268
+ # int functions/properties
269
+ assert node.real == 1.0
270
+ assert node.imag == 0.0
271
+ assert node.bit_length() == 1
272
+ assert node.to_bytes(1, "little") == b"\x01"
273
+ # Arithmetic
274
+ minimal.int_0d += 3
275
+ assert node == 4
276
+ assert +node == 4
277
+ assert -node == -4
278
+ assert bool(node) is True
279
+ assert 2 * node == node * 2 == node + node == node + 4 == 4 + node == 8
280
+ assert node - node == 0
281
+ minimal.int_0d -= node
282
+ assert node == 0
283
+ assert bool(node) is False
284
+ node.value = 2
285
+ assert 3**node == 9
286
+ assert node**3 == 8
287
+ assert node / 3 == 2 / 3
288
+ assert node // 3 == 0
289
+ assert node % 3 == 2
290
+ assert node << 1 == 4
291
+ assert node >> 1 == 1
292
+ assert 1 < node <= 2
293
+ assert 2 <= node < 2.01
294
+ node.value = 7
295
+ assert divmod(node, 2) == (3, 1)
296
+ assert divmod(10, node) == (1, 3)
297
+ # Check we haven't accidentally replaced `node` with an actual int
298
+ assert node is minimal.int_0d
299
+
300
+ # Numpy operations
301
+ assert np.array_equal(node, 7)
302
+ assert np.isclose(node, 7)
303
+ assert np.array(node).dtype.kind == "i" # Don't care if int32 or int64
304
+
305
+
306
+ def test_ducktype_flt0d(minimal):
307
+ node = minimal.flt_0d
308
+ node.value = np.pi
309
+ assert node == np.pi
310
+ assert int(node) == 3
311
+ assert float(node) == np.pi
312
+ assert complex(node) == np.pi + 0.0j
313
+ assert str(node) == str(np.pi)
314
+ assert isinstance(node, Number)
315
+ assert isinstance(node, Real)
316
+ # float functions/properties
317
+ assert node.real == np.pi
318
+ assert node.imag == 0.0
319
+ assert node.conjugate() == np.pi
320
+ assert not node.is_integer()
321
+ # Arithmetic
322
+ assert +node == np.pi
323
+ assert -node == -np.pi
324
+ assert bool(node) is True
325
+ twopi = 2 * np.pi
326
+ assert 2 * node == node * 2 == node + node == node + np.pi == np.pi + node == twopi
327
+ assert node - node == 0.0
328
+ minimal.flt_0d -= node
329
+ assert node == 0
330
+ assert bool(node) is False
331
+ node.value = 2
332
+ assert isinstance(node.value, float)
333
+ assert 3**node == 9
334
+ assert node**3 == 8
335
+ assert node / 3 == 2 / 3
336
+ assert node // 3 == 0
337
+ assert node % 3 == 2
338
+ assert 1 < node <= 2
339
+ assert 2 <= node < 2.01
340
+ node.value = 7
341
+ assert divmod(node, 2) == (3, 1)
342
+ assert divmod(10, node) == (1, 3)
343
+ # Check we haven't accidentally replaced `node` with an actual float
344
+ assert node is minimal.flt_0d
345
+
346
+ # Numpy operations
347
+ assert np.array_equal(node, 7)
348
+ assert np.isclose(node, 7)
349
+ assert np.array(node).dtype == np.float64
350
+
351
+
352
+ def test_ducktype_cpx0d(minimal):
353
+ node = minimal.cpx_0d
354
+ node.value = 1.0 - 1.5j
355
+ assert node == 1.0 - 1.5j
356
+ assert complex(node) == 1.0 - 1.5j
357
+ assert str(node) == str(1.0 - 1.5j)
358
+ assert isinstance(node, Number)
359
+ assert isinstance(node, Complex)
360
+ # complex functions/properties
361
+ assert node.real == 1.0
362
+ assert node.imag == -1.5
363
+ assert node.conjugate() == 1.0 + 1.5j
364
+ # Arithmetic
365
+ assert +node == 1.0 - 1.5j
366
+ assert -node == -1.0 + 1.5j
367
+ assert bool(node) is True
368
+ assert 2 * node == node * 2 == node + node == 2.0 - 3.0j
369
+ assert node + 1.0 == 1.0 + node == 2.0 - 1.5j
370
+ assert node - node == 0
371
+ minimal.cpx_0d -= node
372
+ assert node == 0
373
+ assert bool(node) is False
374
+ node.value = 2.0 + 1j
375
+ assert 3**node == 3 ** (2.0 + 1j)
376
+ assert node**3 == (2.0 + 1j) ** 3
377
+ assert node / 3 == 2 / 3 + 1j / 3
378
+ # Check we haven't accidentally replaced `node` with an actual complex
379
+ assert node is minimal.cpx_0d
380
+
381
+ # Numpy operations
382
+ assert np.array_equal(node, 2 + 1j)
383
+ assert np.isclose(node, 2 + 1j)
384
+ assert np.array(node).dtype == np.complex128
385
+
386
+
387
+ ducktype_params = []
388
+ for dtype in (IDSDataType.INT, IDSDataType.FLT, IDSDataType.CPX):
389
+ for ndim in range(1, 4 if dtype is IDSDataType.INT else 7):
390
+ value = np.ones((2,) * ndim, dtype=dtype.numpy_dtype)
391
+ ducktype_params.append((f"{dtype.value}_{ndim}D", value))
392
+
393
+
394
+ @pytest.mark.parametrize("tp, val", ducktype_params)
395
+ def test_ducktype_ndarray(minimal, tp, val):
396
+ node = minimal[tp.lower()]
397
+ node.value = val
398
+ # Numpy array properties
399
+ assert node.shape == val.shape
400
+ assert len(node) == len(val)
401
+ assert node.ndim == val.ndim == node.metadata.ndim
402
+ # Comparisons
403
+ assert np.all(node == 1)
404
+ assert not np.any(node != 1)
405
+ assert np.all(0 < node)
406
+ assert np.all(node <= 1)
407
+ assert np.all(1 <= node)
408
+ assert np.all(node < 2)
409
+ # Some array functions
410
+ assert node.all()
411
+ assert node.min() == node.max() == node.mean() == 1.0
412
+ assert node.std() == 0.0
413
+ # Indexing
414
+ assert np.array_equal(node[1], val[1])
415
+ assert np.array_equal(node[:1], val[:1])
416
+ # Arithmetic
417
+ assert np.array_equal([1, 1] @ node, node @ [1, 1])
418
+ assert np.array_equal([1, 1] @ node, [1, 1] @ val)
419
+ assert np.array_equal(1 + node, node + 1)
420
+ assert np.array_equal(node + 1, val + 1)
421
+ assert np.array_equal(2 * node, node * 2)
422
+ assert np.array_equal(2 * node, node + node)
423
+ assert np.array_equal(2 * node, 2 * val)
424
+ assert np.array_equal(node / 2, val / 2)
425
+ assert np.array_equal(node * node, node**2)
426
+ assert np.array_equal(node**2, val**2)
427
+ if not tp.startswith("CPX"):
428
+ assert np.array_equal(node // 2, val // 2)
429
+ # Assignment
430
+ node[(1,) * node.ndim] = 0
431
+ assert node[(1,) * node.ndim] == 0
432
+ # In place operation
433
+ minimal[tp.lower()] += 2
434
+ assert node[(0,) * node.ndim] == 3
435
+ # Check we haven't accidentally replaced `node` with an actual numpy array
436
+ assert node is minimal[tp.lower()]
@@ -0,0 +1,70 @@
1
+ """A minimal testcase loading an IDS file and checking that the structure built is ok"""
2
+
3
+ import numpy as np
4
+
5
+ from imas.ids_defs import IDS_TIME_MODE_INDEPENDENT, MEMORY_BACKEND
6
+ from imas.test.test_helpers import open_dbentry, randdims
7
+
8
+ TEST_DATA = {
9
+ "str_0d": "test",
10
+ "str_1d": ["test0", "test1"],
11
+ "str_type": "test_legacy",
12
+ "str_1d_type": ["test0_legacy", "test1_legacy"],
13
+ "flt_type": 2.0,
14
+ "flt_1d_type": np.asarray([3.0, 4.0]),
15
+ "int_type": 5,
16
+ }
17
+ for i in range(0, 7):
18
+ # dimensions are random
19
+ TEST_DATA["flt_%dd" % i] = np.random.random_sample(size=randdims(i))
20
+ if i < 4:
21
+ TEST_DATA["int_%dd" % i] = np.random.randint(0, 1000, size=randdims(i))
22
+
23
+
24
+ def test_minimal_types_io(backend, ids_minimal_types, worker_id, tmp_path):
25
+ """Write and then read again a number on our minimal IDS."""
26
+ dbentry = open_dbentry(
27
+ backend, "w", worker_id, tmp_path, xml_path=ids_minimal_types
28
+ )
29
+ minimal = dbentry.factory.new("minimal")
30
+ for k, v in TEST_DATA.items():
31
+ minimal[k] = v
32
+
33
+ minimal.ids_properties.homogeneous_time = IDS_TIME_MODE_INDEPENDENT
34
+ dbentry.put(minimal)
35
+
36
+ dbentry2 = open_dbentry(
37
+ backend, "a", worker_id, tmp_path, xml_path=ids_minimal_types
38
+ )
39
+ minimal2 = dbentry2.get("minimal")
40
+ for k, v in TEST_DATA.items():
41
+ if isinstance(v, np.ndarray):
42
+ assert np.array_equal(minimal2[k].value, v)
43
+ else:
44
+ assert minimal2[k].value == v
45
+
46
+ dbentry.close()
47
+ if backend != MEMORY_BACKEND: # MEM backend already cleaned up, prevent SEGFAULT
48
+ dbentry2.close()
49
+
50
+
51
+ def test_large_numbers(backend, ids_minimal_types, worker_id, tmp_path):
52
+ """Write and then read again a large number"""
53
+ dbentry = open_dbentry(
54
+ backend, "w", worker_id, tmp_path, xml_path=ids_minimal_types
55
+ )
56
+ minimal = dbentry.factory.new("minimal")
57
+ minimal["int_0d"] = 955683416
58
+
59
+ minimal.ids_properties.homogeneous_time = IDS_TIME_MODE_INDEPENDENT
60
+ dbentry.put(minimal)
61
+
62
+ dbentry2 = open_dbentry(
63
+ backend, "a", worker_id, tmp_path, xml_path=ids_minimal_types
64
+ )
65
+ minimal2 = dbentry2.get("minimal")
66
+ assert minimal2["int_0d"] == 955683416
67
+
68
+ dbentry.close()
69
+ if backend != MEMORY_BACKEND: # MEM backend already cleaned up, prevent SEGFAULT
70
+ dbentry2.close()
@@ -0,0 +1,66 @@
1
+ """A minimal testcase loading an IDS file and checking that the structure built is ok
2
+ """
3
+
4
+ import numpy as np
5
+
6
+ from imas.ids_defs import IDS_TIME_MODE_INDEPENDENT, MEMORY_BACKEND
7
+ from imas.ids_factory import IDSFactory
8
+ from imas.test.test_helpers import fill_with_random_data, open_dbentry
9
+ from imas.test.test_minimal_types_io import TEST_DATA
10
+
11
+
12
+ def test_minimal_types_str_1d_decode(ids_minimal_types):
13
+ minimal = IDSFactory(xml_path=ids_minimal_types).new("minimal")
14
+ minimal.str_1d = [b"test", b"test2"]
15
+ assert minimal.str_1d.value == ["test", "test2"]
16
+
17
+
18
+ def test_minimal_types_str_1d_decode_and_put(
19
+ backend, ids_minimal_types, worker_id, tmp_path
20
+ ):
21
+ """The access layer changed 1d string types to bytes.
22
+ This is unexpected, especially since on read it is converted from bytes to string
23
+ again (which implies that the proper form for in python is as strings)"""
24
+ dbentry = open_dbentry(
25
+ backend, "w", worker_id, tmp_path, xml_path=ids_minimal_types
26
+ )
27
+ minimal = dbentry.factory.new("minimal")
28
+ minimal.str_1d = [b"test", b"test2"]
29
+ minimal.ids_properties.homogeneous_time = IDS_TIME_MODE_INDEPENDENT
30
+
31
+ assert minimal.str_1d.value == ["test", "test2"]
32
+ dbentry.put(minimal)
33
+ assert minimal.str_1d.value == ["test", "test2"]
34
+ dbentry.close()
35
+
36
+
37
+ def test_minimal_types_io_automatic(backend, ids_minimal_types, worker_id, tmp_path):
38
+ """Write and then read again our minimal IDS."""
39
+ dbentry = open_dbentry(
40
+ backend, "w", worker_id, tmp_path, xml_path=ids_minimal_types
41
+ )
42
+ minimal = dbentry.factory.new("minimal")
43
+ fill_with_random_data(minimal)
44
+
45
+ minimal.ids_properties.homogeneous_time = IDS_TIME_MODE_INDEPENDENT
46
+ dbentry.put(minimal)
47
+
48
+ dbentry2 = open_dbentry(
49
+ backend, "a", worker_id, tmp_path, xml_path=ids_minimal_types
50
+ )
51
+ minimal2 = dbentry2.get("minimal")
52
+ for k, v in TEST_DATA.items():
53
+ if isinstance(v, np.ndarray):
54
+ assert np.array_equal(minimal2[k].value, minimal[k].value)
55
+ else:
56
+ if isinstance(minimal2[k].value, np.ndarray):
57
+ assert np.array_equal(
58
+ minimal2[k].value,
59
+ np.asarray(minimal[k].value, dtype=minimal2[k].value.dtype),
60
+ )
61
+ else:
62
+ assert minimal2[k].value == minimal[k].value
63
+
64
+ dbentry.close()
65
+ if backend != MEMORY_BACKEND: # MEM backend already cleaned up, prevent SEGFAULT
66
+ dbentry2.close()