sdata 1.5.0__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.
Files changed (98) hide show
  1. sdata/__init__.py +140 -0
  2. sdata/base.py +684 -0
  3. sdata/contrib/__init__.py +0 -0
  4. sdata/contrib/piexif/__init__.py +12 -0
  5. sdata/contrib/piexif/_common.py +94 -0
  6. sdata/contrib/piexif/_dump.py +346 -0
  7. sdata/contrib/piexif/_exceptions.py +2 -0
  8. sdata/contrib/piexif/_exif.py +638 -0
  9. sdata/contrib/piexif/_insert.py +60 -0
  10. sdata/contrib/piexif/_load.py +270 -0
  11. sdata/contrib/piexif/_remove.py +56 -0
  12. sdata/contrib/piexif/_transplant.py +45 -0
  13. sdata/contrib/piexif/_webp.py +240 -0
  14. sdata/contrib/piexif/helper.py +66 -0
  15. sdata/contrib/ranger/__init__.py +8 -0
  16. sdata/contrib/ranger/collections/__init__.py +0 -0
  17. sdata/contrib/ranger/collections/rangebucketmap.py +346 -0
  18. sdata/contrib/ranger/collections/rangemap.py +396 -0
  19. sdata/contrib/ranger/collections/rangeset.py +483 -0
  20. sdata/contrib/ranger/range/__init__.py +0 -0
  21. sdata/contrib/ranger/range/cut.py +285 -0
  22. sdata/contrib/ranger/range/range.py +644 -0
  23. sdata/contrib/sobol_seq.py +394 -0
  24. sdata/contrib/sortedcontainers/LICENSE +13 -0
  25. sdata/contrib/sortedcontainers/__init__.py +74 -0
  26. sdata/contrib/sortedcontainers/sorteddict.py +789 -0
  27. sdata/contrib/sortedcontainers/sortedlist.py +2646 -0
  28. sdata/contrib/sortedcontainers/sortedset.py +733 -0
  29. sdata/contrib/sqlitedict.py +598 -0
  30. sdata/contrib/timeflake/__init__.py +40 -0
  31. sdata/contrib/timeflake/flake.py +69 -0
  32. sdata/contrib/timeflake/utils.py +47 -0
  33. sdata/deprecated/__init__.py +10 -0
  34. sdata/deprecated/data.py +1503 -0
  35. sdata/did/__init__.py +129 -0
  36. sdata/did/_http.py +67 -0
  37. sdata/did/base58btc.py +49 -0
  38. sdata/did/did_github.py +152 -0
  39. sdata/did/did_peer4.py +155 -0
  40. sdata/did/did_web.py +222 -0
  41. sdata/did/diddoc.py +75 -0
  42. sdata/did/ed25519.py +225 -0
  43. sdata/did/eddsa.py +107 -0
  44. sdata/did/errors.py +40 -0
  45. sdata/did/issue_vc.py +193 -0
  46. sdata/did/jose.py +126 -0
  47. sdata/did/keys.py +104 -0
  48. sdata/did/utils_didkey.py +161 -0
  49. sdata/did/verify_vp.py +158 -0
  50. sdata/doe.py +101 -0
  51. sdata/dtypes.py +510 -0
  52. sdata/experiments/__init__.py +331 -0
  53. sdata/experiments/blob0.py +131 -0
  54. sdata/experiments/file.py +42 -0
  55. sdata/experiments/filegroup.py +144 -0
  56. sdata/experiments/image_old.py +313 -0
  57. sdata/experiments/ks2.py +15 -0
  58. sdata/experiments/lapshear.py +8 -0
  59. sdata/experiments/material.py +7 -0
  60. sdata/experiments/parameters_deprecated.py +394 -0
  61. sdata/experiments/workbook.py +226 -0
  62. sdata/format.py +125 -0
  63. sdata/imagemeta.py +533 -0
  64. sdata/interactive.py +118 -0
  65. sdata/iolib/__init__.py +51 -0
  66. sdata/iolib/hashtree.py +264 -0
  67. sdata/iolib/json1sqlitestore.py +554 -0
  68. sdata/iolib/jsonsqlitestore.py +704 -0
  69. sdata/iolib/pud.py +242 -0
  70. sdata/iolib/reader.py +262 -0
  71. sdata/iolib/writer.py +419 -0
  72. sdata/metadata.py +882 -0
  73. sdata/parameter.py +414 -0
  74. sdata/schema.py +273 -0
  75. sdata/sclass/__init__.py +111 -0
  76. sdata/sclass/bfo_classes.py +362 -0
  77. sdata/sclass/blob.py +362 -0
  78. sdata/sclass/content.py +87 -0
  79. sdata/sclass/dataframe.py +1251 -0
  80. sdata/sclass/dataframegroup.py +187 -0
  81. sdata/sclass/dependency_graph.py +85 -0
  82. sdata/sclass/filereference.py +124 -0
  83. sdata/sclass/image.py +218 -0
  84. sdata/sclass/lazy_namespace.py +155 -0
  85. sdata/sclass/process.py +383 -0
  86. sdata/sclass/process_graph.py +221 -0
  87. sdata/sclass/zipfile.py +135 -0
  88. sdata/semantic.py +346 -0
  89. sdata/suuid.py +136 -0
  90. sdata/timestamp.py +336 -0
  91. sdata/tools.py +14 -0
  92. sdata/units.py +602 -0
  93. sdata/vocab.py +149 -0
  94. sdata-1.5.0.dist-info/METADATA +264 -0
  95. sdata-1.5.0.dist-info/RECORD +98 -0
  96. sdata-1.5.0.dist-info/WHEEL +5 -0
  97. sdata-1.5.0.dist-info/licenses/LICENSE-MIT +21 -0
  98. sdata-1.5.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,394 @@
