aesoptparam 0.3.6__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 aesoptparam might be problematic. Click here for more details.
- aesoptparam/__init__.py +13 -0
- aesoptparam/example.py +110 -0
- aesoptparam/parameterized.py +417 -0
- aesoptparam/parameters.py +641 -0
- aesoptparam/serializer.py +94 -0
- aesoptparam/test/dummy_instance.json +30 -0
- aesoptparam/test/dummy_schema.json +752 -0
- aesoptparam/test/test_parameterized.py +574 -0
- aesoptparam/test/test_parameters.py +519 -0
- aesoptparam/test/test_units.py +369 -0
- aesoptparam/test/test_utils.py +147 -0
- aesoptparam/utils/__init__.py +63 -0
- aesoptparam/utils/html_repr.py +533 -0
- aesoptparam/utils/json_utils.py +127 -0
- aesoptparam/utils/unit_library.ini +233 -0
- aesoptparam/utils/units.py +1060 -0
- aesoptparam-0.3.6.dist-info/METADATA +86 -0
- aesoptparam-0.3.6.dist-info/RECORD +21 -0
- aesoptparam-0.3.6.dist-info/WHEEL +5 -0
- aesoptparam-0.3.6.dist-info/licenses/LICENSE +21 -0
- aesoptparam-0.3.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from aesoptparam.utils.units import (
|
|
7
|
+
NumberDict,
|
|
8
|
+
PhysicalUnit,
|
|
9
|
+
_find_unit,
|
|
10
|
+
add_offset_unit,
|
|
11
|
+
add_unit,
|
|
12
|
+
convert_units,
|
|
13
|
+
import_library,
|
|
14
|
+
simplify_unit,
|
|
15
|
+
unit_conversion,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_UnknownKeyGives0():
|
|
20
|
+
# a NumberDict instance should initilize using integer and non-integer indices
|
|
21
|
+
# a NumberDict instance should initilize all entries with an initial
|
|
22
|
+
# value of 0
|
|
23
|
+
x = NumberDict()
|
|
24
|
+
|
|
25
|
+
# integer test
|
|
26
|
+
assert x[0] == 0
|
|
27
|
+
|
|
28
|
+
# string test
|
|
29
|
+
assert x["t"] == 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test__add__KnownValues():
|
|
33
|
+
# __add__ should give known result with known input
|
|
34
|
+
# for non-string data types, addition must be commutative
|
|
35
|
+
|
|
36
|
+
x = NumberDict()
|
|
37
|
+
y = NumberDict()
|
|
38
|
+
x["t1"], x["t2"] = 1, 2
|
|
39
|
+
y["t1"], y["t2"] = 2, 1
|
|
40
|
+
|
|
41
|
+
result1, result2 = x + y, y + x
|
|
42
|
+
assert np.all((3, 3) == (result1["t1"], result1["t2"]))
|
|
43
|
+
assert np.all((3, 3) == (result2["t1"], result2["t2"]))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test__sub__KnownValues():
|
|
47
|
+
# __sub__ should give known result with known input
|
|
48
|
+
# commuting the input should result in equal magnitude, opposite sign
|
|
49
|
+
|
|
50
|
+
x = NumberDict()
|
|
51
|
+
y = NumberDict()
|
|
52
|
+
x["t1"], x["t2"] = 1, 2
|
|
53
|
+
y["t1"], y["t2"] = 2, 1
|
|
54
|
+
|
|
55
|
+
result1, result2 = x - y, y - x
|
|
56
|
+
assert np.all((-1, 1) == (result1["t1"], result1["t2"]))
|
|
57
|
+
assert np.all((1, -1) == (result2["t1"], result2["t2"]))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test__mul__KnownValues():
|
|
61
|
+
# __mul__ should give known result with known input
|
|
62
|
+
|
|
63
|
+
x = NumberDict([("t1", 1), ("t2", 2)])
|
|
64
|
+
y = 10
|
|
65
|
+
|
|
66
|
+
result1, result2 = x * y, y * x
|
|
67
|
+
assert np.all((10, 20) == (result1["t1"], result1["t2"]))
|
|
68
|
+
assert np.all((10, 20) == (result2["t1"], result2["t2"]))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test__div__KnownValues():
|
|
72
|
+
# __div__ should give known result with known input
|
|
73
|
+
|
|
74
|
+
x = NumberDict()
|
|
75
|
+
x = NumberDict([("t1", 1), ("t2", 2)])
|
|
76
|
+
y = 10.0
|
|
77
|
+
result1 = x / y
|
|
78
|
+
assert np.all((0.1, 0.20) == (result1["t1"], result1["t2"]))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
with open(
|
|
82
|
+
os.path.join(os.path.dirname(__file__), "../utils/unit_library.ini")
|
|
83
|
+
) as default_lib:
|
|
84
|
+
_unitLib = import_library(default_lib)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _get_powers(**powdict):
|
|
88
|
+
powers = [0] * len(_unitLib.base_types)
|
|
89
|
+
for name, power in powdict.items():
|
|
90
|
+
powers[_unitLib.base_types[name]] = power
|
|
91
|
+
return powers
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_repr_str():
|
|
95
|
+
# __repr__should return a string which could be used to contruct the
|
|
96
|
+
# unit instance, __str__ should return a string with just the unit
|
|
97
|
+
# name for str
|
|
98
|
+
|
|
99
|
+
u = _find_unit("d")
|
|
100
|
+
|
|
101
|
+
assert repr(u) == "PhysicalUnit({'d': 1},86400.0,%s,0.0)" % _get_powers(time=1)
|
|
102
|
+
assert str(u) == "<PhysicalUnit d>"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_cmp():
|
|
106
|
+
# should error for incompatible units, if they are compatible then it
|
|
107
|
+
# should cmp on their factors
|
|
108
|
+
|
|
109
|
+
x = _find_unit("d")
|
|
110
|
+
y = _find_unit("s")
|
|
111
|
+
z = _find_unit("ft")
|
|
112
|
+
|
|
113
|
+
assert x > y
|
|
114
|
+
assert x == x
|
|
115
|
+
assert y < x
|
|
116
|
+
|
|
117
|
+
with pytest.raises(TypeError, match="Units 'd' and 'ft' are incompatible."):
|
|
118
|
+
x < z
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
known__mul__Values = (
|
|
122
|
+
("1m", "5m", 5),
|
|
123
|
+
("1cm", "1cm", 1),
|
|
124
|
+
("1cm", "5m", 5),
|
|
125
|
+
("7km", "1m", 7),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_multiply():
|
|
130
|
+
# multiplication should error for units with offsets
|
|
131
|
+
|
|
132
|
+
x = _find_unit("g")
|
|
133
|
+
y = _find_unit("s")
|
|
134
|
+
z = _find_unit("degC")
|
|
135
|
+
|
|
136
|
+
assert x * y == PhysicalUnit(
|
|
137
|
+
{"s": 1, "kg": 1}, 0.001, _get_powers(mass=1, time=1), 0
|
|
138
|
+
)
|
|
139
|
+
assert y * x == PhysicalUnit(
|
|
140
|
+
{"s": 1, "kg": 1}, 0.001, _get_powers(mass=1, time=1), 0
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
with pytest.raises(
|
|
144
|
+
TypeError,
|
|
145
|
+
match="Can't multiply units: either 'g' or 'degC' has a non-zero offset.",
|
|
146
|
+
):
|
|
147
|
+
x * z
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def test_division():
|
|
151
|
+
# division should error when working with offset units
|
|
152
|
+
|
|
153
|
+
w = _find_unit("kg")
|
|
154
|
+
x = _find_unit("g")
|
|
155
|
+
y = _find_unit("s")
|
|
156
|
+
z = _find_unit("degC")
|
|
157
|
+
|
|
158
|
+
quo = w / x
|
|
159
|
+
quo2 = x / y
|
|
160
|
+
|
|
161
|
+
assert np.all(quo == PhysicalUnit({"kg": 1, "g": -1}, 1000.0, _get_powers(), 0))
|
|
162
|
+
assert np.all(
|
|
163
|
+
quo2 == PhysicalUnit({"s": -1, "g": 1}, 0.001, _get_powers(mass=1, time=-1), 0),
|
|
164
|
+
)
|
|
165
|
+
quo = y / 2.0
|
|
166
|
+
assert np.all(quo == PhysicalUnit({"s": 1, "2.0": -1}, 0.5, _get_powers(time=1), 0))
|
|
167
|
+
quo = 2.0 / y
|
|
168
|
+
assert np.all(quo == PhysicalUnit({"s": -1, "2.0": 1}, 2, _get_powers(time=-1), 0))
|
|
169
|
+
with pytest.raises(
|
|
170
|
+
TypeError,
|
|
171
|
+
match="Can't divide units: either 'g' or 'degC' has a non-zero offset.",
|
|
172
|
+
):
|
|
173
|
+
x / z
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
known__pow__Values = (("1V", 3), ("1m", 2), ("1.1m", 2))
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_pow():
|
|
180
|
+
# power should error for offest units and for non-integer powers
|
|
181
|
+
|
|
182
|
+
x = _find_unit("m")
|
|
183
|
+
y = _find_unit("degF")
|
|
184
|
+
|
|
185
|
+
z = x**3
|
|
186
|
+
assert np.all(z == _find_unit("m**3"))
|
|
187
|
+
x = z ** (1.0 / 3.0) # checks inverse integer units
|
|
188
|
+
assert np.all(x == _find_unit("m"))
|
|
189
|
+
z = 5.2 * x**2 # Test with value
|
|
190
|
+
x = z ** (1.0 / 2.0)
|
|
191
|
+
assert np.all(x == (np.sqrt(5.2) * _find_unit("m")))
|
|
192
|
+
x = _find_unit("m")
|
|
193
|
+
|
|
194
|
+
# test offset units:
|
|
195
|
+
with pytest.raises(
|
|
196
|
+
TypeError,
|
|
197
|
+
match="Can't exponentiate unit 'degF' because it has a non-zero offset.",
|
|
198
|
+
):
|
|
199
|
+
y**17
|
|
200
|
+
|
|
201
|
+
# test non-integer powers
|
|
202
|
+
with pytest.raises(
|
|
203
|
+
TypeError,
|
|
204
|
+
match="Can't exponentiate unit 'm': only integer and inverse integer exponents are allowed.",
|
|
205
|
+
):
|
|
206
|
+
x**1.2
|
|
207
|
+
|
|
208
|
+
with pytest.raises(
|
|
209
|
+
TypeError,
|
|
210
|
+
match="Can't exponentiate unit 'm': only integer and inverse integer exponents are allowed.",
|
|
211
|
+
):
|
|
212
|
+
x ** (5.0 / 2.0)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_compare():
|
|
216
|
+
x = _find_unit("m")
|
|
217
|
+
y = _find_unit("degF")
|
|
218
|
+
|
|
219
|
+
with pytest.raises(TypeError, match="Units 'm' and 'degF' are incompatible."):
|
|
220
|
+
x > y
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
known__conversion_factor_to__Values = (
|
|
224
|
+
("1m", "1cm", 100),
|
|
225
|
+
("1s", "1ms", 1000),
|
|
226
|
+
("1ms", "1s", 0.001),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_conversion_tuple_to():
|
|
231
|
+
# test_conversion_tuple_to shoudl error when units have different power
|
|
232
|
+
# lists
|
|
233
|
+
|
|
234
|
+
w = _find_unit("cm")
|
|
235
|
+
x = _find_unit("m")
|
|
236
|
+
y = _find_unit("degF")
|
|
237
|
+
z1 = _find_unit("degC")
|
|
238
|
+
|
|
239
|
+
# check for non offset units
|
|
240
|
+
assert np.all(w.conversion_tuple_to(x) == (1 / 100.0, 0))
|
|
241
|
+
|
|
242
|
+
# check for offset units
|
|
243
|
+
result = y.conversion_tuple_to(z1)
|
|
244
|
+
np.testing.assert_almost_equal(result[0], 0.556, 3)
|
|
245
|
+
np.testing.assert_almost_equal(result[1], -32.0, 3)
|
|
246
|
+
np.testing.assert_almost_equal
|
|
247
|
+
|
|
248
|
+
# check for incompatible units
|
|
249
|
+
with pytest.raises(
|
|
250
|
+
TypeError,
|
|
251
|
+
match="Units 'm' and 'degC' are incompatible.",
|
|
252
|
+
):
|
|
253
|
+
x.conversion_tuple_to(z1)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def test_name():
|
|
257
|
+
# name should return a mathematically correct representation of the
|
|
258
|
+
# unit
|
|
259
|
+
x1 = _find_unit("m")
|
|
260
|
+
x2 = _find_unit("kg")
|
|
261
|
+
y = 1 / x1
|
|
262
|
+
assert np.all(y.name() == "1/m")
|
|
263
|
+
y = 1 / x1 / x1
|
|
264
|
+
assert np.all(y.name() == "1/m**2")
|
|
265
|
+
y = x1**2
|
|
266
|
+
assert np.all(y.name() == "m**2")
|
|
267
|
+
y = x2 / (x1**2)
|
|
268
|
+
assert np.all(y.name() == "kg/m**2")
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_unit_conversion():
|
|
272
|
+
assert np.all(unit_conversion("km", "m") == (1000.0, 0.0))
|
|
273
|
+
|
|
274
|
+
with pytest.raises(
|
|
275
|
+
ValueError,
|
|
276
|
+
match="The units '1.0' are invalid.",
|
|
277
|
+
):
|
|
278
|
+
unit_conversion("km", 1.0)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def test_unit_simplification():
|
|
282
|
+
test_strings = [
|
|
283
|
+
"ft/s*s",
|
|
284
|
+
"m/s*s",
|
|
285
|
+
"m * ft * cm / km / m",
|
|
286
|
+
"s/s",
|
|
287
|
+
"m ** 7 / m ** 5",
|
|
288
|
+
]
|
|
289
|
+
|
|
290
|
+
correct_strings = ["ft", "m", "ft*cm/km", None, "m**2"]
|
|
291
|
+
|
|
292
|
+
for test_str, correct_str in zip(test_strings, correct_strings):
|
|
293
|
+
simplified_str = simplify_unit(test_str)
|
|
294
|
+
assert np.all(simplified_str == correct_str)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def test_atto_seconds():
|
|
298
|
+
# The unit 'as' was bugged because it is a python keyword.
|
|
299
|
+
|
|
300
|
+
fact = unit_conversion("s", "as")
|
|
301
|
+
assert abs(fact[0] - 1e18) / 1e18 < 1e-15
|
|
302
|
+
|
|
303
|
+
# Make sure regex for 'as' doesn't pick up partial words.
|
|
304
|
+
fact = unit_conversion("aslug*as*as", "aslug*zs*zs")
|
|
305
|
+
assert abs(fact[0] - 1e6) / 1e6 < 1e-15
|
|
306
|
+
|
|
307
|
+
# Make sure simplification works.
|
|
308
|
+
simple = simplify_unit("m*as/as")
|
|
309
|
+
assert np.all(simple == "m")
|
|
310
|
+
|
|
311
|
+
simple = simplify_unit("as**6/as**4")
|
|
312
|
+
assert np.all(simple == "as**2")
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def test_add_unit():
|
|
316
|
+
with pytest.raises(
|
|
317
|
+
KeyError,
|
|
318
|
+
match="Unit 'ft' already defined with different factor or powers.",
|
|
319
|
+
):
|
|
320
|
+
add_unit("ft", "20*m")
|
|
321
|
+
|
|
322
|
+
with pytest.raises(
|
|
323
|
+
KeyError,
|
|
324
|
+
match="Unit 'degR' already defined with different factor or powers.",
|
|
325
|
+
):
|
|
326
|
+
add_offset_unit("degR", "degK", 20, 10)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def test_various():
|
|
330
|
+
# Test .in_base_units
|
|
331
|
+
x = _find_unit("kg*Pa")
|
|
332
|
+
assert x.in_base_units() == _find_unit("kg**2/(m*s**2)")
|
|
333
|
+
x = _find_unit("m**-1")
|
|
334
|
+
assert x.in_base_units() == _find_unit("1/m")
|
|
335
|
+
|
|
336
|
+
# .is_dimensionless
|
|
337
|
+
x = _find_unit("Pa")
|
|
338
|
+
assert not x.is_dimensionless()
|
|
339
|
+
assert (x / _find_unit("N/m**2")).is_dimensionless()
|
|
340
|
+
|
|
341
|
+
# .is_angle
|
|
342
|
+
assert not x.is_angle()
|
|
343
|
+
x = _find_unit("rad")
|
|
344
|
+
assert x.is_angle()
|
|
345
|
+
x = _find_unit("rad/s")
|
|
346
|
+
assert not x.is_angle()
|
|
347
|
+
|
|
348
|
+
# Double letter unit prefix
|
|
349
|
+
x = _find_unit("dam")
|
|
350
|
+
assert x == 10 * _find_unit("m")
|
|
351
|
+
|
|
352
|
+
# Invalid prefix
|
|
353
|
+
units = "xxm"
|
|
354
|
+
with pytest.raises(ValueError, match=f"The units '{units}' are invalid."):
|
|
355
|
+
x = _find_unit(units, True)
|
|
356
|
+
# Should not fail without flag
|
|
357
|
+
x = _find_unit(units)
|
|
358
|
+
|
|
359
|
+
# convert_unit
|
|
360
|
+
ounits = "Pa"
|
|
361
|
+
val = 4 * _find_unit(ounits)
|
|
362
|
+
nunits = "hPa"
|
|
363
|
+
# Return current val
|
|
364
|
+
nval = convert_units(val, None)
|
|
365
|
+
assert nval == val
|
|
366
|
+
|
|
367
|
+
# simplify_units
|
|
368
|
+
out = simplify_unit(None)
|
|
369
|
+
assert out is None
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from aesoptparam.utils.html_repr import json_data_render
|
|
7
|
+
from aesoptparam.utils.json_utils import is_valid_json, read_json, write_json
|
|
8
|
+
|
|
9
|
+
file_path = os.path.dirname(__file__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_read_json():
|
|
13
|
+
data = read_json(os.path.join(file_path, "dummy_instance.json"))
|
|
14
|
+
|
|
15
|
+
assert isinstance(data, dict)
|
|
16
|
+
assert len(data) == 15
|
|
17
|
+
assert data["version"] == "0.0.0"
|
|
18
|
+
assert isinstance(data["d"], np.ndarray)
|
|
19
|
+
assert isinstance(data["e"], np.ndarray)
|
|
20
|
+
assert isinstance(data["sub1"], dict)
|
|
21
|
+
assert len(data["sub1"]) == 5
|
|
22
|
+
assert isinstance(data["sub1"]["b"], np.ndarray)
|
|
23
|
+
|
|
24
|
+
data = read_json(os.path.join(file_path, "dummy_instance.json"), False)
|
|
25
|
+
|
|
26
|
+
assert isinstance(data, dict)
|
|
27
|
+
assert len(data) == 15
|
|
28
|
+
assert data["version"] == "0.0.0"
|
|
29
|
+
assert isinstance(data["d"], list)
|
|
30
|
+
assert isinstance(data["e"], list)
|
|
31
|
+
assert isinstance(data["sub1"], dict)
|
|
32
|
+
assert len(data["sub1"]) == 5
|
|
33
|
+
assert isinstance(data["sub1"]["b"], list)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_write_json(tmp_path):
|
|
37
|
+
# Input data
|
|
38
|
+
data = dict(
|
|
39
|
+
a="a",
|
|
40
|
+
b=np.int16(2),
|
|
41
|
+
c=np.float16(5.1),
|
|
42
|
+
d=np.array([0, 2.0, 3.1]),
|
|
43
|
+
e=dict(a="a", b=2, c=5.1, d=np.array([0, 2.0, 3.1])),
|
|
44
|
+
f=[
|
|
45
|
+
dict(a="a", b=2, c=5.1, d=np.array([0, 2.0, 3.1])),
|
|
46
|
+
dict(a="a", b=2, c=5.1, d=np.array([0, 2.0, 3.1])),
|
|
47
|
+
],
|
|
48
|
+
g=np.bool_(True),
|
|
49
|
+
)
|
|
50
|
+
filename = os.path.join(tmp_path, "dummy.json")
|
|
51
|
+
|
|
52
|
+
# Write data file
|
|
53
|
+
write_json(filename, data)
|
|
54
|
+
|
|
55
|
+
# Read data back in
|
|
56
|
+
_data = read_json(filename)
|
|
57
|
+
assert isinstance(_data["a"], str)
|
|
58
|
+
assert isinstance(_data["b"], int)
|
|
59
|
+
assert isinstance(_data["c"], float)
|
|
60
|
+
assert isinstance(_data["d"], np.ndarray)
|
|
61
|
+
assert isinstance(_data["e"]["a"], str)
|
|
62
|
+
assert isinstance(_data["e"]["b"], int)
|
|
63
|
+
assert isinstance(_data["e"]["c"], float)
|
|
64
|
+
assert isinstance(_data["e"]["d"], np.ndarray)
|
|
65
|
+
assert isinstance(_data["f"][0]["a"], str)
|
|
66
|
+
assert isinstance(_data["f"][0]["b"], int)
|
|
67
|
+
assert isinstance(_data["f"][0]["c"], float)
|
|
68
|
+
assert isinstance(_data["f"][0]["d"], np.ndarray)
|
|
69
|
+
assert isinstance(_data["f"][1]["a"], str)
|
|
70
|
+
assert isinstance(_data["f"][1]["b"], int)
|
|
71
|
+
assert isinstance(_data["f"][1]["c"], float)
|
|
72
|
+
assert isinstance(_data["f"][1]["d"], np.ndarray)
|
|
73
|
+
|
|
74
|
+
_data = read_json(filename, False)
|
|
75
|
+
|
|
76
|
+
# Raise if not converting numpy
|
|
77
|
+
with pytest.raises(TypeError, match="is not JSON serializable"):
|
|
78
|
+
write_json(filename, data, False)
|
|
79
|
+
|
|
80
|
+
# Raise if not converting numpy
|
|
81
|
+
with pytest.raises(TypeError, match="is not JSON serializable"):
|
|
82
|
+
write_json(filename, object())
|
|
83
|
+
|
|
84
|
+
# Write data file
|
|
85
|
+
write_json(filename, _data, False)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_is_valid_json():
|
|
89
|
+
data = dict(
|
|
90
|
+
a="a",
|
|
91
|
+
b=2,
|
|
92
|
+
c=5.1,
|
|
93
|
+
d=np.array([0, 2.0, 3.1]),
|
|
94
|
+
e=dict(a="a", b=2, c=5.1, d=np.array([0, 2.0, 3.1])),
|
|
95
|
+
f=[
|
|
96
|
+
dict(a="a", b=2, c=5.1, d=np.array([0, 2.0, 3.1])),
|
|
97
|
+
dict(a="a", b=2, c=5.1, d=np.array([0, 2.0, 3.1])),
|
|
98
|
+
],
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
assert is_valid_json(data, True)
|
|
102
|
+
|
|
103
|
+
assert is_valid_json(data) is False
|
|
104
|
+
|
|
105
|
+
data["d"] = data["d"].tolist()
|
|
106
|
+
data["e"]["d"] = data["e"]["d"].tolist()
|
|
107
|
+
data["f"][0]["d"] = data["f"][0]["d"].tolist()
|
|
108
|
+
data["f"][1]["d"] = data["f"][1]["d"].tolist()
|
|
109
|
+
|
|
110
|
+
assert is_valid_json(data)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_json2html():
|
|
114
|
+
data = dict(
|
|
115
|
+
a=0.2,
|
|
116
|
+
b=[0.1, 0.2],
|
|
117
|
+
c=np.array([0.2, 0.3]),
|
|
118
|
+
d=dict(a=0.1, b=dict(a=0.1)),
|
|
119
|
+
e=[
|
|
120
|
+
dict(a=0.2),
|
|
121
|
+
dict(a=0.3),
|
|
122
|
+
dict(a=[0.1, 0.2, 0.3]),
|
|
123
|
+
dict(a=[dict(a=0.1), 0.5, "str"]),
|
|
124
|
+
],
|
|
125
|
+
)
|
|
126
|
+
json_data_render(data)._repr_html_()
|
|
127
|
+
json_data_render(data, True)._repr_html_()
|
|
128
|
+
json_data_render(data, fields=["e", 3, "a", 0])._repr_html_()
|
|
129
|
+
json_data_render(data, fields=[["e", 2, "a"], ["e", 3, "a", 0]])._repr_html_()
|
|
130
|
+
json_data_render(data, True, fields=["e", 3, "a", 0])._repr_html_()
|
|
131
|
+
json_data_render(data, True, fields=[["d", "b"], ["e", 3, "a", 0]])._repr_html_()
|
|
132
|
+
|
|
133
|
+
json_data_render([data])._repr_html_()
|
|
134
|
+
json_data_render(5.0)._repr_html_()
|
|
135
|
+
|
|
136
|
+
big_array_dict = {
|
|
137
|
+
"a" + str(i): np.random.rand(*size)
|
|
138
|
+
for i, size in enumerate(
|
|
139
|
+
[(5,), (50,), (100,), (1000,), (100, 100), (10, 10, 10)]
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
out1 = json_data_render(big_array_dict)._repr_html_()
|
|
143
|
+
out2 = json_data_render(big_array_dict, max_arr_size=-1)._repr_html_()
|
|
144
|
+
assert out1.__sizeof__() < out2.__sizeof__()
|
|
145
|
+
|
|
146
|
+
with pytest.raises(ValueError, match="`fields` has to be"):
|
|
147
|
+
json_data_render(data, fields="test")._repr_html_()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from .html_repr import display_json_data
|
|
2
|
+
from .json_utils import read_json, write_json
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def copy_param(param, exclude=None, update=None):
|
|
6
|
+
"""Copy a Parameter, either a standalone `Parameter` (`AESOptNumber`, `AESOptArray`, ..) or from a `Parametrized` class (using `par_class.param.param_name`)
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
param : `Parameter`
|
|
11
|
+
Parameter instance
|
|
12
|
+
exclude : list, optional
|
|
13
|
+
List of entries to exclude, by default None
|
|
14
|
+
update : dict, optional
|
|
15
|
+
Dict with values to update, by default None
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
`Parameter`
|
|
20
|
+
Copy of parameter instance. Optionally without entries from `exclude` or updated values from `update`
|
|
21
|
+
"""
|
|
22
|
+
if exclude is None:
|
|
23
|
+
exclude = []
|
|
24
|
+
if update is None:
|
|
25
|
+
update = dict()
|
|
26
|
+
kwargs = dict()
|
|
27
|
+
for name in param._slot_defaults:
|
|
28
|
+
val = getattr(param, name)
|
|
29
|
+
if not name in exclude and val is not None:
|
|
30
|
+
kwargs[name] = val
|
|
31
|
+
for name, val in update.items():
|
|
32
|
+
kwargs[name] = val
|
|
33
|
+
|
|
34
|
+
return type(param)(**kwargs)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def copy_param_ref(param, ref, exclude=None, update=None):
|
|
38
|
+
"""Similar to `copy_param` but adding "default" to `exclude` and "default_ref" to `update` with value of `ref`
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
param : `Parameter`
|
|
43
|
+
Parameter instance
|
|
44
|
+
ref : str
|
|
45
|
+
String with the reference path
|
|
46
|
+
exclude : list, optional
|
|
47
|
+
List of entries to exclude, by default None
|
|
48
|
+
update : dict, optional
|
|
49
|
+
Dict with values to update, by default None
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
`Parameter`
|
|
54
|
+
Copy of parameter instance. Optionally without entries from `exclude` or updated values from `update`
|
|
55
|
+
"""
|
|
56
|
+
if exclude is None:
|
|
57
|
+
exclude = []
|
|
58
|
+
if update is None:
|
|
59
|
+
update = dict()
|
|
60
|
+
if not "default" in exclude:
|
|
61
|
+
exclude.append("default")
|
|
62
|
+
update["default_ref"] = ref
|
|
63
|
+
return copy_param(param, exclude, update)
|