opensemantic.characteristics.quantitative 0.2.2.dev1__tar.gz → 0.2.2.dev2__tar.gz
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.
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/PKG-INFO +3 -1
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/setup.cfg +2 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic/characteristics/quantitative/__init__.py +4 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic/characteristics/quantitative/_model.py +3 -3
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic/characteristics/quantitative/_static.py +96 -3
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic.characteristics.quantitative.egg-info/PKG-INFO +3 -1
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic.characteristics.quantitative.egg-info/requires.txt +2 -0
- opensemantic_characteristics_quantitative-0.2.2.dev2/tests/integration_test.py +238 -0
- opensemantic_characteristics_quantitative-0.2.2.dev1/tests/integration_test.py +0 -106
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/.coveragerc +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/.github/workflows/ci.yml +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/.gitignore +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/.isort.cfg +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/.pre-commit-config.yaml +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/.readthedocs.yml +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/AUTHORS.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/CHANGELOG.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/CONTRIBUTING.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/LICENSE.txt +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/README.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/Makefile +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/_static/.gitignore +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/authors.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/changelog.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/conf.py +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/contributing.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/index.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/license.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/readme.md +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/docs/requirements.txt +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/pyproject.toml +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/setup.py +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic/characteristics/quantitative/conversion_test.py +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic.characteristics.quantitative.egg-info/SOURCES.txt +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic.characteristics.quantitative.egg-info/dependency_links.txt +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic.characteristics.quantitative.egg-info/not-zip-safe +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/src/opensemantic.characteristics.quantitative.egg-info/top_level.txt +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/tests/conftest.py +0 -0
- {opensemantic_characteristics_quantitative-0.2.2.dev1 → opensemantic_characteristics_quantitative-0.2.2.dev2}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensemantic.characteristics.quantitative
|
|
3
|
-
Version: 0.2.2.
|
|
3
|
+
Version: 0.2.2.dev2
|
|
4
4
|
Summary: Library with Python models derived from the page package world.opensemantic.characteristics.quantitative
|
|
5
5
|
Home-page: https://github.com/OpenSemanticWorld-Packages/opensemantic.characteristics.quantitative-python
|
|
6
6
|
Author: OpenSemanticWorld
|
|
@@ -17,12 +17,14 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
18
|
Requires-Dist: pydantic
|
|
19
19
|
Requires-Dist: pint
|
|
20
|
+
Requires-Dist: pint-pandas
|
|
20
21
|
Requires-Dist: oold
|
|
21
22
|
Requires-Dist: opensemantic.characteristics
|
|
22
23
|
Provides-Extra: testing
|
|
23
24
|
Requires-Dist: setuptools; extra == "testing"
|
|
24
25
|
Requires-Dist: pytest; extra == "testing"
|
|
25
26
|
Requires-Dist: pytest-cov; extra == "testing"
|
|
27
|
+
Requires-Dist: scipy; extra == "testing"
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
|
|
28
30
|
<!-- These are examples of badges you might want to add to your README:
|
|
@@ -369,7 +369,7 @@ class AmountOfSubstancePerMass(QuantityValue):
|
|
|
369
369
|
|
|
370
370
|
|
|
371
371
|
class DimensionlessUnit(UnitEnum):
|
|
372
|
-
|
|
372
|
+
dimensionless = "Item:OSW5d3fe58ebbac5483bad8904ff8811366"
|
|
373
373
|
|
|
374
374
|
|
|
375
375
|
class Dimensionless(QuantityValue):
|
|
@@ -398,7 +398,7 @@ class Dimensionless(QuantityValue):
|
|
|
398
398
|
|
|
399
399
|
type: Optional[Any] = ["Category:OSWbcaa33bd770e53e09d5e6087d141648b"]
|
|
400
400
|
unit: Optional[DimensionlessUnit] = Field(
|
|
401
|
-
DimensionlessUnit.
|
|
401
|
+
DimensionlessUnit.dimensionless,
|
|
402
402
|
options={"enum_titles": ["#"]},
|
|
403
403
|
title="DimensionlessUnit",
|
|
404
404
|
x_enum_varnames=[""],
|
|
@@ -1595,7 +1595,7 @@ class Dimensionless(QuantityValue):
|
|
|
1595
1595
|
|
|
1596
1596
|
type: Optional[Any] = ["Category:OSWbcaa33bd770e53e09d5e6087d141648b"]
|
|
1597
1597
|
unit: Optional[DimensionlessUnit] = Field(
|
|
1598
|
-
DimensionlessUnit.
|
|
1598
|
+
DimensionlessUnit.dimensionless,
|
|
1599
1599
|
options={"enum_titles": ["#"]},
|
|
1600
1600
|
title="DimensionlessUnit",
|
|
1601
1601
|
x_enum_varnames=[""],
|
|
@@ -10,11 +10,13 @@ else:
|
|
|
10
10
|
|
|
11
11
|
from typing import Any, Dict, List, Optional, Union
|
|
12
12
|
|
|
13
|
+
import pandas as pd
|
|
14
|
+
|
|
13
15
|
# pip install pint
|
|
14
16
|
import pint
|
|
17
|
+
import pint_pandas # noqa: F401
|
|
15
18
|
from oold.model.v1 import LinkedBaseModelMetaClass as ModelMetaclass
|
|
16
|
-
from
|
|
17
|
-
from pydantic.v1 import Field
|
|
19
|
+
from pydantic.v1 import Field, create_model
|
|
18
20
|
from pydantic.v1.fields import FieldInfo
|
|
19
21
|
|
|
20
22
|
from opensemantic import OswBaseModel
|
|
@@ -80,7 +82,7 @@ class Characteristic(OswBaseModel):
|
|
|
80
82
|
# uuid: UUID = Field(default_factory=uuid4, options={"hidden": True}, title="UUID")
|
|
81
83
|
|
|
82
84
|
|
|
83
|
-
ureg =
|
|
85
|
+
ureg = pint.get_application_registry()
|
|
84
86
|
|
|
85
87
|
quantity_registry: Dict[EnumType, ModelMetaclass] = {}
|
|
86
88
|
|
|
@@ -212,6 +214,11 @@ class QuantityValue(Characteristic, metaclass=QuantityValueMetaclass):
|
|
|
212
214
|
pint_quantity = self.to_pint().to_base_units()
|
|
213
215
|
return self.from_pint(pint_quantity, simplify=False)
|
|
214
216
|
|
|
217
|
+
def __eq__(self, other: "QuantityValue") -> bool:
|
|
218
|
+
if isinstance(other, QuantityValue):
|
|
219
|
+
other = other.to_pint()
|
|
220
|
+
return self.to_pint() == other
|
|
221
|
+
|
|
215
222
|
def __add__(self, other: "QuantityValue") -> "QuantityValue":
|
|
216
223
|
res_pint = self.to_pint() + other.to_pint()
|
|
217
224
|
return self.from_pint(res_pint)
|
|
@@ -220,8 +227,94 @@ class QuantityValue(Characteristic, metaclass=QuantityValueMetaclass):
|
|
|
220
227
|
res_pint = self.to_pint() - other.to_pint()
|
|
221
228
|
return self.from_pint(res_pint)
|
|
222
229
|
|
|
230
|
+
# * operator
|
|
223
231
|
def __mul__(self, other: Union["QuantityValue", float, int]) -> "QuantityValue":
|
|
224
232
|
if not isinstance(other, (float, int)):
|
|
225
233
|
other = other.to_pint()
|
|
226
234
|
res_pint = self.to_pint() * other
|
|
227
235
|
return self.from_pint(res_pint)
|
|
236
|
+
|
|
237
|
+
# / operator
|
|
238
|
+
def __truediv__(self, other: Union["QuantityValue", float, int]) -> "QuantityValue":
|
|
239
|
+
if not isinstance(other, (float, int)):
|
|
240
|
+
other = other.to_pint()
|
|
241
|
+
res_pint = self.to_pint() / other
|
|
242
|
+
return self.from_pint(res_pint)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class TabularData(OswBaseModel):
|
|
246
|
+
# rows: List[Any] # convention for tabular data is a list of rows
|
|
247
|
+
|
|
248
|
+
# consider https://stackoverflow.com/questions/51505504/pandas-nesting-dataframes # noqa: E501
|
|
249
|
+
# consider https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.attrs.html # noqa: E501
|
|
250
|
+
|
|
251
|
+
def to_df(self) -> pd.DataFrame:
|
|
252
|
+
series = []
|
|
253
|
+
row_class = self.__class__.__fields__["rows"].type_
|
|
254
|
+
for attr in row_class.__fields__.keys():
|
|
255
|
+
q_name = (
|
|
256
|
+
row_class.__fields__[attr]
|
|
257
|
+
.type_.__fields__["unit"]
|
|
258
|
+
.default.name.replace("_", " ")
|
|
259
|
+
)
|
|
260
|
+
# q_pint = ureg[q_name]
|
|
261
|
+
s = pd.Series(
|
|
262
|
+
[
|
|
263
|
+
(
|
|
264
|
+
getattr(m, attr).to_pint().to(q_name).magnitude
|
|
265
|
+
if getattr(m, attr, None) is not None
|
|
266
|
+
else None
|
|
267
|
+
)
|
|
268
|
+
for m in self.rows
|
|
269
|
+
],
|
|
270
|
+
dtype="pint[" + q_name + "]",
|
|
271
|
+
name=attr,
|
|
272
|
+
)
|
|
273
|
+
series.append(s)
|
|
274
|
+
rows = {s.name: s for s in series}
|
|
275
|
+
return pd.DataFrame(rows)
|
|
276
|
+
|
|
277
|
+
@classmethod
|
|
278
|
+
def from_df(cls, df: pd.DataFrame):
|
|
279
|
+
rows = []
|
|
280
|
+
row_class = OswBaseModel
|
|
281
|
+
if "rows" in cls.__fields__:
|
|
282
|
+
row_class = cls.__fields__["rows"].type_
|
|
283
|
+
|
|
284
|
+
additional_fields = {}
|
|
285
|
+
for key in df.columns:
|
|
286
|
+
# print(df[key].pint.__dict__)
|
|
287
|
+
if key not in row_class.__fields__.keys():
|
|
288
|
+
# raise ValueError(f"Column '{key}' not found in '{row_class.__name__}'") # noqa: E501
|
|
289
|
+
quantity = QuantityValue.from_pint(
|
|
290
|
+
1 * getattr(df.dtypes, key).units
|
|
291
|
+
).__class__
|
|
292
|
+
additional_fields[key] = (quantity, ...)
|
|
293
|
+
|
|
294
|
+
if len(additional_fields) > 0:
|
|
295
|
+
row_class = create_model(
|
|
296
|
+
row_class.__name__ + "Extended", **additional_fields, __base__=row_class
|
|
297
|
+
)
|
|
298
|
+
cls = create_model(
|
|
299
|
+
cls.__name__ + "Extended",
|
|
300
|
+
**{"rows": (List[row_class], ...)},
|
|
301
|
+
__base__=cls,
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# convert all columns to the default unit
|
|
305
|
+
for attr in row_class.__fields__.keys():
|
|
306
|
+
q_name = (
|
|
307
|
+
row_class.__fields__[attr]
|
|
308
|
+
.type_.__fields__["unit"]
|
|
309
|
+
.default.name.replace("_", " ")
|
|
310
|
+
)
|
|
311
|
+
q_pint = ureg[q_name]
|
|
312
|
+
df[attr] = df[attr].pint.to(q_pint)
|
|
313
|
+
|
|
314
|
+
for i, row in df.iterrows():
|
|
315
|
+
# create a dictionary with the values of the row
|
|
316
|
+
# using the column names as keys
|
|
317
|
+
d = {key: {"value": row[key].magnitude} for key in df.columns}
|
|
318
|
+
m = row_class(**d)
|
|
319
|
+
rows.append(m)
|
|
320
|
+
return cls(rows=rows)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensemantic.characteristics.quantitative
|
|
3
|
-
Version: 0.2.2.
|
|
3
|
+
Version: 0.2.2.dev2
|
|
4
4
|
Summary: Library with Python models derived from the page package world.opensemantic.characteristics.quantitative
|
|
5
5
|
Home-page: https://github.com/OpenSemanticWorld-Packages/opensemantic.characteristics.quantitative-python
|
|
6
6
|
Author: OpenSemanticWorld
|
|
@@ -17,12 +17,14 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
18
|
Requires-Dist: pydantic
|
|
19
19
|
Requires-Dist: pint
|
|
20
|
+
Requires-Dist: pint-pandas
|
|
20
21
|
Requires-Dist: oold
|
|
21
22
|
Requires-Dist: opensemantic.characteristics
|
|
22
23
|
Provides-Extra: testing
|
|
23
24
|
Requires-Dist: setuptools; extra == "testing"
|
|
24
25
|
Requires-Dist: pytest; extra == "testing"
|
|
25
26
|
Requires-Dist: pytest-cov; extra == "testing"
|
|
27
|
+
Requires-Dist: scipy; extra == "testing"
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
|
|
28
30
|
<!-- These are examples of badges you might want to add to your README:
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
|
|
4
|
+
from scipy.stats import linregress
|
|
5
|
+
|
|
6
|
+
from opensemantic import OswBaseModel
|
|
7
|
+
from opensemantic.characteristics.quantitative import (
|
|
8
|
+
Area,
|
|
9
|
+
AreaUnit,
|
|
10
|
+
Force,
|
|
11
|
+
ForcePerAreaUnit,
|
|
12
|
+
ForceUnit,
|
|
13
|
+
Length,
|
|
14
|
+
LengthUnit,
|
|
15
|
+
LinearStrain,
|
|
16
|
+
ModulusOfElasticity,
|
|
17
|
+
QuantityValue,
|
|
18
|
+
Stress,
|
|
19
|
+
TabularData,
|
|
20
|
+
Thickness,
|
|
21
|
+
Width,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# to we have to adapt VSCode settings to include the package index?
|
|
25
|
+
# "python.analysis.packageIndexDepths": [
|
|
26
|
+
# {"name": "opensemantic.characteristics.quantitative",
|
|
27
|
+
# "depth": 4, "includeAllSymbols": true}
|
|
28
|
+
# ]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_pint():
|
|
32
|
+
|
|
33
|
+
q = Length(value=1.0, unit=LengthUnit.milli_meter)
|
|
34
|
+
# transform to pint
|
|
35
|
+
q_pint = q.to_pint()
|
|
36
|
+
# transform back to QuantityValue
|
|
37
|
+
q_ = QuantityValue.from_pint(q_pint)
|
|
38
|
+
assert q == q_
|
|
39
|
+
|
|
40
|
+
q2 = Length(value=1.0, unit=LengthUnit.meter)
|
|
41
|
+
q3 = q + q2
|
|
42
|
+
assert q3 == Length(value=1.001, unit=LengthUnit.meter)
|
|
43
|
+
|
|
44
|
+
q31 = q * q2
|
|
45
|
+
assert q31 == Area(value=1000.0, unit=AreaUnit.milli_meter_squared)
|
|
46
|
+
|
|
47
|
+
q41 = Area(value=1.0, unit=AreaUnit.meter_squared)
|
|
48
|
+
q42 = Area(value=1.0, unit=AreaUnit.milli_meter_squared)
|
|
49
|
+
# 'square_meter' is not a valid unit for pint, but 'square_meter' is
|
|
50
|
+
q43 = q41 + q42
|
|
51
|
+
assert q43 == Area(value=1.000001, unit=AreaUnit.meter_squared)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_export():
|
|
55
|
+
|
|
56
|
+
q = Length(value=1.0, unit=LengthUnit.milli_meter)
|
|
57
|
+
|
|
58
|
+
q_json = json.loads(q.json(exclude_none=True))
|
|
59
|
+
print(q_json)
|
|
60
|
+
assert q_json == {
|
|
61
|
+
"type": ["Category:OSWee9c7e5c343e542cb5a8b4648315902f"],
|
|
62
|
+
"value": 1.0,
|
|
63
|
+
"unit": str(
|
|
64
|
+
"Item:OSWf101d25e944856e3bd4b4c9863db7de2"
|
|
65
|
+
"#OSW322dec469be75aedb008b3ebff29db86"
|
|
66
|
+
),
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
q = Length(value=1.0, unit=LengthUnit.meter)
|
|
70
|
+
|
|
71
|
+
q_json = json.loads(q.json(exclude_none=True))
|
|
72
|
+
print(q_json)
|
|
73
|
+
assert q_json == {
|
|
74
|
+
"type": ["Category:OSWee9c7e5c343e542cb5a8b4648315902f"],
|
|
75
|
+
"value": 1.0,
|
|
76
|
+
"unit": "Item:OSWf101d25e944856e3bd4b4c9863db7de2",
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
q_json = json.loads(q.json(exclude_none=True, exclude_defaults=True))
|
|
80
|
+
print(q_json)
|
|
81
|
+
assert q_json == {"value": 1.0}
|
|
82
|
+
|
|
83
|
+
ln = Length(value=0.1)
|
|
84
|
+
w = Width(value=200, unit=LengthUnit.milli_meter)
|
|
85
|
+
a = ln * w
|
|
86
|
+
print(a)
|
|
87
|
+
|
|
88
|
+
json_dict = a.dict()
|
|
89
|
+
print(json_dict)
|
|
90
|
+
assert json_dict["type"] == ["Category:OSW1fcf1694712e5684885071efdf775bd9"]
|
|
91
|
+
assert json_dict["value"] == 20000.0
|
|
92
|
+
assert json_dict["unit"] == (
|
|
93
|
+
"Item:OSWd10e5841c68e5aad94b481b58ef9dfb9"
|
|
94
|
+
"#OSWeca22bf4270853038ef3395bd6dd797b"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# _a = QuantityValue(**json_dict)
|
|
98
|
+
|
|
99
|
+
_a = a.to_base()
|
|
100
|
+
json_dict = _a.dict(exclude_none=True, exclude_defaults=True)
|
|
101
|
+
print(json_dict)
|
|
102
|
+
assert json_dict["value"] == 0.02
|
|
103
|
+
assert len(json_dict.keys()) == 1
|
|
104
|
+
|
|
105
|
+
__a = Area(**json_dict)
|
|
106
|
+
assert __a == _a
|
|
107
|
+
|
|
108
|
+
# not supported yet
|
|
109
|
+
# jsonld_dict = a.to_jsonld()
|
|
110
|
+
# print(json.dumps(jsonld_dict, indent=2))
|
|
111
|
+
|
|
112
|
+
# a2 = QuantityValue.from_jsonld(jsonld_dict)
|
|
113
|
+
# print(a2)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_pandas():
|
|
117
|
+
|
|
118
|
+
class Measurement(OswBaseModel):
|
|
119
|
+
length: Length
|
|
120
|
+
width: Width
|
|
121
|
+
area: Optional[Area] = None
|
|
122
|
+
|
|
123
|
+
class MeasurementData(TabularData):
|
|
124
|
+
rows: List[Measurement]
|
|
125
|
+
|
|
126
|
+
measurement = MeasurementData(
|
|
127
|
+
rows=[
|
|
128
|
+
Measurement(length=Length(value=1.0), width=Width(value=2.0)),
|
|
129
|
+
Measurement(length=Length(value=3.0), width=Width(value=4.0)),
|
|
130
|
+
]
|
|
131
|
+
)
|
|
132
|
+
df = measurement.to_df()
|
|
133
|
+
print(df)
|
|
134
|
+
df["area"] = df["length"] * df["width"]
|
|
135
|
+
print(df)
|
|
136
|
+
measurement2 = MeasurementData.from_df(df)
|
|
137
|
+
print(measurement2)
|
|
138
|
+
measurement3 = TabularData.from_df(df)
|
|
139
|
+
print(measurement3.json(exclude_none=True, exclude_defaults=True, indent=2))
|
|
140
|
+
# print(measurement3.__class__.schema_json(indent=2))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_tensile_test():
|
|
144
|
+
|
|
145
|
+
class TensileTestSpecimen(OswBaseModel):
|
|
146
|
+
length: Length
|
|
147
|
+
width: Width
|
|
148
|
+
thickness: Length
|
|
149
|
+
cross_section_area: Optional[Area] = None
|
|
150
|
+
e_mod: Optional[ModulusOfElasticity] = None
|
|
151
|
+
|
|
152
|
+
class TensileTestResultRow(OswBaseModel):
|
|
153
|
+
elongation: Length
|
|
154
|
+
force: Force
|
|
155
|
+
strain: Optional[LinearStrain] = None
|
|
156
|
+
stress: Optional[Stress] = None
|
|
157
|
+
|
|
158
|
+
class TensileTestResult(TabularData):
|
|
159
|
+
rows: List[TensileTestResultRow]
|
|
160
|
+
linear_region: Optional[LinearStrain] = LinearStrain(value=0.002)
|
|
161
|
+
|
|
162
|
+
class TensileTestDataset(OswBaseModel):
|
|
163
|
+
specimen: TensileTestSpecimen
|
|
164
|
+
result: TensileTestResult
|
|
165
|
+
|
|
166
|
+
def tensile_test_analysis(dataset: TensileTestDataset):
|
|
167
|
+
# Calculate cross section area if not provided
|
|
168
|
+
if dataset.specimen.cross_section_area is None:
|
|
169
|
+
dataset.specimen.cross_section_area = (
|
|
170
|
+
dataset.specimen.width * dataset.specimen.thickness
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Calculate stress and strain - slow iteration
|
|
174
|
+
# for row in dataset.result.rows:
|
|
175
|
+
# #row.stress = Stress(value=row.force.value / dataset.specimen.cross_section_area.value, unit=row.force.unit) # noqa: E501
|
|
176
|
+
# #row.strain = LinearStrain(value=row.force.value / (dataset.specimen.e_mod.value * dataset.specimen.cross_section_area.value), unit=row.force.unit) # noqa: E501
|
|
177
|
+
# row.stress = row.force / dataset.specimen.cross_section_area # noqa: E501
|
|
178
|
+
|
|
179
|
+
# Calculate stress and strain - fast as pandas DataFrame operation
|
|
180
|
+
df = dataset.result.to_df()
|
|
181
|
+
df["strain"] = df["elongation"] / dataset.specimen.length.to_pint()
|
|
182
|
+
df["stress"] = df["force"] / dataset.specimen.cross_section_area.to_pint()
|
|
183
|
+
|
|
184
|
+
# make a linear fit on the linear region of the stress-strain curve
|
|
185
|
+
# to find the modulus of elasticity
|
|
186
|
+
linear_region = df[df["strain"] <= dataset.result.linear_region.to_pint()]
|
|
187
|
+
|
|
188
|
+
slope, intercept, r_value, p_value, std_err = linregress(
|
|
189
|
+
linear_region["strain"].pint.to_base_units().pint.magnitude,
|
|
190
|
+
linear_region["stress"].pint.to_base_units().pint.magnitude,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
slope = (
|
|
194
|
+
slope
|
|
195
|
+
* linear_region["stress"].pint.to_base_units().pint.units
|
|
196
|
+
/ linear_region["strain"].pint.to_base_units().pint.units
|
|
197
|
+
) # noqa: E501
|
|
198
|
+
dataset.specimen.e_mod = ModulusOfElasticity.from_pint(slope.to("Pa"))
|
|
199
|
+
|
|
200
|
+
dataset.result = TensileTestResult.from_df(df)
|
|
201
|
+
|
|
202
|
+
return dataset
|
|
203
|
+
|
|
204
|
+
# Example usage
|
|
205
|
+
specimen = TensileTestSpecimen(
|
|
206
|
+
length=Length(value=100, unit=LengthUnit.milli_meter),
|
|
207
|
+
width=Width(value=10, unit=LengthUnit.milli_meter),
|
|
208
|
+
thickness=Thickness(value=10, unit=LengthUnit.milli_meter),
|
|
209
|
+
)
|
|
210
|
+
result = TensileTestResult(
|
|
211
|
+
rows=[
|
|
212
|
+
TensileTestResultRow(
|
|
213
|
+
force=Force(value=1.0000, unit=ForceUnit.kilo_newton),
|
|
214
|
+
elongation=Length(value=0.10, unit=LengthUnit.milli_meter),
|
|
215
|
+
), # noqa: E501
|
|
216
|
+
TensileTestResultRow(
|
|
217
|
+
force=Force(value=1.5050, unit=ForceUnit.kilo_newton),
|
|
218
|
+
elongation=Length(value=0.15, unit=LengthUnit.milli_meter),
|
|
219
|
+
), # noqa: E501
|
|
220
|
+
TensileTestResultRow(
|
|
221
|
+
force=Force(value=2.0000, unit=ForceUnit.kilo_newton),
|
|
222
|
+
elongation=Length(value=0.20, unit=LengthUnit.milli_meter),
|
|
223
|
+
), # noqa: E501
|
|
224
|
+
]
|
|
225
|
+
)
|
|
226
|
+
dataset = TensileTestDataset(specimen=specimen, result=result)
|
|
227
|
+
analyzed_dataset = tensile_test_analysis(dataset)
|
|
228
|
+
# print(analyzed_dataset.json(exclude_none=True, indent=2))
|
|
229
|
+
assert analyzed_dataset.specimen.e_mod == ModulusOfElasticity(
|
|
230
|
+
value=10.0, unit=ForcePerAreaUnit.giga_pascal
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
test_pint()
|
|
236
|
+
test_export()
|
|
237
|
+
test_pandas()
|
|
238
|
+
test_tensile_test()
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from opensemantic.characteristics.quantitative import (
|
|
4
|
-
Area,
|
|
5
|
-
AreaUnit,
|
|
6
|
-
Length,
|
|
7
|
-
LengthUnit,
|
|
8
|
-
QuantityValue,
|
|
9
|
-
Width,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
# to we have to adapt VSCode settings to include the package index?
|
|
13
|
-
# "python.analysis.packageIndexDepths": [
|
|
14
|
-
# {"name": "opensemantic.characteristics.quantitative",
|
|
15
|
-
# "depth": 4, "includeAllSymbols": true}
|
|
16
|
-
# ]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def test_pint():
|
|
20
|
-
|
|
21
|
-
q = Length(value=1.0, unit=LengthUnit.milli_meter)
|
|
22
|
-
# transform to pint
|
|
23
|
-
q_pint = q.to_pint()
|
|
24
|
-
# transform back to QuantityValue
|
|
25
|
-
q_ = QuantityValue.from_pint(q_pint)
|
|
26
|
-
assert q == q_
|
|
27
|
-
|
|
28
|
-
q2 = Length(value=1.0, unit=LengthUnit.meter)
|
|
29
|
-
q3 = q + q2
|
|
30
|
-
assert q3 == Length(value=1.001, unit=LengthUnit.meter)
|
|
31
|
-
|
|
32
|
-
q31 = q * q2
|
|
33
|
-
assert q31 == Area(value=1000.0, unit=AreaUnit.milli_meter_squared)
|
|
34
|
-
|
|
35
|
-
q41 = Area(value=1.0, unit=AreaUnit.meter_squared)
|
|
36
|
-
q42 = Area(value=1.0, unit=AreaUnit.milli_meter_squared)
|
|
37
|
-
# 'square_meter' is not a valid unit for pint, but 'square_meter' is
|
|
38
|
-
q43 = q41 + q42
|
|
39
|
-
assert q43 == Area(value=1.000001, unit=AreaUnit.meter_squared)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def test_export():
|
|
43
|
-
|
|
44
|
-
q = Length(value=1.0, unit=LengthUnit.milli_meter)
|
|
45
|
-
|
|
46
|
-
q_json = json.loads(q.json(exclude_none=True))
|
|
47
|
-
print(q_json)
|
|
48
|
-
assert q_json == {
|
|
49
|
-
"type": ["Category:OSWee9c7e5c343e542cb5a8b4648315902f"],
|
|
50
|
-
"value": 1.0,
|
|
51
|
-
"unit": str(
|
|
52
|
-
"Item:OSWf101d25e944856e3bd4b4c9863db7de2"
|
|
53
|
-
"#OSW322dec469be75aedb008b3ebff29db86"
|
|
54
|
-
),
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
q = Length(value=1.0, unit=LengthUnit.meter)
|
|
58
|
-
|
|
59
|
-
q_json = json.loads(q.json(exclude_none=True))
|
|
60
|
-
print(q_json)
|
|
61
|
-
assert q_json == {
|
|
62
|
-
"type": ["Category:OSWee9c7e5c343e542cb5a8b4648315902f"],
|
|
63
|
-
"value": 1.0,
|
|
64
|
-
"unit": "Item:OSWf101d25e944856e3bd4b4c9863db7de2",
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
q_json = json.loads(q.json(exclude_none=True, exclude_defaults=True))
|
|
68
|
-
print(q_json)
|
|
69
|
-
assert q_json == {"value": 1.0}
|
|
70
|
-
|
|
71
|
-
ln = Length(value=0.1)
|
|
72
|
-
w = Width(value=200, unit=LengthUnit.milli_meter)
|
|
73
|
-
a = ln * w
|
|
74
|
-
print(a)
|
|
75
|
-
|
|
76
|
-
json_dict = a.dict()
|
|
77
|
-
print(json_dict)
|
|
78
|
-
assert json_dict["type"] == ["Category:OSW1fcf1694712e5684885071efdf775bd9"]
|
|
79
|
-
assert json_dict["value"] == 20000.0
|
|
80
|
-
assert json_dict["unit"] == (
|
|
81
|
-
"Item:OSWd10e5841c68e5aad94b481b58ef9dfb9"
|
|
82
|
-
"#OSWeca22bf4270853038ef3395bd6dd797b"
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
# _a = QuantityValue(**json_dict)
|
|
86
|
-
|
|
87
|
-
_a = a.to_base()
|
|
88
|
-
json_dict = _a.dict(exclude_none=True, exclude_defaults=True)
|
|
89
|
-
print(json_dict)
|
|
90
|
-
assert json_dict["value"] == 0.02
|
|
91
|
-
assert len(json_dict.keys()) == 1
|
|
92
|
-
|
|
93
|
-
__a = Area(**json_dict)
|
|
94
|
-
assert __a == _a
|
|
95
|
-
|
|
96
|
-
# not supported yet
|
|
97
|
-
# jsonld_dict = a.to_jsonld()
|
|
98
|
-
# print(json.dumps(jsonld_dict, indent=2))
|
|
99
|
-
|
|
100
|
-
# a2 = QuantityValue.from_jsonld(jsonld_dict)
|
|
101
|
-
# print(a2)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if __name__ == "__main__":
|
|
105
|
-
test_pint()
|
|
106
|
-
test_export()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|