1
+ import json
2
+ from typing import Dict, Optional, Tuple, List, Union
3
+ import random
4
+
5
+
6
+ class Distribution:
7
+ def __init__(self, name: str, **params):
8
+ """
9
+ Unified distribution object to encapsulate name and _parameter.
10
+
11
+ :param name: Name of the distribution (e.g., 'normal', 'uniform').
12
+ :param params: Parameters specific to the distribution.
13
+ """
14
+ self.name = name
15
+ self.params = params
16
+
17
+ def to_dict(self) -> Dict:
18
+ """Convert the distribution to a dictionary."""
19
+ return {
20
+ "name": self.name,
21
+ "params": self.params
22
+ }
23
+
24
+ @classmethod
25
+ def from_dict(cls, data: Dict):
26
+ """Create a Distribution instance from a dictionary."""
27
+ return cls(name=data["name"], **data.get("params", {}))
28
+
29
+ def generate_value(self, range: Union[Tuple[float, float], List[Union[int, str]]]) -> Union[float, int, str]:
30
+ """
31
+ Generate a value based on the distribution within the specified range.
32
+
33
+ :param range: Tuple specifying the minimum and maximum values or a list of discrete options.
34
+ :return: Generated value.
35
+ """
36
+ if isinstance(range, list):
37
+ return random.choice(range)
38
+
39
+ min_val, max_val = range
40
+
41
+ if self.name == "normal":
42
+ mean = self.params.get("mean", (min_val + max_val) / 2)
43
+ std_dev = self.params.get("std_dev", (max_val - min_val) / 6)
44
+ return max(min(random.gauss(mean, std_dev), max_val), min_val)
45
+
46
+ elif self.name == "truncated_gauss":
47
+ mean = self.params.get("mean", (min_val + max_val) / 2)
48
+ std_dev = self.params.get("std_dev", (max_val - min_val) / 6)
49
+ value = random.gauss(mean, std_dev)
50
+ while not (min_val <= value <= max_val):
51
+ value = random.gauss(mean, std_dev)
52
+ return value
53
+
54
+ elif self.name == "weibull":
55
+ scale = self.params.get("scale", (max_val - min_val) / 2)
56
+ shape = self.params.get("shape", 1.5)
57
+ return max(min(min_val + random.weibullvariate(scale, shape), max_val), min_val)
58
+
59
+ elif self.name == "uniform":
60
+ return random.uniform(min_val, max_val)
61
+
62
+ elif self.name == "exponential":
63
+ rate = self.params.get("rate", 1.0)
64
+ return max(min_val, min(random.expovariate(rate), max_val))
65
+
66
+ elif self.name == "lognormal":
67
+ mean = self.params.get("mean", (min_val + max_val) / 2)
68
+ sigma = self.params.get("sigma", (max_val - min_val) / 6)
69
+ return max(min_val, min(random.lognormvariate(mean, sigma), max_val))
70
+
71
+ elif self.name == "beta":
72
+ alpha = self.params.get("alpha", 2.0)
73
+ beta = self.params.get("beta", 5.0)
74
+ return min_val + (random.betavariate(alpha, beta) * (max_val - min_val))
75
+
76
+ elif self.name == "gamma":
77
+ shape = self.params.get("shape", 2.0)
78
+ scale = self.params.get("scale", 1.0)
79
+ return max(min_val, min(random.gammavariate(shape, scale), max_val))
80
+
81
+ elif self.name == "cauchy":
82
+ location = self.params.get("location", (min_val + max_val) / 2)
83
+ scale = self.params.get("scale", (max_val - min_val) / 4)
84
+ value = random.uniform(location - scale, location + scale)
85
+ return max(min_val, min(value, max_val))
86
+
87
+ else:
88
+ raise ValueError(f"Unsupported distribution: {self.name}")
89
+
90
+
91
+ class Parameter:
92
+ def __init__(self, name: str,
93
+ value: Union[float, int, str],
94
+ range: Optional[Union[Tuple[float, float], List[Union[int, str]]]] = None,
95
+ distribution: Optional[Distribution] = None,
96
+ type: Optional[str] = None,
97
+ description: Optional[str] = None,
98
+ discrete_values: Optional[List[Union[int, str]]] = None,
99
+ constant: Optional[bool] = False, ):
100
+ """
101
+ Unified class for a parameter.
102
+
103
+ :param name: Name of the parameter
104
+ :param value: Value of the parameter
105
+ :param range: Range of the parameter (tuple or list, required for Variables or DiscreteVariables)
106
+ :param distribution: Distribution object for the parameter (optional)
107
+ :param type: Type of the parameter ("Constant", "Variable", or "DiscreteVariable")
108
+ :param description: Description of the parameter (optional)
109
+ :param discrete_values: Discrete values for "DiscreteVariable" type (optional)
110
+ """
111
+ self.name = name
112
+ self.value = value
113
+ self.range = range
114
+ self.distribution = distribution
115
+ self.description = description
116
+ self.discrete_values = discrete_values
117
+ self.constant = constant
118
+
119
+ if type:
120
+ self.type = type
121
+ else:
122
+ if range is not None and isinstance(range, list):
123
+ self.type = "DiscreteVariable"
124
+ self.discrete_values = range
125
+ self.range = None
126
+ elif range is not None:
127
+ self.type = "Variable"
128
+ else:
129
+ self.type = "Constant"
130
+
131
+ if self.type == "Variable" and not self.distribution:
132
+ self.distribution = Distribution("uniform")
133
+
134
+ @property
135
+ def min(self):
136
+ if isinstance(self.range, (list, tuple)):
137
+ return self.range[0]
138
+ raise ValueError("min is only available for continuous ranges")
139
+
140
+ @property
141
+ def max(self):
142
+ if isinstance(self.range, (list, tuple)):
143
+ return self.range[1]
144
+ raise ValueError("max is only available for continuous ranges")
145
+
146
+ def set_type(self, new_type: str):
147
+ """
148
+ Change the type of the parameter to "Constant", "Variable", or "DiscreteVariable".
149
+
150
+ :param new_type: The new type to set ("Constant", "Variable", or "DiscreteVariable").
151
+ """
152
+ if new_type not in ["Constant", "Variable", "DiscreteVariable"]:
153
+ raise ValueError("Type must be 'Constant', 'Variable', or 'DiscreteVariable'")
154
+
155
+ self.type = new_type
156
+
157
+ if self.type == "Constant":
158
+ self.range = None
159
+ self.distribution = None
160
+ self.discrete_values = None
161
+ elif self.type == "Variable" and not self.distribution:
162
+ self.distribution = Distribution("uniform")
163
+ self.discrete_values = None
164
+ elif self.type == "DiscreteVariable":
165
+ self.range = None
166
+
167
+ def to_dict(self) -> Dict:
168
+ """Convert the parameter to a dictionary."""
169
+ return {
170
+ "name": self.name,
171
+ "value": self.value,
172
+ "range": self.range,
173
+ "type": self.type,
174
+ "description": self.description,
175
+ "discrete_values": self.discrete_values,
176
+ "distribution": self.distribution.to_dict() if self.distribution else None
177
+ }
178
+
179
+ @classmethod
180
+ def from_dict(cls, data: Dict):
181
+ """Create a Parameter instance from a dictionary."""
182
+ distribution = None
183
+ if data.get("distribution"):
184
+ distribution = Distribution.from_dict(data["distribution"])
185
+ return cls(
186
+ name=data["name"],
187
+ value=data["value"],
188
+ range=data.get("range"),
189
+ distribution=distribution,
190
+ type=data.get("type"),
191
+ description=data.get("description"),
192
+ discrete_values=data.get("discrete_values")
193
+ )
194
+
195
+ def to_json(self) -> str:
196
+ """Serialize the parameter to a JSON string."""
197
+ return json.dumps(self.to_dict(), indent=4)
198
+
199
+ @classmethod
200
+ def from_json(cls, json_str: str):
201
+ """Create a Parameter instance from a JSON string."""
202
+ data = json.loads(json_str)
203
+ return cls.from_dict(data)
204
+
205
+ def sample_value(self) -> Union[float, int, str]:
206
+ """
207
+ Sample and update the value based on the defined distribution.
208
+ """
209
+ if self.type == "Constant":
210
+ return self.value
211
+ elif self.type == "DiscreteVariable":
212
+ self.value = random.choice(self.discrete_values)
213
+ return self.value
214
+ self.value = self.distribution.generate_value(self.range)
215
+ return self.value
216
+
217
+ def sample_values(self, n: int) -> List[Union[float, int, str]]:
218
+ """
219
+ Generate n sampled values based on the defined distribution.
220
+ """
221
+ if self.type == "Constant":
222
+ return [self.value] * n
223
+ elif self.type == "DiscreteVariable":
224
+ return [random.choice(self.discrete_values) for _ in range(n)]
225
+ return [self.distribution.generate_value(self.range) for _ in range(n)]
226
+
227
+ def __repr__(self):
228
+ try:
229
+ value_range = f"{self.min:.2g},{self.max:.2g}"
230
+ except:
231
+ if self.discrete_values and len(self.discrete_values) > 4:
232
+ value_range = self.discrete_values[:4] + ["..."]
233
+ elif self.discrete_values:
234
+ value_range = self.discrete_values
235
+ else:
236
+ value_range = "None"
237
+ return f"({self.name}|{self.value}|[{value_range}]|{self.type})"
238
+
239
+ def __str__(self):
240
+ return self.__repr__()
241
+
242
+
243
+ class ParameterSet:
244
+ def __init__(self, name=None):
245
+ """
246
+ ParameterSet class to hold multiple _parameter in a dictionary.
247
+ """
248
+ self.name = name or "N.N."
249
+ self._parameter = {}
250
+
251
+ @property
252
+ def parameters(self):
253
+ return self._parameter
254
+
255
+ def update(self, parameter_list):
256
+ """
257
+
258
+ """
259
+ for parameter in parameter_list:
260
+ self._parameter[parameter.name] = parameter
261
+
262
+ def __getitem__(self, name):
263
+ return self.get(name)
264
+
265
+ def __contains__(self, item):
266
+ return item in self._parameter.keys()
267
+
268
+ def pop(self, pname):
269
+ try:
270
+ return self._parameter.pop(pname)
271
+ except KeyError as exp:
272
+ return None
273
+
274
+ def __iter__(self):
275
+ for x in self._parameter.values():
276
+ yield x
277
+
278
+ def items(self):
279
+ """
280
+ Provide a dict-like items view for parameters.
281
+
282
+ :return: Items view of parameters.
283
+ """
284
+ return self._parameter.items()
285
+
286
+ def keys(self):
287
+ """
288
+ Provide a dict-like keys view for parameters.
289
+
290
+ :return: Keys view of parameters.
291
+ """
292
+ return self._parameter.keys()
293
+
294
+ def values(self):
295
+ """
296
+ Provide a dict-like values view for parameters.
297
+
298
+ :return: Values view of parameters.
299
+ """
300
+ return self._parameter.values()
301
+
302
+ def get(self, name, default=None):
303
+ if self._parameter.get(name) is not None:
304
+ return self._parameter.get(name)
305
+ else:
306
+ return default
307
+ def set(self, parameter: Parameter):
308
+ """
309
+ Add a parameter to the set.
310
+
311
+ :param parameter: A Parameter object to add.
312
+ """
313
+ self._parameter[parameter.name] = parameter
314
+
315
+ def add_parameters(self, parameter_list: List):
316
+ """
317
+ Add a parameter to the set.
318
+
319
+ :param parameter: A Parameter object to add.
320
+ """
321
+ for parameter in parameter_list:
322
+ self._parameter[parameter.name] = parameter
323
+
324
+ def to_dict(self) -> Dict[str, Dict]:
325
+ """
326
+ Convert the entire parameter set to a dictionary.
327
+
328
+ :return: A dictionary of parameter dictionaries.
329
+ """
330
+ d = {"name": self.name}
331
+ d["parameter"] = {pname: param.to_dict() for pname, param in self._parameter.items()}
332
+ return d
333
+
334
+ @classmethod
335
+ def from_dict(cls, data: Dict):
336
+ """
337
+ Create a ParameterSet instance from a dictionary.
338
+
339
+ :param data: A dictionary containing parameter set data.
340
+ :return: A ParameterSet instance.
341
+ """
342
+ instance = cls(name=data.get("name", "N.N."))
343
+ parameters = data.get("parameter", {})
344
+ for pname, param_data in parameters.items():
345
+ parameter = Parameter.from_dict(param_data) # Assuming Parameter has a from_dict method
346
+ instance.set(parameter)
347
+ return instance
348
+
349
+ def to_json(self) -> str:
350
+ """
351
+ Convert the ParameterSet to a JSON string.
352
+
353
+ :return: JSON string representation of the ParameterSet.
354
+ """
355
+ import json
356
+ return json.dumps(self.to_dict())
357
+
358
+ @classmethod
359
+ def from_json(cls, json_str: str):
360
+ """
361
+ Create a ParameterSet instance from a JSON string.
362
+
363
+ :param json_str: JSON string containing parameter set data.
364
+ :return: A ParameterSet instance.
365
+ """
366
+ import json
367
+ data = json.loads(json_str)
368
+ return cls.from_dict(data)
369
+
370
+ def print(self):
371
+ for pname in sorted(self._parameter.keys()):
372
+ print(self._parameter[pname])
373
+
374
+ def __repr__(self):
375
+ return f"ParameterSet({self.name}|{list(self._parameter.keys())})"
376
+
377
+ def __str__(self):
378
+ return self.__repr__()
379
+
380
+
381
+ if __name__ == '__main__':
382
+ # Example usage
383
+ param_constant = Parameter(name="constant_param", value=10.0, description="This is a constant parameter.")
384
+ param_variable = Parameter(name="variable_param", value=5.0, range=(0.0, 10.0),
385
+ description="This is a variable parameter.")
386
+ param_discrete = Parameter(name="discrete_param", value="a", range=["a", "b", "c"],
387
+ description="This is a discrete parameter.")
388
+
389
+ print(param_constant.to_json())
390
+ print(param_variable.to_json())
391
+ print(param_discrete.to_json())
392
+
393
+ print(param_variable.sample_values(5))
394
+ print(param_discrete.sample_values(5))
@@ -0,0 +1,226 @@
1
+ # -*-coding: utf-8-*-
2
+
3
+ import logging
4
+
5
+ logger = logging.getLogger("sdata")
6
+ import collections
7
+ import pandas as pd
8
+ import numpy as np
9
+ from sdata.timestamp import TimeStamp
10
+ import sdata
11
+ from sdata.deprecated.data import Data
12
+ from sdata.metadata import Metadata, Attribute
13
+ import json
14
+ import os
15
+ import hashlib
16
+ import uuid
17
+
18
+
19
+ class Workbook(Data):
20
+ """Workbook with Sheets
21
+
22
+ .. warning::
23
+
24
+ highly experimental"""
25
+
26
+ def __init__(self, **kwargs):
27
+ """Workbook with Sheets
28
+
29
+ :param name:
30
+ :param kwargs:
31
+
32
+ """
33
+ Data.__init__(self, **kwargs)
34
+
35
+ self._sheets = collections.OrderedDict()
36
+
37
+ def create_sheet(self, name):
38
+ """create a sheet to the Workbook
39
+
40
+ :param data:
41
+ :return: sdata.Data
42
+ """
43
+ if not isinstance(name, str):
44
+ logger.error("{}.create_sheet: sheet name has to be a string!".format(self.__class__.__name__))
45
+ return
46
+ data = Data(name=name)
47
+ self._sheets[name] = data
48
+ return data
49
+
50
+ def add_sheet(self, data):
51
+ """create a sheet to the Workbook
52
+
53
+ :param data:
54
+ :return: sdata.Data
55
+ """
56
+ if isinstance(data, (Data, sdata.Data)):
57
+ self._sheets[data.name] = data
58
+ else:
59
+ logger.error("{}.add_sheet: need sdata.Data, got {}".format(self.__class__.__name__, type(data)))
60
+
61
+ @property
62
+ def sheetnames(self):
63
+ """return sheet names of the workbook"""
64
+ return list(self._sheets.keys())
65
+
66
+ def get_sheet(self, name, default=None):
67
+ """get Sheet from Workbook
68
+
69
+ :param name:
70
+ :return: sheet data
71
+ """
72
+ return self._sheets.get(name, default)
73
+
74
+ @property
75
+ def sheets(self):
76
+ """all sheets of the workbook"""
77
+ return list(self._sheets.values())
78
+
79
+ def __getitem__(self, name):
80
+ return self.get(name)
81
+
82
+ def __iter__(self):
83
+ """
84
+
85
+ :return:
86
+ """
87
+ self._isheet = 0
88
+ return self
89
+
90
+ def __next__(self):
91
+ """
92
+
93
+ :return:
94
+ """
95
+ if self._isheet <= (len(self._sheets.keys()) - 1):
96
+ self._isheet += 1
97
+ return self._sheets.get(list(self._sheets.keys())[self._isheet - 1])
98
+ else:
99
+ raise StopIteration
100
+
101
+ def get(self, name, default=None):
102
+ if self.get_sheet(name) is not None:
103
+ return self.get_sheet(name)
104
+ else:
105
+ return default
106
+
107
+ def keys(self):
108
+ """
109
+
110
+ :return: list of Attribute names
111
+ """
112
+ return list(self._sheets.keys())
113
+
114
+ def values(self):
115
+ """
116
+
117
+ :return: list of Attribute values
118
+ """
119
+ return list(self._sheets.values())
120
+
121
+ def items(self):
122
+ """
123
+
124
+ :return: list of Attribute items (keys, values)
125
+ """
126
+ return list(self._sheets.items())
127
+
128
+ def to_hdf5(self, filepath, **kwargs):
129
+ """export sdata.Data to hdf5
130
+
131
+ :param filepath:
132
+ :param complib: default='zlib' ['zlib', 'lzo', 'bzip2', 'blosc', 'blosc:blosclz', 'blosc:lz4', 'blosc:lz4hc', 'blosc:snappy', 'blosc:zlib', 'blosc:zstd']
133
+ :param complevel: default=9 [0-9]
134
+
135
+ :return:
136
+ """
137
+ if not isinstance(self.df, pd.DataFrame):
138
+ df = pd.DataFrame()
139
+ else:
140
+ df = self.df
141
+ kwargs["mode"] = "w"
142
+ if kwargs.get("complib") is None:
143
+ kwargs["complib"] = "zlib"
144
+
145
+ if kwargs.get("complevel") is None:
146
+ kwargs["complevel"] = 9
147
+
148
+ with pd.HDFStore(filepath, **kwargs) as hdf:
149
+ hdf.put('metadata', self.metadata.df, format='fixed', data_columns=True)
150
+ hdf.put('table', df, format='fixed', data_columns=True)
151
+ hdf.put('description', self.description_to_df(), format='fixed', data_columns=True)
152
+
153
+ for sheet in self.sheets:
154
+ if not isinstance(sheet.df, pd.DataFrame):
155
+ logger.warning("no df in sheet!")
156
+ df = pd.DataFrame()
157
+ else:
158
+ df = sheet.df
159
+ hdf.put(f'/sheets/uuid_{sheet.uuid}/metadata', sheet.metadata.df, format='fixed', data_columns=True)
160
+ hdf.put(f'/sheets/uuid_{sheet.uuid}/table', df, format='fixed', data_columns=True)
161
+ hdf.put(f'/sheets/uuid_{sheet.uuid}/description', sheet.description_to_df(), format='fixed',
162
+ data_columns=True)
163
+
164
+ @classmethod
165
+ def metadata_from_hdf5(cls, filepath, **kwargs):
166
+ """import sdata.Data.Metadata from hdf5
167
+
168
+ :param filepath:
169
+ :return: sdata.Data
170
+ """
171
+ if not os.path.exists:
172
+ logger.error("hdf5 file '{}' not available".format(filepath))
173
+ return
174
+
175
+ with pd.HDFStore(filepath, mode="r+") as hdf:
176
+ metadata_path = "/metadata".format(uuid)
177
+ df_metadata = hdf.get(metadata_path)
178
+ metadata = Metadata.from_dataframe(df_metadata)
179
+ return metadata
180
+
181
+ @classmethod
182
+ def from_hdf5(cls, filepath, **kwargs):
183
+ """import sdata.Data from hdf5
184
+
185
+ :param filepath:
186
+ :return: sdata.Data
187
+ """
188
+ if not os.path.exists:
189
+ logger.error("hdf5 file '{}' not available".format(filepath))
190
+ return
191
+
192
+ def read_data(nodepath):
193
+ metadata_path = f"{nodepath}/metadata".format(uuid)
194
+ table_path = f"{nodepath}/table".format(uuid)
195
+ description_path = f"{nodepath}/description".format(uuid)
196
+ df_metadata = hdf.get(metadata_path)
197
+ # print(df_metadata)
198
+ df_table = hdf.get(table_path)
199
+ df_description = hdf.get(description_path)
200
+ metadata = Metadata.from_dataframe(df_metadata)
201
+ # logger.debug("hdf {}".format(metadata.get("!sdata_uuid").value))
202
+ sheetdata = Data(metadata=metadata, table=df_table)
203
+ sheetdata.metadata = metadata
204
+ sheetdata.description_from_df(df_description)
205
+ # print(sheetdata.df)
206
+ return sheetdata
207
+
208
+ with pd.HDFStore(filepath, mode="r+") as hdf:
209
+ metadata_path = "/metadata".format(uuid)
210
+ table_path = "/table".format(uuid)
211
+ description_path = "/description".format(uuid)
212
+ df_metadata = hdf.get(metadata_path)
213
+ df_table = hdf.get(table_path)
214
+ df_description = hdf.get(description_path)
215
+ metadata = Metadata.from_dataframe(df_metadata)
216
+ # logger.debug("hdf {}".format(metadata.get("!sdata_uuid").value))
217
+ wb = Workbook(metadata=metadata, table=df_table)
218
+ wb.metadata = metadata
219
+ wb.description_from_df(df_description)
220
+ s = hdf.get_node("/sheets")
221
+ for g in s._v_groups:
222
+ # print(g)
223
+ nodepath = f"/sheets/{g}"
224
+ sheetdata = read_data(nodepath)
225
+ wb.add_sheet(sheetdata)
226
+ return wb