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.
- sdata/__init__.py +140 -0
- sdata/base.py +684 -0
- sdata/contrib/__init__.py +0 -0
- sdata/contrib/piexif/__init__.py +12 -0
- sdata/contrib/piexif/_common.py +94 -0
- sdata/contrib/piexif/_dump.py +346 -0
- sdata/contrib/piexif/_exceptions.py +2 -0
- sdata/contrib/piexif/_exif.py +638 -0
- sdata/contrib/piexif/_insert.py +60 -0
- sdata/contrib/piexif/_load.py +270 -0
- sdata/contrib/piexif/_remove.py +56 -0
- sdata/contrib/piexif/_transplant.py +45 -0
- sdata/contrib/piexif/_webp.py +240 -0
- sdata/contrib/piexif/helper.py +66 -0
- sdata/contrib/ranger/__init__.py +8 -0
- sdata/contrib/ranger/collections/__init__.py +0 -0
- sdata/contrib/ranger/collections/rangebucketmap.py +346 -0
- sdata/contrib/ranger/collections/rangemap.py +396 -0
- sdata/contrib/ranger/collections/rangeset.py +483 -0
- sdata/contrib/ranger/range/__init__.py +0 -0
- sdata/contrib/ranger/range/cut.py +285 -0
- sdata/contrib/ranger/range/range.py +644 -0
- sdata/contrib/sobol_seq.py +394 -0
- sdata/contrib/sortedcontainers/LICENSE +13 -0
- sdata/contrib/sortedcontainers/__init__.py +74 -0
- sdata/contrib/sortedcontainers/sorteddict.py +789 -0
- sdata/contrib/sortedcontainers/sortedlist.py +2646 -0
- sdata/contrib/sortedcontainers/sortedset.py +733 -0
- sdata/contrib/sqlitedict.py +598 -0
- sdata/contrib/timeflake/__init__.py +40 -0
- sdata/contrib/timeflake/flake.py +69 -0
- sdata/contrib/timeflake/utils.py +47 -0
- sdata/deprecated/__init__.py +10 -0
- sdata/deprecated/data.py +1503 -0
- sdata/did/__init__.py +129 -0
- sdata/did/_http.py +67 -0
- sdata/did/base58btc.py +49 -0
- sdata/did/did_github.py +152 -0
- sdata/did/did_peer4.py +155 -0
- sdata/did/did_web.py +222 -0
- sdata/did/diddoc.py +75 -0
- sdata/did/ed25519.py +225 -0
- sdata/did/eddsa.py +107 -0
- sdata/did/errors.py +40 -0
- sdata/did/issue_vc.py +193 -0
- sdata/did/jose.py +126 -0
- sdata/did/keys.py +104 -0
- sdata/did/utils_didkey.py +161 -0
- sdata/did/verify_vp.py +158 -0
- sdata/doe.py +101 -0
- sdata/dtypes.py +510 -0
- sdata/experiments/__init__.py +331 -0
- sdata/experiments/blob0.py +131 -0
- sdata/experiments/file.py +42 -0
- sdata/experiments/filegroup.py +144 -0
- sdata/experiments/image_old.py +313 -0
- sdata/experiments/ks2.py +15 -0
- sdata/experiments/lapshear.py +8 -0
- sdata/experiments/material.py +7 -0
- sdata/experiments/parameters_deprecated.py +394 -0
- sdata/experiments/workbook.py +226 -0
- sdata/format.py +125 -0
- sdata/imagemeta.py +533 -0
- sdata/interactive.py +118 -0
- sdata/iolib/__init__.py +51 -0
- sdata/iolib/hashtree.py +264 -0
- sdata/iolib/json1sqlitestore.py +554 -0
- sdata/iolib/jsonsqlitestore.py +704 -0
- sdata/iolib/pud.py +242 -0
- sdata/iolib/reader.py +262 -0
- sdata/iolib/writer.py +419 -0
- sdata/metadata.py +882 -0
- sdata/parameter.py +414 -0
- sdata/schema.py +273 -0
- sdata/sclass/__init__.py +111 -0
- sdata/sclass/bfo_classes.py +362 -0
- sdata/sclass/blob.py +362 -0
- sdata/sclass/content.py +87 -0
- sdata/sclass/dataframe.py +1251 -0
- sdata/sclass/dataframegroup.py +187 -0
- sdata/sclass/dependency_graph.py +85 -0
- sdata/sclass/filereference.py +124 -0
- sdata/sclass/image.py +218 -0
- sdata/sclass/lazy_namespace.py +155 -0
- sdata/sclass/process.py +383 -0
- sdata/sclass/process_graph.py +221 -0
- sdata/sclass/zipfile.py +135 -0
- sdata/semantic.py +346 -0
- sdata/suuid.py +136 -0
- sdata/timestamp.py +336 -0
- sdata/tools.py +14 -0
- sdata/units.py +602 -0
- sdata/vocab.py +149 -0
- sdata-1.5.0.dist-info/METADATA +264 -0
- sdata-1.5.0.dist-info/RECORD +98 -0
- sdata-1.5.0.dist-info/WHEEL +5 -0
- sdata-1.5.0.dist-info/licenses/LICENSE-MIT +21 -0
- sdata-1.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import logging
|
|
3
|
+
import collections
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import numpy as np
|
|
6
|
+
from sdata.timestamp import TimeStamp
|
|
7
|
+
from sdata.deprecated.data import Data
|
|
8
|
+
from sdata.suuid import SUUID
|
|
9
|
+
from sdata.metadata import Metadata, Attribute
|
|
10
|
+
import sdata.contrib
|
|
11
|
+
import sdata.contrib.piexif
|
|
12
|
+
import sdata.contrib.piexif.helper
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
from io import BytesIO
|
|
16
|
+
import base64
|
|
17
|
+
import hashlib
|
|
18
|
+
try:
|
|
19
|
+
import PIL
|
|
20
|
+
except:
|
|
21
|
+
logging.warning("PIL is not available -> no image import")
|
|
22
|
+
PIL = None
|
|
23
|
+
|
|
24
|
+
class Image(Data):
|
|
25
|
+
"""Image Object
|
|
26
|
+
|
|
27
|
+
.. warning::
|
|
28
|
+
|
|
29
|
+
highly experimental"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def __init__(self, url, **kwargs):
|
|
33
|
+
"""Image Object"""
|
|
34
|
+
|
|
35
|
+
# url = kwargs.get("url", "")
|
|
36
|
+
load = kwargs.get("load", False)
|
|
37
|
+
try:
|
|
38
|
+
name = os.path.basename(url)
|
|
39
|
+
except Exception as exp:
|
|
40
|
+
name = None
|
|
41
|
+
if "name" not in kwargs:
|
|
42
|
+
kwargs["name"] = name
|
|
43
|
+
Data.__init__(self, **kwargs)
|
|
44
|
+
self.url = url
|
|
45
|
+
self.img = None
|
|
46
|
+
if load is True:
|
|
47
|
+
self.load()
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def _from_filepath(cls, filepath, **kwargs):
|
|
51
|
+
"""read image from file
|
|
52
|
+
|
|
53
|
+
:param fielpath: image file path
|
|
54
|
+
:return: sdata.Image
|
|
55
|
+
"""
|
|
56
|
+
project = kwargs.get("project")
|
|
57
|
+
suuid = SUUID.from_file(cls.__class__.__name__, filepath, ns_name=project)
|
|
58
|
+
kwargs["uuid"] = suuid.huuid
|
|
59
|
+
kwargs["url"] = filepath
|
|
60
|
+
data = cls(name=os.path.basename(filepath), **kwargs)
|
|
61
|
+
return data
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def from_image(cls, name, img, **kwargs):
|
|
65
|
+
"""read image from PIL.Image
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
project = kwargs.get("project", "")
|
|
69
|
+
parent = kwargs.get("parent", "")
|
|
70
|
+
class_name = "Image" #cls.__class__.__name__
|
|
71
|
+
|
|
72
|
+
sh = hashlib.sha3_256()
|
|
73
|
+
sh.update(img.tobytes())
|
|
74
|
+
suuid = SUUID.from_name(class_name=class_name, name=sh.hexdigest(), ns_name=project)
|
|
75
|
+
suuid.project = project
|
|
76
|
+
kwargs["parent"] = parent
|
|
77
|
+
kwargs["project"] = suuid.project
|
|
78
|
+
kwargs["sname"] = suuid.sname
|
|
79
|
+
kwargs["uuid"] = suuid.huuid
|
|
80
|
+
kwargs["suuid"] = suuid.idstr
|
|
81
|
+
kwargs["url"] = sdata.osname(name)
|
|
82
|
+
# name = os.path.basename(filepath)
|
|
83
|
+
data = cls(name=name, **kwargs)
|
|
84
|
+
data.img = img
|
|
85
|
+
return data
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def from_bytes(cls, name, image_data, **kwargs):
|
|
90
|
+
"""read image from file
|
|
91
|
+
|
|
92
|
+
"""
|
|
93
|
+
project = kwargs.get("project")
|
|
94
|
+
class_name = "Image" #cls.__class__.__name__
|
|
95
|
+
suuid = SUUID.from_str(class_name, name, ns_name=project)
|
|
96
|
+
kwargs["sname"] = suuid.sname
|
|
97
|
+
kwargs["uuid"] = suuid.huuid
|
|
98
|
+
kwargs["suuid"] = suuid.idstr
|
|
99
|
+
kwargs["url"] = name
|
|
100
|
+
data = cls(name=name, **kwargs)
|
|
101
|
+
data.img = PIL.Image.open(BytesIO(image_data))
|
|
102
|
+
try:
|
|
103
|
+
d = None
|
|
104
|
+
if name.lower().endswith(".png"):
|
|
105
|
+
d = cls._get_png_metadata(image_data)
|
|
106
|
+
elif name.lower().endswith(("jpg", "jpeg")):
|
|
107
|
+
d = cls._get_jpg_metadata(image_data)
|
|
108
|
+
if d is not None:
|
|
109
|
+
data.metadata = data.metadata.from_json(d)
|
|
110
|
+
except:
|
|
111
|
+
pass
|
|
112
|
+
return data
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def from_file(cls, filepath, **kwargs):
|
|
117
|
+
"""read image from file
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
project = kwargs.get("project")
|
|
121
|
+
class_name = "Image" #cls.__class__.__name__
|
|
122
|
+
suuid = SUUID.from_file(class_name, filepath, ns_name=project)
|
|
123
|
+
kwargs["sname"] = suuid.sname
|
|
124
|
+
kwargs["uuid"] = suuid.huuid
|
|
125
|
+
kwargs["suuid"] = suuid.idstr
|
|
126
|
+
kwargs["url"] = filepath
|
|
127
|
+
name = os.path.basename(filepath)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
if filepath.lower().endswith(".png"):
|
|
131
|
+
data = cls.from_png(filepath, **kwargs)
|
|
132
|
+
elif filepath.lower().endswith(("jpg", "jpeg")):
|
|
133
|
+
data = cls.from_jpg(filepath, **kwargs)
|
|
134
|
+
else:
|
|
135
|
+
data = cls(name=name, **kwargs)
|
|
136
|
+
return data
|
|
137
|
+
|
|
138
|
+
def get_sha3_256(self, filepath):
|
|
139
|
+
sh = hashlib.sha3_256()
|
|
140
|
+
with open(filepath, "rb") as fh:
|
|
141
|
+
sh.update(fh.read())
|
|
142
|
+
return sh.hexdigest()
|
|
143
|
+
|
|
144
|
+
def get_image_metadata(self):
|
|
145
|
+
"""get metadata dict from pillow image"""
|
|
146
|
+
if self.img is None:
|
|
147
|
+
self.load()
|
|
148
|
+
return self.img.info
|
|
149
|
+
|
|
150
|
+
def load(self):
|
|
151
|
+
"""store image data in sdata.Image.img"""
|
|
152
|
+
if PIL is None:
|
|
153
|
+
logging.warning("PIL is not available -> no image import")
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
if os.path.exists(self.url):
|
|
157
|
+
self.img = PIL.Image.open(self.url)
|
|
158
|
+
return self.img
|
|
159
|
+
|
|
160
|
+
def to_numpy(self):
|
|
161
|
+
"""returns a NumPy array created from the color channels of the given Image object
|
|
162
|
+
|
|
163
|
+
array([[[192, 190, 187],
|
|
164
|
+
[193, 190, 187],
|
|
165
|
+
[193, 190, 185],
|
|
166
|
+
"""
|
|
167
|
+
return np.array(self.img)
|
|
168
|
+
|
|
169
|
+
@classmethod
|
|
170
|
+
def from_png(cls, filepath, **kwargs):
|
|
171
|
+
"""load png image and metadata
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
if PIL is None:
|
|
175
|
+
logging.warning("PIL is not available -> no image import")
|
|
176
|
+
return
|
|
177
|
+
data = cls._from_filepath(filepath, **kwargs)
|
|
178
|
+
data.load()
|
|
179
|
+
if "sdata" in data.img.info:
|
|
180
|
+
d = json.loads(data.img.info.get("sdata"))
|
|
181
|
+
data.metadata = data.metadata.from_json(d)
|
|
182
|
+
return data
|
|
183
|
+
|
|
184
|
+
@staticmethod
|
|
185
|
+
def _get_metadata(filepath, **kwargs):
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
"""
|
|
189
|
+
if filepath.lower().endswith(".png"):
|
|
190
|
+
d = Image._get_png_metadata(filepath, **kwargs)
|
|
191
|
+
elif filepath.lower().endswith(".jpg"):
|
|
192
|
+
d = Image._get_png_metadata(filepath, **kwargs)
|
|
193
|
+
else:
|
|
194
|
+
d = {}
|
|
195
|
+
return d
|
|
196
|
+
|
|
197
|
+
@staticmethod
|
|
198
|
+
def _get_png_metadata(filepath, **kwargs):
|
|
199
|
+
"""load metadata json dict from img.info
|
|
200
|
+
"""
|
|
201
|
+
img = PIL.Image.open(filepath)
|
|
202
|
+
try:
|
|
203
|
+
d = json.loads(img.info.get("sdata"))
|
|
204
|
+
except Exception as exp:
|
|
205
|
+
d = {}
|
|
206
|
+
return d
|
|
207
|
+
|
|
208
|
+
@classmethod
|
|
209
|
+
def from_jpg(cls, filepath, **kwargs):
|
|
210
|
+
"""load jpg image and metadata
|
|
211
|
+
|
|
212
|
+
"""
|
|
213
|
+
if PIL is None:
|
|
214
|
+
logging.warning("PIL is not available -> no image import")
|
|
215
|
+
return
|
|
216
|
+
data = cls._from_filepath(filepath, **kwargs)
|
|
217
|
+
# data.load()
|
|
218
|
+
try:
|
|
219
|
+
d = cls._get_jpg_metadata(filepath)
|
|
220
|
+
if d is not None:
|
|
221
|
+
data.metadata = data.metadata.from_json(d)
|
|
222
|
+
except Exception as exp:
|
|
223
|
+
logging.debug(exp)
|
|
224
|
+
return data
|
|
225
|
+
|
|
226
|
+
@staticmethod
|
|
227
|
+
def _get_jpg_metadata(filepath):
|
|
228
|
+
"""load metadata json dict from exif usercomment
|
|
229
|
+
|
|
230
|
+
"""
|
|
231
|
+
exif_dict = sdata.contrib.piexif.load(filepath)
|
|
232
|
+
exif = exif_dict.get("Exif")
|
|
233
|
+
user_comment = exif.get(sdata.contrib.piexif.ExifIFD.UserComment)
|
|
234
|
+
d = None
|
|
235
|
+
if user_comment is not None:
|
|
236
|
+
json_string = sdata.contrib.piexif.helper.UserComment.load(user_comment)
|
|
237
|
+
d = json.loads(json_string)
|
|
238
|
+
return d
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def basename(self):
|
|
242
|
+
return os.path.basename(self.url)
|
|
243
|
+
|
|
244
|
+
def saveas(self, filepath, rename=True, random=True, **kwargs):
|
|
245
|
+
"""save image
|
|
246
|
+
|
|
247
|
+
"""
|
|
248
|
+
other = copy.deepcopy(self) # keep parent ...
|
|
249
|
+
if rename is True:
|
|
250
|
+
basename = os.path.basename(filepath)
|
|
251
|
+
other.rename(basename, random=random)
|
|
252
|
+
other.update_mtime()
|
|
253
|
+
other.save(filepath)
|
|
254
|
+
return other
|
|
255
|
+
|
|
256
|
+
def save(self, filepath, **kwargs):
|
|
257
|
+
|
|
258
|
+
if self.img is None:
|
|
259
|
+
self.load()
|
|
260
|
+
|
|
261
|
+
if filepath.endswith(".png"):
|
|
262
|
+
self._save_png(filepath)
|
|
263
|
+
elif filepath.lower().endswith(".jpg"):
|
|
264
|
+
self._save_jpg(filepath)
|
|
265
|
+
else:
|
|
266
|
+
logging.warning(f"metadata not supported for {filepath}")
|
|
267
|
+
self.img.save(filepath)
|
|
268
|
+
|
|
269
|
+
def _save_png(self, filepath):
|
|
270
|
+
"""save png with metadata
|
|
271
|
+
|
|
272
|
+
"""
|
|
273
|
+
if self.img is None:
|
|
274
|
+
self.load()
|
|
275
|
+
|
|
276
|
+
json_string = json.dumps(self.metadata.to_json())
|
|
277
|
+
metadaten = PIL.PngImagePlugin.PngInfo()
|
|
278
|
+
metadaten.add_text("sdata", json_string)
|
|
279
|
+
|
|
280
|
+
self.img.save(filepath, "PNG", pnginfo=metadaten)
|
|
281
|
+
|
|
282
|
+
def _save_jpg(self, filepath):
|
|
283
|
+
"""save jpg with metadata
|
|
284
|
+
|
|
285
|
+
"""
|
|
286
|
+
if self.img is None:
|
|
287
|
+
self.load()
|
|
288
|
+
json_string = json.dumps(self.metadata.to_json())
|
|
289
|
+
exif_dict = {"Exif": {sdata.contrib.piexif.ExifIFD.UserComment: sdata.contrib.piexif.helper.UserComment.dump(json_string)}}
|
|
290
|
+
exif_bytes = sdata.contrib.piexif.dump(exif_dict)
|
|
291
|
+
self.img.save(filepath, "jpeg", exif=exif_bytes)
|
|
292
|
+
|
|
293
|
+
def get_image_download_link(self, img, filename, text):
|
|
294
|
+
|
|
295
|
+
json_string = json.dumps(self.metadata.to_json())
|
|
296
|
+
buffered = BytesIO()
|
|
297
|
+
|
|
298
|
+
if filename.endswith(".png"):
|
|
299
|
+
metadaten = PIL.PngImagePlugin.PngInfo()
|
|
300
|
+
metadaten.add_text("sdata", json_string)
|
|
301
|
+
img.save(buffered, "PNG", pnginfo=metadaten)
|
|
302
|
+
elif filename.lower().endswith(".jpg"):
|
|
303
|
+
exif_dict = {"Exif": {
|
|
304
|
+
sdata.contrib.piexif.ExifIFD.UserComment: sdata.contrib.piexif.helper.UserComment.dump(json_string)}}
|
|
305
|
+
exif_bytes = sdata.contrib.piexif.dump(exif_dict)
|
|
306
|
+
img.save(buffered, format="JPEG", exif=exif_bytes)
|
|
307
|
+
else:
|
|
308
|
+
logging.warning(f"metadata not supported for {filepath}")
|
|
309
|
+
img.save(buffered)
|
|
310
|
+
|
|
311
|
+
img_str = base64.b64encode(buffered.getvalue()).decode()
|
|
312
|
+
href = f'<a href="data:file/txt;base64,{img_str}" download="{filename}">{text}</a>'
|
|
313
|
+
return href
|
sdata/experiments/ks2.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# ["name", "default_value", "dtype", "unit", "description", "required"]
|
|
4
|
+
|
|
5
|
+
ks2specimen_default_attributes = [["rd", None, "float", "deg", "rolling direction", True],
|
|
6
|
+
["t", None, "float", "mm", "thickness sheet", True],
|
|
7
|
+
["r", None, "float", "mm", "bending radius sheet", True],
|
|
8
|
+
["bi", None, "float", "mm", "inner width", True],
|
|
9
|
+
["hi", None, "float", "mm", "inner height", True],
|
|
10
|
+
["l", None, "float", "mm", "length", True],
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
# ["name", "value", "dtype", "unit", "description", "required"]
|
|
14
|
+
ks2test_default_attributes = [["angle", None, "float", "deg", "loading angle", True],
|
|
15
|
+
]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
lapshear_specimen_default_attributes = [
|
|
4
|
+
["rd", None, "float", "deg", "rolling direction", True],
|
|
5
|
+
["t", None, "float", "mm", "thickness sheet", True],
|
|
6
|
+
["l", None, "float", "mm", "length", True],
|
|
7
|
+
["w", None, "float", "mm", "width", True],
|
|
8
|
+
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# ["name", "default_value", "dtype", "unit", "description", "required"]
|
|
4
|
+
material_default_attributes = [
|
|
5
|
+
["material_type", None, "str", "-", "Material type, e.g. alu|steel|plastic|wood|glas|foam|soil|...", True],
|
|
6
|
+
["material_grade", "-", "str", "-", "Material grade, e.g. T4", False],
|
|
7
|
+
]
|