aesoptparam 0.3.7__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.
@@ -0,0 +1,533 @@
1
+ import sys
2
+ from gc import get_referents
3
+ from types import FunctionType, ModuleType
4
+
5
+ import numpy as np
6
+ import param as pm
7
+ from param.parameterized import truncate
8
+
9
+ from .json_utils import is_valid_json
10
+
11
+ try:
12
+ import markdown
13
+
14
+ has_markdown = True
15
+ except ImportError: # pragma: no cover
16
+ has_markdown = False
17
+
18
+ html_repr_settings = {"max_arr_size": 30}
19
+
20
+
21
+ def param_html_repr(
22
+ key, val, parameter, parametrized, vallen=30, max_arr_size=None
23
+ ): # pragma: no cover
24
+ """HTML representation for a single Parameter object and its value"""
25
+
26
+ if hasattr(parameter, "bounds"):
27
+ if parameter.bounds is None:
28
+ range_ = ""
29
+ elif hasattr(parameter, "inclusive_bounds"):
30
+ bl, bu = parameter.bounds
31
+ il, iu = parameter.inclusive_bounds
32
+
33
+ lb = "" if bl is None else (">=" if il else ">") + str(bl)
34
+ ub = "" if bu is None else ("<=" if iu else "<") + str(bu)
35
+ range_ = lb + (", " if lb and bu else "") + ub
36
+ else:
37
+ range_ = repr(parameter.bounds)
38
+ elif hasattr(parameter, "objects") and parameter.objects:
39
+ range_ = ", ".join(list(map(repr, parameter.objects)))
40
+ elif hasattr(parameter, "class_"):
41
+ if isinstance(parameter.class_, tuple):
42
+ range_ = (
43
+ "type=<code>"
44
+ + " | ".join(kls.__name__ for kls in parameter.class_)
45
+ + "</code>"
46
+ )
47
+ else:
48
+ range_ = f"type=<code>{parameter.class_.__name__}</code>"
49
+ elif hasattr(parameter, "regex") and parameter.regex is not None:
50
+ range_ = f"regex({parameter.regex})"
51
+ else:
52
+ range_ = ""
53
+
54
+ if parameter.readonly:
55
+ range_ = " ".join(s for s in ["<i>read-only</i>", range_] if s)
56
+ elif parameter.constant:
57
+ range_ = " ".join(s for s in ["<i>constant</i>", range_] if s)
58
+
59
+ if getattr(parameter, "shape", False):
60
+ if len(range_) > 0:
61
+ range_ += "<br>"
62
+ range_ += f"shape=<code>{parameter.shape}</code>"
63
+ if getattr(parameter, "item_type", False):
64
+ if isinstance(parameter.item_type, tuple):
65
+ item_type = " | ".join(kls.__name__ for kls in parameter.item_type)
66
+ else:
67
+ item_type = parameter.item_type.__name__
68
+ if len(range_) > 0:
69
+ range_ += "<br>"
70
+ range_ += f"item_type=<code>{item_type}</code>"
71
+
72
+ units = getattr(parameter, "units", False)
73
+ if units is None:
74
+ units = "-"
75
+ elif isinstance(units, str):
76
+ units = f"<code>{units}</code>"
77
+ else:
78
+ units = ""
79
+
80
+ if isinstance(val, pm.Parameterized) or (
81
+ type(val) is type and issubclass(val, pm.Parameterized)
82
+ ):
83
+ # value = val.param._repr_html_(open=False)
84
+ value = parameterized_repr_html(val, open=False)
85
+ elif (
86
+ isinstance(val, list) and len(val) > 0 and isinstance(val[0], pm.Parameterized)
87
+ ):
88
+ value = ListOfParameterized_repr_html(
89
+ key, val, parameter.identifier, False, max_arr_size
90
+ )
91
+ elif hasattr(val, "_repr_html_"):
92
+ value = val._repr_html_()
93
+ elif hasattr(parametrized.param[key], "repr_html"):
94
+ val_pp = parametrized._param__private.values.get(key, None)
95
+ value = parametrized.param[key].repr_html(val, val_pp, max_arr_size)
96
+ else:
97
+ value = repr_val(val, max_arr_size)
98
+
99
+ doc = parameter.doc.strip() if parameter.doc else ""
100
+ if doc.startswith("\x1b"):
101
+ doc = ""
102
+ elif "\n\x1b" in doc:
103
+ doc = doc.split("\n\x1b")[0]
104
+ if has_markdown:
105
+ doc = markdown.markdown(doc)
106
+
107
+ return (
108
+ f"<tr>"
109
+ f' <td><p style="margin-bottom: 0px;">{key}</p></td>'
110
+ f' <td style="max-width: 300px; text-align:left;">{doc}</td>'
111
+ f' <td style="text-align:left;">{parameter.__class__.__name__}</td>'
112
+ f' <td style="max-width: 300px;">{range_}</td>'
113
+ f' <td style="max-width: 100px;">{units}</td>'
114
+ f' <td style="min-width: 300px; text-align:left;">{value}</td>'
115
+ f"</tr>\n"
116
+ )
117
+
118
+
119
+ def parameterized_repr_html(p, open, title=None, max_arr_size=None): # pragma: no cover
120
+ """HTML representation for a Parameterized object"""
121
+ # Changed the layout to set value at the end to make display of nested objects better
122
+ # as well as adding documentation column that is markdown rendered
123
+ if isinstance(p, pm.Parameterized):
124
+ if title is None:
125
+ cls = p.__class__
126
+ title = cls.name + "()"
127
+ value_field = "Value"
128
+ else:
129
+ if title is None:
130
+ cls = p
131
+ title = cls.name
132
+ value_field = "Default"
133
+ openstr = " open" if open else ""
134
+ precedence = sorted(
135
+ [
136
+ (0.5 if el.precedence is None else el.precedence, name)
137
+ for name, el in p.param.objects().items()
138
+ ]
139
+ )
140
+ contents_list = []
141
+ for _, name in precedence:
142
+ # Skip .name if it is the default name
143
+ if (name == "name") and (
144
+ p.param[name].doc == "\n String identifier for this object."
145
+ ):
146
+ continue
147
+ contents_list.append(
148
+ param_html_repr(name, p[name], p.param[name], p, max_arr_size=max_arr_size)
149
+ )
150
+ contents = "".join(contents_list)
151
+ return (
152
+ f'<details {openstr} style="border-width:1px;border-radius:25px;">\n'
153
+ ' <summary style="display:list-item; outline:none;padding-left:10px;">\n'
154
+ f" <tt>{title}</tt>\n"
155
+ " </summary>\n"
156
+ ' <div style="padding-left:10px; padding-bottom:5px;">\n'
157
+ ' <table style="max-width:100%;">\n'
158
+ f' <tr><th style="text-align:left;">Name</th><th style="text-align:left;">Documentation</th><th style="text-align:left;">Type</th><th>Range</th><th>Units</th><th style="text-align:left;">{value_field}</th></tr>\n'
159
+ f"{contents}\n"
160
+ " </table>\n </div>\n</details>\n"
161
+ )
162
+
163
+
164
+ def ListOfParameterized_repr_html(
165
+ title, items, identifier, open=True, max_arr_size=None
166
+ ): # pragma: no cover
167
+ """HTML render an ListOfParameterized as a one column table with each element in the list. Each element is identified by an `identifier`."""
168
+ openstr = " open" if open else ""
169
+ contents = "".join(
170
+ [
171
+ "<tr><td>"
172
+ + parameterized_repr_html(
173
+ val,
174
+ False,
175
+ val.__class__.name + f"({identifier}=<code>{val[identifier]}</code>)",
176
+ max_arr_size=max_arr_size,
177
+ )
178
+ + "<td></tr>"
179
+ for val in items
180
+ ]
181
+ )
182
+ return (
183
+ f"<details {openstr}>\n"
184
+ ' <summary style="display:list-item; outline:none;">\n'
185
+ f" <tt>{title}</tt>\n"
186
+ " </summary>\n"
187
+ ' <div style="padding-left:10px; padding-bottom:5px;">\n'
188
+ ' <table style="max-width:100%;">\n'
189
+ f" <tr><th></th></tr>\n"
190
+ f"{contents}\n"
191
+ " </table>\n </div>\n</details>\n"
192
+ )
193
+
194
+
195
+ def value_ref_default_repr_html(
196
+ parameter, val, val_pp, max_arr_size
197
+ ): # pragma: no cover
198
+ """HTML render of a parameter with reference and/or default states. `val` is the parameter value after full evaluation (as seen by the user). `val_pp` is the value from `._param__private.values` which is the value that is stored."""
199
+ from ..parameters import Function, Reference
200
+
201
+ if val_pp is None and not parameter.default is None:
202
+ val_pp = parameter.default
203
+ if isinstance(val_pp, Reference):
204
+ title, value = ref_html_repr(val, val_pp, max_arr_size)
205
+ elif isinstance(val_pp, Function):
206
+ title = f"<i>$function:</i> {repr_val(val, max_arr_size)}"
207
+ value = f"<i>definition:</i> <code>{val_pp.source_str}</code><br>"
208
+ elif (val_pp is None) and (not val is None):
209
+ if hasattr(parameter, "default_full") and (not parameter.default_full is None):
210
+ title = f"<i>default full:</i> {repr_val(val, max_arr_size)}"
211
+ value = f"<i>full args:</i> {parameter.default_full}"
212
+ elif hasattr(parameter, "default_interp") and (
213
+ not parameter.default_interp is None
214
+ ):
215
+ title = f"<i>default interp:</i> {repr_val(val, max_arr_size)}"
216
+ value = f"<i>interp args:</i> {parameter.default_interp}"
217
+ elif hasattr(parameter, "default_ref") and (not parameter.default_ref is None):
218
+ title, value = ref_html_repr(val, parameter.default_ref, max_arr_size)
219
+ else:
220
+ return "None"
221
+ elif isinstance(val, (float, int)):
222
+ return str(val)
223
+ elif isinstance(parameter, pm.String) and isinstance(val, str):
224
+ return repr_val(val, max_arr_size)
225
+ elif (val_pp is None) and (val is None):
226
+ return "None"
227
+ else:
228
+ return repr_val(val, max_arr_size)
229
+ return (
230
+ f"<details>\n"
231
+ ' <summary style="display:list-item; outline:none;">\n'
232
+ f" <tt>{title}</tt>\n"
233
+ " </summary>\n"
234
+ ' <div style="padding-left:10px; padding-bottom:5px;">\n'
235
+ f"{value}\n"
236
+ "</div>\n</details>\n"
237
+ )
238
+
239
+
240
+ def repr_val(val, max_arr_size):
241
+ if isinstance(val, str):
242
+ return "'" + val + "'"
243
+ elif isinstance(val, (dict, list, np.ndarray)) and is_valid_json(val, True):
244
+ val = json2html(
245
+ is_valid_json(val, True),
246
+ title=f"{truncate(repr(val))}",
247
+ max_arr_size=max_arr_size,
248
+ display_inline=True,
249
+ )
250
+ return str(val)
251
+
252
+
253
+ def ref_html_repr(val, val_pp, max_arr_size):
254
+ title = f"<i>$ref:</i> {repr_val(val, max_arr_size)}"
255
+ value = f"<i>path:</i> <code>{val_pp.path.strip()}</code>"
256
+ return title, value
257
+
258
+
259
+ class parameterized_repr_html_class:
260
+
261
+ def __init__(self, parameterized_ins, open=True, title=None, max_arr_size=None):
262
+ self.parameterized_ins = parameterized_ins
263
+ self.open = open
264
+ self.title = title
265
+ self.max_arr_size = max_arr_size
266
+
267
+ def _repr_html_(self):
268
+ return parameterized_repr_html(
269
+ self.parameterized_ins, self.open, self.title, self.max_arr_size
270
+ )
271
+
272
+
273
+ # %% JSON dict render
274
+ def json2html(
275
+ data_in,
276
+ open_default=False,
277
+ fields=None,
278
+ max_arr_size=None,
279
+ title=None,
280
+ display_inline=False,
281
+ ):
282
+ # %% Setting/checking default input
283
+ # Ensuring open_fields is a list of list's
284
+ if not (fields is None or isinstance(fields, bool)):
285
+ if not isinstance(fields, list):
286
+ raise ValueError(f"`fields` has to be a list (given: {fields})")
287
+ if not isinstance(fields[0], list):
288
+ fields = [fields]
289
+ # If root object should be open
290
+ open = open_default
291
+ if isinstance(fields, bool):
292
+ open = fields
293
+ fields = None
294
+ elif fields is not None:
295
+ open = True
296
+ openstr = " open" if open else ""
297
+ # Setting max_arr_size
298
+ if max_arr_size is None:
299
+ data_size = get_data_size(data_in)
300
+ if data_size > 1_000_000: # Rough size of 1000 size 100 arrays
301
+ max_arr_size = 5
302
+ elif data_size > 100_000: # Rough size of 100 size 100 arrays
303
+ max_arr_size = 10
304
+ elif data_size > 10_000: # Rough size of 10 size 100 arrays
305
+ max_arr_size = 100
306
+ else:
307
+ max_arr_size = -1 # Print all data
308
+ # Title
309
+ if title is None:
310
+ title = truncate(repr(data_in))
311
+ # Displaying inline
312
+ details_style = ""
313
+ if display_inline is True:
314
+ details_style = "style='display: inline;'"
315
+
316
+ if isinstance(data_in, dict):
317
+ contents, _ = _dict2html_tree(data_in, open_default, fields, max_arr_size)
318
+ elif isinstance(data_in, list):
319
+ contents, _ = _list2html_tree(data_in, open_default, fields, max_arr_size)
320
+ else:
321
+ contents = _item2html_tree("", data_in, open_default, fields, max_arr_size)
322
+ return (
323
+ f"<details {openstr} {details_style}>\n"
324
+ ' <summary style="display:list-item; outline:none;">\n'
325
+ f" <tt>{title}</tt>\n"
326
+ " </summary>\n"
327
+ ' <div style="padding-left:10px; padding-bottom:5px;">\n'
328
+ ' <table style="max-width:100%;">\n'
329
+ f"{contents}\n"
330
+ " </table>\n </div>\n</details>\n"
331
+ )
332
+
333
+
334
+ def _item2html_tree(name, item, open_default, fields, max_arr_size):
335
+ if isinstance(item, (dict, list)):
336
+ _fields = remove_name_from_fields(name, fields)
337
+ if isinstance(item, dict):
338
+ content, size = _dict2html_tree(item, open_default, _fields, max_arr_size)
339
+ else:
340
+ content, size = _list2html_tree(item, open_default, _fields, max_arr_size)
341
+ value = _collaps_item(item, content, open_str(name, open_default, fields))
342
+ if isinstance(name, str):
343
+ name = f"'{name}'"
344
+ name = f"{name} |{size}| :"
345
+ else:
346
+ if isinstance(name, str):
347
+ name = f"'{name}'"
348
+ name = f"{name} :"
349
+ if isinstance(item, str):
350
+ value = f"'{item}'"
351
+ else:
352
+ value = item
353
+ return _add_HTML_row(name, value)
354
+
355
+
356
+ def _add_HTML_row(name, value):
357
+ return (
358
+ f"<tr>"
359
+ f' <td><p style="margin-bottom: 0px; margin-top: 0px;">{name}</p></td>'
360
+ f' <td style="text-align:left;">{value}</td>'
361
+ f"</tr>\n"
362
+ )
363
+
364
+
365
+ def _dict2html_tree(dict_in, open_default, fields, max_arr_size):
366
+ out = ""
367
+ for name, item in dict_in.items():
368
+ out += _item2html_tree(name, item, open_default, fields, max_arr_size)
369
+ return out, len(dict_in)
370
+
371
+
372
+ def _list2html_tree(list_in, open_default, open_fields, max_arr_size):
373
+ out = ""
374
+ if (
375
+ max_arr_size > 0
376
+ and _is_numeric_array(list_in)
377
+ and np.asarray(list_in).size > max_arr_size
378
+ ):
379
+ array = np.asarray(list_in)
380
+ out += _add_HTML_row("min", repr(float(array.min())))
381
+ out += _add_HTML_row("max", repr(float(array.max())))
382
+ size = repr(array.shape).strip("(),")
383
+ else:
384
+
385
+ for iel, el in enumerate(list_in):
386
+ out += _item2html_tree(iel, el, open_default, open_fields, max_arr_size)
387
+ size = len(list_in)
388
+ return out, size
389
+
390
+
391
+ def _is_numeric_array(list_in):
392
+ """Method to test if a `list` or nested `list`'s only contains `float`'s or `int`'s. Testing by casting to an array and check the resulting `.dtype`.
393
+
394
+ Parameters
395
+ ----------
396
+ list_in : Any
397
+ Data to test
398
+
399
+ Returns
400
+ -------
401
+ bool
402
+ Flag, `True` means the list is a `list` or nested `list`'s of numbers.
403
+ """
404
+ try:
405
+ if np.issubdtype(np.asarray(list_in).dtype, np.number):
406
+ return True
407
+ return False
408
+ except:
409
+ return False
410
+
411
+
412
+ def _collaps_item(item, content, open):
413
+ return (
414
+ f"<details {open}>\n"
415
+ ' <summary style="display:list-item; outline:none;">\n'
416
+ f" <tt>{truncate(repr(item), 15)}</tt>\n"
417
+ " </summary>\n"
418
+ ' <div style="padding-left:10px; padding-bottom:5px;">\n'
419
+ '<table style="max-width:100%;">\n'
420
+ f"{content}\n"
421
+ "</table>\n </div>\n</details>\n"
422
+ )
423
+
424
+
425
+ def is_open(name, open_default, fields):
426
+ open = open_default
427
+ if fields is not None and any(
428
+ [(name == el[0]) or (el[0] is True) for el in fields if isinstance(el, list)]
429
+ ):
430
+ return not open
431
+ return open
432
+
433
+
434
+ def open_str(name, open_default, fields):
435
+ open = is_open(name, open_default, fields)
436
+ return " open" if open else ""
437
+
438
+
439
+ def remove_name_from_fields(name, fields):
440
+ if fields is None:
441
+ return None
442
+ out = []
443
+ for el in fields:
444
+ if isinstance(el, list) and ((el[0] == name) or (el[0] is True)):
445
+ if len(el) > 1:
446
+ out.append(el[1:])
447
+ else:
448
+ out.append("")
449
+ else:
450
+ out.append(el)
451
+ return out
452
+
453
+
454
+ # From: https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python
455
+ BLACKLIST = type, ModuleType, FunctionType
456
+
457
+
458
+ def get_data_size(obj):
459
+ """sum size of object & members."""
460
+ if isinstance(obj, BLACKLIST):
461
+ raise TypeError("getsize() does not take argument of type: " + str(type(obj)))
462
+ seen_ids = set()
463
+ size = 0
464
+ objects = [obj]
465
+ while objects:
466
+ need_referents = []
467
+ for obj in objects:
468
+ if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids:
469
+ seen_ids.add(id(obj))
470
+ size += sys.getsizeof(obj)
471
+ need_referents.append(obj)
472
+ objects = get_referents(*need_referents)
473
+ return size
474
+
475
+
476
+ class json_data_render:
477
+ """Converting JSON data to a HTML table with collapsible nested list and dict's
478
+
479
+ Parameters
480
+ ----------
481
+ data_in : dict, list
482
+ JSON compliant dict and list
483
+ open_default : bool, optional
484
+ Flag for default opening or closing collapsible entries, by default False
485
+ fields : list, bool, optional
486
+ list or list of list of names to open or close (opposed to open_default). `True` means that it should open the root - `False` close the root, by default None
487
+ max_arr_size : int, optional
488
+ Maximum size of numeric arrays to render. Using `np.size(array) > max_arr_size`. Default will be determined based on the size of the data, `max_arr_size=[5, 10, 100]` for data with approx. size of [1000, 100, 10] size 100 arrays. Otherwise `max_array_size=-1` which means to render all arrays.
489
+
490
+ Returns
491
+ -------
492
+ str
493
+ Representation of the data as a HTML table with collapsible entries
494
+
495
+ Raises
496
+ ------
497
+ ValueError
498
+ If fields are not a list or None
499
+ """
500
+
501
+ def __init__(self, data_in, open_default=False, fields=None, max_arr_size=None):
502
+ self.open_default = open_default
503
+ self.fields = fields
504
+ self.max_arr_size = max_arr_size
505
+ self.json_data = is_valid_json(data_in, True)
506
+
507
+ def _repr_html_(self):
508
+ return json2html(
509
+ self.json_data, self.open_default, self.fields, self.max_arr_size
510
+ )
511
+
512
+
513
+ def display_json_data(data_in, open_default=False, fields=None, max_arr_size=None):
514
+ """Display json like data as an HTML tree
515
+
516
+ Simple wrapper for:
517
+
518
+ display(json_data_render(json_data))
519
+
520
+ Parameters
521
+ ----------
522
+ data_in : dict, list
523
+ JSON compliant dict and list
524
+ open_default : bool, optional
525
+ Flag for default opening or closing collapsible entries, by default False
526
+ fields : list, optional
527
+ list or list of list of names to open or close (opposed to open_default). `True` means that it should open the root - `False` close the root, by default None
528
+ max_arr_size : int, optional
529
+ Maximum size of numeric arrays to render. Using `np.size(array) > max_arr_size`. Default will be determined based on the size of the data, `max_arr_size=[5, 10, 100]` for data with approx. size of [1000, 100, 10] size 100 arrays. Otherwise `max_array_size=-1` which means to render all arrays.
530
+ """
531
+ from IPython.display import display
532
+
533
+ display(json_data_render(data_in, open_default, fields, max_arr_size))
@@ -0,0 +1,127 @@
1
+ import json
2
+
3
+ import numpy as np
4
+
5
+
6
+ def read_json(filename, asarray=True, **json_load_kwargs):
7
+ """Read a json file. Optionally convert data with list of numbers to numpy array.
8
+
9
+ Simple wrapper for:
10
+
11
+ with open(filename, "r") as file:
12
+ out = json.load(file, object_hook=NpDecode_object_hook if asarray else None)
13
+ return out
14
+
15
+ Parameters
16
+ ----------
17
+ filename : str
18
+ Name of the file to load
19
+ asarray : bool, optional
20
+ Flag for converter list of numbers to numpy array, by default True
21
+
22
+ Returns
23
+ -------
24
+ dist, list
25
+ Data from the json file
26
+ """
27
+ with open(filename, "r") as file:
28
+ out = json.load(
29
+ file,
30
+ object_hook=JSONNumpyDecode_object_hook if asarray else None,
31
+ **json_load_kwargs
32
+ )
33
+ return out
34
+
35
+
36
+ def write_json(filename, data, convert_numpy=True, **json_dump_kwargs):
37
+ """Write JSON compatible data to file. Optionally convert numpy data.
38
+
39
+ Simple wrapper:
40
+
41
+ with open(filename, "w") as file:
42
+ json.dump(data, file, cls=NpEncoder if convert_numpy else None)
43
+
44
+ Parameters
45
+ ----------
46
+ filename : str
47
+ Name of the JSON file to write
48
+ data : dict, list
49
+ Data to be written to file
50
+ convert_numpy : bool, optional
51
+ Flag for converting numpy data as a part of the writing process, by default True
52
+ """
53
+ with open(filename, "w") as file:
54
+ json.dump(
55
+ data,
56
+ file,
57
+ cls=JSONNumpyEncoder if convert_numpy else None,
58
+ **json_dump_kwargs
59
+ )
60
+
61
+
62
+ class JSONNumpyEncoder(json.JSONEncoder):
63
+ """Encodes numpy types to python buildin
64
+
65
+ Usages:
66
+
67
+ with open("data.json", "w") as file:
68
+ out = json.dump(file, cls=NpEncoder)
69
+ """
70
+
71
+ def default(self, obj):
72
+ if isinstance(obj, np.integer):
73
+ return int(obj)
74
+ if isinstance(obj, np.floating):
75
+ return float(obj)
76
+ if isinstance(obj, np.ndarray):
77
+ return obj.tolist()
78
+ if isinstance(obj, np.bool_):
79
+ return bool(obj)
80
+ return super(JSONNumpyEncoder, self).default(obj)
81
+
82
+
83
+ def JSONNumpyDecode_object_hook(obj):
84
+ """JSON `object_hook` to converter list of numbers to numpy arrays
85
+
86
+ Usages:
87
+
88
+ with open("data.json", "r") as file:
89
+ out = json.load(file, object_hook=NpDecode_object_hook)
90
+
91
+ Parameters
92
+ ----------
93
+ obj : dict
94
+ JSON compliant dict
95
+
96
+ Returns
97
+ -------
98
+ dict
99
+ Dict with all list of numbers replaced as numpy arrays
100
+ """
101
+ for name, val in obj.items():
102
+ if isinstance(val, list) and np.issubdtype(np.asarray(val).dtype, np.number):
103
+ obj[name] = np.asarray(val)
104
+ return obj
105
+
106
+
107
+ def is_valid_json(data, allow_numpy=False):
108
+ """Verify if data is JSON valid. Optionally (`allow_numpy=True`) it will allow numpy.
109
+
110
+ Parameters
111
+ ----------
112
+ data : dict, list
113
+ Data to verify if is JSON valid
114
+ allow_numpy : bool, optional
115
+ Flag for allowing numpy data, by default False
116
+
117
+ Returns
118
+ -------
119
+ dict,list
120
+ Returns JSON valid data. (If `allow_numpy=True` numpy data will be converted to lists and build-in data types)
121
+ """
122
+ try:
123
+ return json.loads(
124
+ json.dumps(data, cls=JSONNumpyEncoder if allow_numpy else None)
125
+ )
126
+ except:
127
+ return False