easyscience 1.0.0__tar.gz → 1.1.0__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.
- {easyscience-1.0.0 → easyscience-1.1.0}/PKG-INFO +5 -7
- {easyscience-1.0.0 → easyscience-1.1.0}/pyproject.toml +7 -10
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/Groups.py +11 -8
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/ObjectClasses.py +11 -3
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/Variable.py +2 -2
- easyscience-1.1.0/src/easyscience/Objects/new_variable/__init__.py +11 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/descriptor_base.py +5 -7
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/descriptor_number.py +70 -66
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/parameter.py +109 -101
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/virtual.py +1 -1
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/classTools.py +4 -6
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/io/template.py +7 -3
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/__init__.py +12 -9
- easyscience-1.1.0/src/easyscience/__version__.py +1 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/available_minimizers.py +33 -24
- easyscience-1.1.0/src/easyscience/fitting/minimizers/factory.py +25 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/minimizers/minimizer_base.py +16 -17
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/minimizers/minimizer_bumps.py +5 -10
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/minimizers/minimizer_dfo.py +8 -14
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/minimizers/minimizer_lmfit.py +6 -9
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/map.py +6 -17
- easyscience-1.0.0/src/easyscience/Objects/new_variable/__init__.py +0 -4
- easyscience-1.0.0/src/easyscience/__version__.py +0 -1
- easyscience-1.0.0/src/easyscience/fitting/minimizers/factory.py +0 -43
- {easyscience-1.0.0 → easyscience-1.1.0}/.gitignore +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/LICENSE +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/README.md +0 -0
- {easyscience-1.0.0/src/easyscience/fitting → easyscience-1.1.0/src/easyscience}/Constraints.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Datasets/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Datasets/xarray.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/Inferface.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/core.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/job/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/job/analysis.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/job/experiment.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/job/job.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/job/theoreticalmodel.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/descriptor_bool.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/descriptor_str.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/REDIRECT.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/Exceptions.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/classUtils.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/decorators.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/io/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/io/dict.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/io/json.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/io/xml.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Utils/string.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/fitter.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/minimizers/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/minimizers/utils.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/fitting/multi_fitter.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/global_object.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/hugger/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/hugger/hugger.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/hugger/property.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/logger.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/global_object/undo_redo.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/models/__init__.py +0 -0
- {easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/models/polynomial.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: easyscience
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Generic logic for easyScience libraries
|
|
5
|
-
Project-URL: homepage, https://
|
|
6
|
-
Project-URL: documentation, https://
|
|
5
|
+
Project-URL: homepage, https://github.com/EasyScience/EasyScience
|
|
6
|
+
Project-URL: documentation, https://easyscience.github.io/EasyScience/
|
|
7
7
|
Author: EasyScience contributors
|
|
8
8
|
License: BSD 3-Clause License
|
|
9
9
|
|
|
@@ -40,13 +40,12 @@ Classifier: License :: OSI Approved :: BSD License
|
|
|
40
40
|
Classifier: Operating System :: OS Independent
|
|
41
41
|
Classifier: Programming Language :: Python :: 3
|
|
42
42
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
43
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
44
43
|
Classifier: Programming Language :: Python :: 3.9
|
|
45
44
|
Classifier: Programming Language :: Python :: 3.10
|
|
46
45
|
Classifier: Programming Language :: Python :: 3.11
|
|
47
46
|
Classifier: Programming Language :: Python :: 3.12
|
|
48
47
|
Classifier: Topic :: Scientific/Engineering
|
|
49
|
-
Requires-Python: <3.
|
|
48
|
+
Requires-Python: <3.13,>=3.9
|
|
50
49
|
Requires-Dist: asteval
|
|
51
50
|
Requires-Dist: bumps
|
|
52
51
|
Requires-Dist: dfo-ls
|
|
@@ -68,10 +67,9 @@ Requires-Dist: tox-gh-actions; extra == 'dev'
|
|
|
68
67
|
Provides-Extra: docs
|
|
69
68
|
Requires-Dist: doc8; extra == 'docs'
|
|
70
69
|
Requires-Dist: readme-renderer; extra == 'docs'
|
|
71
|
-
Requires-Dist: sphinx; extra == 'docs'
|
|
72
70
|
Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
|
|
71
|
+
Requires-Dist: sphinx-book-theme; extra == 'docs'
|
|
73
72
|
Requires-Dist: sphinx-gallery; extra == 'docs'
|
|
74
|
-
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
75
73
|
Requires-Dist: toml; extra == 'docs'
|
|
76
74
|
Description-Content-Type: text/markdown
|
|
77
75
|
|
|
@@ -21,14 +21,13 @@ classifiers = [
|
|
|
21
21
|
"Topic :: Scientific/Engineering",
|
|
22
22
|
"Programming Language :: Python :: 3",
|
|
23
23
|
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
-
"Programming Language :: Python :: 3.8",
|
|
25
24
|
"Programming Language :: Python :: 3.9",
|
|
26
25
|
"Programming Language :: Python :: 3.10",
|
|
27
26
|
"Programming Language :: Python :: 3.11",
|
|
28
27
|
"Programming Language :: Python :: 3.12",
|
|
29
28
|
"Development Status :: 3 - Alpha"
|
|
30
29
|
]
|
|
31
|
-
requires-python = ">=3.
|
|
30
|
+
requires-python = ">=3.9,<3.13"
|
|
32
31
|
dependencies = [
|
|
33
32
|
"asteval",
|
|
34
33
|
"bumps",
|
|
@@ -55,16 +54,15 @@ dev = [
|
|
|
55
54
|
docs = [
|
|
56
55
|
"doc8",
|
|
57
56
|
"readme-renderer",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"sphinx-gallery",
|
|
57
|
+
"sphinx_autodoc_typehints",
|
|
58
|
+
"sphinx_book_theme",
|
|
59
|
+
"sphinx_gallery",
|
|
62
60
|
"toml"
|
|
63
61
|
]
|
|
64
62
|
|
|
65
63
|
[project.urls]
|
|
66
|
-
homepage = "https://
|
|
67
|
-
documentation = "https://
|
|
64
|
+
homepage = "https://github.com/EasyScience/EasyScience"
|
|
65
|
+
documentation = "https://easyscience.github.io/EasyScience/"
|
|
68
66
|
|
|
69
67
|
[tool.hatch.version]
|
|
70
68
|
path = "src/easyscience/__version__.py"
|
|
@@ -130,10 +128,9 @@ force-single-line = true
|
|
|
130
128
|
legacy_tox_ini = """
|
|
131
129
|
[tox]
|
|
132
130
|
isolated_build = True
|
|
133
|
-
envlist = py{3.
|
|
131
|
+
envlist = py{3.9,3.10,3.11,3.12}
|
|
134
132
|
[gh-actions]
|
|
135
133
|
python =
|
|
136
|
-
3.8: py38
|
|
137
134
|
3.9: py39
|
|
138
135
|
3.10: py310
|
|
139
136
|
3.11: py311
|
|
@@ -18,6 +18,7 @@ from typing import Tuple
|
|
|
18
18
|
from typing import Union
|
|
19
19
|
|
|
20
20
|
from easyscience.global_object.undo_redo import NotarizedDict
|
|
21
|
+
from easyscience.Objects.new_variable.descriptor_base import DescriptorBase
|
|
21
22
|
from easyscience.Objects.ObjectClasses import BasedBase
|
|
22
23
|
from easyscience.Objects.ObjectClasses import Descriptor
|
|
23
24
|
|
|
@@ -40,6 +41,7 @@ class BaseCollection(BasedBase, MutableSequence):
|
|
|
40
41
|
name: str,
|
|
41
42
|
*args: Union[B, V],
|
|
42
43
|
interface: Optional[iF] = None,
|
|
44
|
+
unique_name: Optional[str] = None,
|
|
43
45
|
**kwargs,
|
|
44
46
|
):
|
|
45
47
|
"""
|
|
@@ -51,7 +53,7 @@ class BaseCollection(BasedBase, MutableSequence):
|
|
|
51
53
|
:param _kwargs: Fields which this class should contain
|
|
52
54
|
:type _kwargs: dict
|
|
53
55
|
"""
|
|
54
|
-
BasedBase.__init__(self, name)
|
|
56
|
+
BasedBase.__init__(self, name, unique_name=unique_name)
|
|
55
57
|
kwargs = {key: kwargs[key] for key in kwargs.keys() if kwargs[key] is not None}
|
|
56
58
|
_args = []
|
|
57
59
|
for item in args:
|
|
@@ -67,7 +69,7 @@ class BaseCollection(BasedBase, MutableSequence):
|
|
|
67
69
|
_kwargs[key] = item
|
|
68
70
|
kwargs = _kwargs
|
|
69
71
|
for item in list(kwargs.values()) + _args:
|
|
70
|
-
if not issubclass(type(item), (Descriptor, BasedBase)):
|
|
72
|
+
if not issubclass(type(item), (Descriptor, DescriptorBase, BasedBase)):
|
|
71
73
|
raise AttributeError('A collection can only be formed from easyscience objects.')
|
|
72
74
|
args = _args
|
|
73
75
|
_kwargs = {}
|
|
@@ -83,10 +85,11 @@ class BaseCollection(BasedBase, MutableSequence):
|
|
|
83
85
|
for key in kwargs.keys():
|
|
84
86
|
if key in self.__dict__.keys() or key in self.__slots__:
|
|
85
87
|
raise AttributeError(f'Given kwarg: `{key}`, is an internal attribute. Please rename.')
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
if kwargs[key]: # Might be None (empty tuple or list)
|
|
89
|
+
self._global_object.map.add_edge(self, kwargs[key])
|
|
90
|
+
self._global_object.map.reset_type(kwargs[key], 'created_internal')
|
|
91
|
+
if interface is not None:
|
|
92
|
+
kwargs[key].interface = interface
|
|
90
93
|
# TODO wrap getter and setter in Logger
|
|
91
94
|
if interface is not None:
|
|
92
95
|
self.interface = interface
|
|
@@ -104,7 +107,7 @@ class BaseCollection(BasedBase, MutableSequence):
|
|
|
104
107
|
:rtype: None
|
|
105
108
|
"""
|
|
106
109
|
t_ = type(value)
|
|
107
|
-
if issubclass(t_, (BasedBase, Descriptor)):
|
|
110
|
+
if issubclass(t_, (BasedBase, Descriptor, DescriptorBase)):
|
|
108
111
|
update_key = list(self._kwargs.keys())
|
|
109
112
|
values = list(self._kwargs.values())
|
|
110
113
|
# Update the internal dict
|
|
@@ -165,7 +168,7 @@ class BaseCollection(BasedBase, MutableSequence):
|
|
|
165
168
|
if isinstance(value, Number): # noqa: S3827
|
|
166
169
|
item = self.__getitem__(key)
|
|
167
170
|
item.value = value
|
|
168
|
-
elif issubclass(type(value), BasedBase
|
|
171
|
+
elif issubclass(type(value), (BasedBase, Descriptor, DescriptorBase)):
|
|
169
172
|
update_key = list(self._kwargs.keys())
|
|
170
173
|
values = list(self._kwargs.values())
|
|
171
174
|
old_item = values[key]
|
|
@@ -28,7 +28,7 @@ from .Variable import Descriptor
|
|
|
28
28
|
from .Variable import Parameter
|
|
29
29
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
31
|
-
from easyscience.
|
|
31
|
+
from easyscience.Constraints import C
|
|
32
32
|
from easyscience.Objects.Inferface import iF
|
|
33
33
|
from easyscience.Objects.Variable import V
|
|
34
34
|
|
|
@@ -186,7 +186,7 @@ class BasedBase(ComponentSerializer):
|
|
|
186
186
|
for key, item in self._kwargs.items():
|
|
187
187
|
if hasattr(item, '_get_linkable_attributes'):
|
|
188
188
|
item_list = [*item_list, *item._get_linkable_attributes()]
|
|
189
|
-
elif issubclass(type(item), Descriptor
|
|
189
|
+
elif issubclass(type(item), (Descriptor, DescriptorBase)):
|
|
190
190
|
item_list.append(item)
|
|
191
191
|
return item_list
|
|
192
192
|
|
|
@@ -215,6 +215,12 @@ class BasedBase(ComponentSerializer):
|
|
|
215
215
|
new_class_objs = list(k for k in dir(self.__class__) if not k.startswith('_'))
|
|
216
216
|
return sorted(new_class_objs)
|
|
217
217
|
|
|
218
|
+
def __copy__(self) -> BasedBase:
|
|
219
|
+
"""Return a copy of the object."""
|
|
220
|
+
temp = self.as_dict(skip=['unique_name'])
|
|
221
|
+
new_obj = self.__class__.from_dict(temp)
|
|
222
|
+
return new_obj
|
|
223
|
+
|
|
218
224
|
|
|
219
225
|
if TYPE_CHECKING:
|
|
220
226
|
B = TypeVar('B', bound=BasedBase)
|
|
@@ -346,7 +352,9 @@ class BaseObj(BasedBase):
|
|
|
346
352
|
@staticmethod
|
|
347
353
|
def __setter(key: str) -> Callable[[BV], None]:
|
|
348
354
|
def setter(obj: BV, value: float) -> None:
|
|
349
|
-
if issubclass(obj._kwargs[key].__class__, Descriptor) and not issubclass(
|
|
355
|
+
if issubclass(obj._kwargs[key].__class__, (Descriptor, DescriptorBase)) and not issubclass(
|
|
356
|
+
value.__class__, (Descriptor, DescriptorBase)
|
|
357
|
+
):
|
|
350
358
|
obj._kwargs[key].value = value
|
|
351
359
|
else:
|
|
352
360
|
obj._kwargs[key] = value
|
|
@@ -30,14 +30,14 @@ import numpy as np
|
|
|
30
30
|
from easyscience import global_object
|
|
31
31
|
from easyscience import pint
|
|
32
32
|
from easyscience import ureg
|
|
33
|
-
from easyscience.
|
|
33
|
+
from easyscience.Constraints import SelfConstraint
|
|
34
34
|
from easyscience.global_object.undo_redo import property_stack_deco
|
|
35
35
|
from easyscience.Objects.core import ComponentSerializer
|
|
36
36
|
from easyscience.Utils.classTools import addProp
|
|
37
37
|
from easyscience.Utils.Exceptions import CoreSetException
|
|
38
38
|
|
|
39
39
|
if TYPE_CHECKING:
|
|
40
|
-
from easyscience.
|
|
40
|
+
from easyscience.Constraints import C
|
|
41
41
|
|
|
42
42
|
Q_ = ureg.Quantity
|
|
43
43
|
M_ = ureg.Measurement
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .descriptor_bool import DescriptorBool
|
|
2
|
+
from .descriptor_number import DescriptorNumber
|
|
3
|
+
from .descriptor_str import DescriptorStr
|
|
4
|
+
from .parameter import Parameter
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
DescriptorBool,
|
|
8
|
+
DescriptorNumber,
|
|
9
|
+
DescriptorStr,
|
|
10
|
+
Parameter,
|
|
11
|
+
]
|
{easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/descriptor_base.py
RENAMED
|
@@ -27,7 +27,6 @@ class DescriptorBase(ComponentSerializer, metaclass=abc.ABCMeta):
|
|
|
27
27
|
# Used by serializer
|
|
28
28
|
_REDIRECT = {'parent': None}
|
|
29
29
|
|
|
30
|
-
_global_object = global_object
|
|
31
30
|
|
|
32
31
|
def __init__(
|
|
33
32
|
self,
|
|
@@ -55,7 +54,7 @@ class DescriptorBase(ComponentSerializer, metaclass=abc.ABCMeta):
|
|
|
55
54
|
"""
|
|
56
55
|
|
|
57
56
|
if unique_name is None:
|
|
58
|
-
unique_name =
|
|
57
|
+
unique_name = global_object.generate_unique_name(self.__class__.__name__)
|
|
59
58
|
self._unique_name = unique_name
|
|
60
59
|
|
|
61
60
|
if not isinstance(name, str):
|
|
@@ -80,10 +79,10 @@ class DescriptorBase(ComponentSerializer, metaclass=abc.ABCMeta):
|
|
|
80
79
|
|
|
81
80
|
# Let the collective know we've been assimilated
|
|
82
81
|
self._parent = parent
|
|
83
|
-
|
|
82
|
+
global_object.map.add_vertex(self, obj_type='created')
|
|
84
83
|
# Make the connection between self and parent
|
|
85
84
|
if parent is not None:
|
|
86
|
-
|
|
85
|
+
global_object.map.add_edge(parent, self)
|
|
87
86
|
|
|
88
87
|
@property
|
|
89
88
|
def name(self) -> str:
|
|
@@ -187,7 +186,7 @@ class DescriptorBase(ComponentSerializer, metaclass=abc.ABCMeta):
|
|
|
187
186
|
if not isinstance(new_unique_name, str):
|
|
188
187
|
raise TypeError('Unique name has to be a string.')
|
|
189
188
|
self._unique_name = new_unique_name
|
|
190
|
-
|
|
189
|
+
global_object.map.add_vertex(self)
|
|
191
190
|
|
|
192
191
|
@property
|
|
193
192
|
@abc.abstractmethod
|
|
@@ -205,7 +204,6 @@ class DescriptorBase(ComponentSerializer, metaclass=abc.ABCMeta):
|
|
|
205
204
|
|
|
206
205
|
def __copy__(self) -> DescriptorBase:
|
|
207
206
|
"""Return a copy of the object."""
|
|
208
|
-
temp = self.as_dict()
|
|
209
|
-
temp['unique_name'] = None
|
|
207
|
+
temp = self.as_dict(skip=['unique_name'])
|
|
210
208
|
new_obj = self.__class__.from_dict(temp)
|
|
211
209
|
return new_obj
|
{easyscience-1.0.0 → easyscience-1.1.0}/src/easyscience/Objects/new_variable/descriptor_number.py
RENAMED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import numbers
|
|
4
4
|
from typing import Any
|
|
5
5
|
from typing import Dict
|
|
6
|
+
from typing import List
|
|
6
7
|
from typing import Optional
|
|
7
8
|
from typing import Union
|
|
8
9
|
|
|
@@ -89,7 +90,6 @@ class DescriptorNumber(DescriptorBase):
|
|
|
89
90
|
raise TypeError(f'{full_value=} must be a scipp scalar')
|
|
90
91
|
return cls(name=name, value=full_value.value, unit=full_value.unit, variance=full_value.variance, **kwargs)
|
|
91
92
|
|
|
92
|
-
|
|
93
93
|
@property
|
|
94
94
|
def full_value(self) -> Variable:
|
|
95
95
|
"""
|
|
@@ -101,8 +101,10 @@ class DescriptorNumber(DescriptorBase):
|
|
|
101
101
|
|
|
102
102
|
@full_value.setter
|
|
103
103
|
def full_value(self, full_value: Variable) -> None:
|
|
104
|
-
raise AttributeError(
|
|
105
|
-
|
|
104
|
+
raise AttributeError(
|
|
105
|
+
f'Full_value is read-only. Change the value and variance seperately. Or create a new {self.__class__.__name__}.'
|
|
106
|
+
)
|
|
107
|
+
|
|
106
108
|
@property
|
|
107
109
|
def value(self) -> numbers.Number:
|
|
108
110
|
"""
|
|
@@ -135,7 +137,12 @@ class DescriptorNumber(DescriptorBase):
|
|
|
135
137
|
|
|
136
138
|
@unit.setter
|
|
137
139
|
def unit(self, unit_str: str) -> None:
|
|
138
|
-
raise AttributeError(
|
|
140
|
+
raise AttributeError(
|
|
141
|
+
(
|
|
142
|
+
f'Unit is read-only. Use convert_unit to change the unit between allowed types '
|
|
143
|
+
f'or create a new {self.__class__.__name__} with the desired unit.'
|
|
144
|
+
)
|
|
145
|
+
) # noqa: E501
|
|
139
146
|
|
|
140
147
|
@property
|
|
141
148
|
def variance(self) -> float:
|
|
@@ -162,7 +169,6 @@ class DescriptorNumber(DescriptorBase):
|
|
|
162
169
|
variance_float = float(variance_float)
|
|
163
170
|
self._scalar.variance = variance_float
|
|
164
171
|
|
|
165
|
-
|
|
166
172
|
@property
|
|
167
173
|
def error(self) -> float:
|
|
168
174
|
"""
|
|
@@ -205,94 +211,92 @@ class DescriptorNumber(DescriptorBase):
|
|
|
205
211
|
# Just to get return type right
|
|
206
212
|
def __copy__(self) -> DescriptorNumber:
|
|
207
213
|
return super().__copy__()
|
|
208
|
-
|
|
214
|
+
|
|
209
215
|
def __repr__(self) -> str:
|
|
210
216
|
"""Return printable representation."""
|
|
211
|
-
string='<'
|
|
212
|
-
string+= self.__class__.__name__+' '
|
|
213
|
-
string+=f"'{self._name}': "
|
|
214
|
-
string+= f'{self._scalar.value:.4f}'
|
|
217
|
+
string = '<'
|
|
218
|
+
string += self.__class__.__name__ + ' '
|
|
219
|
+
string += f"'{self._name}': "
|
|
220
|
+
string += f'{self._scalar.value:.4f}'
|
|
215
221
|
if self.variance:
|
|
216
|
-
string += f' \
|
|
222
|
+
string += f' \u00b1 {self.error:.4f}'
|
|
217
223
|
obj_unit = self._scalar.unit
|
|
218
224
|
if obj_unit == 'dimensionless':
|
|
219
225
|
obj_unit = ''
|
|
220
226
|
else:
|
|
221
227
|
obj_unit = f' {obj_unit}'
|
|
222
|
-
string+= obj_unit
|
|
223
|
-
string+='>'
|
|
228
|
+
string += obj_unit
|
|
229
|
+
string += '>'
|
|
224
230
|
return string
|
|
225
231
|
# return f"<{class_name} '{obj_name}': {obj_value:0.04f}{obj_unit}>"
|
|
226
232
|
|
|
227
|
-
def as_dict(self) -> Dict[str, Any]:
|
|
228
|
-
raw_dict = super().as_dict()
|
|
233
|
+
def as_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
|
|
234
|
+
raw_dict = super().as_dict(skip=skip)
|
|
229
235
|
raw_dict['value'] = self._scalar.value
|
|
230
236
|
raw_dict['unit'] = str(self._scalar.unit)
|
|
231
237
|
raw_dict['variance'] = self._scalar.variance
|
|
232
238
|
return raw_dict
|
|
233
|
-
|
|
239
|
+
|
|
234
240
|
def __add__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber:
|
|
235
241
|
if isinstance(other, numbers.Number):
|
|
236
242
|
if self.unit != 'dimensionless':
|
|
237
|
-
raise UnitError(
|
|
238
|
-
new_value = self.full_value
|
|
243
|
+
raise UnitError('Numbers can only be added to dimensionless values')
|
|
244
|
+
new_value = self.full_value + other
|
|
239
245
|
elif type(other) is DescriptorNumber:
|
|
240
246
|
original_unit = other.unit
|
|
241
247
|
try:
|
|
242
248
|
other.convert_unit(self.unit)
|
|
243
249
|
except UnitError:
|
|
244
|
-
raise UnitError(f
|
|
250
|
+
raise UnitError(f'Values with units {self.unit} and {other.unit} cannot be added') from None
|
|
245
251
|
new_value = self.full_value + other.full_value
|
|
246
252
|
other.convert_unit(original_unit)
|
|
247
253
|
else:
|
|
248
254
|
return NotImplemented
|
|
249
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
250
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
255
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
256
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
251
257
|
return descriptor_number
|
|
252
|
-
|
|
253
|
-
|
|
254
258
|
|
|
255
259
|
def __radd__(self, other: numbers.Number) -> DescriptorNumber:
|
|
256
260
|
if isinstance(other, numbers.Number):
|
|
257
261
|
if self.unit != 'dimensionless':
|
|
258
|
-
raise UnitError(
|
|
262
|
+
raise UnitError('Numbers can only be added to dimensionless values')
|
|
259
263
|
new_value = other + self.full_value
|
|
260
264
|
else:
|
|
261
265
|
return NotImplemented
|
|
262
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
263
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
266
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
267
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
264
268
|
return descriptor_number
|
|
265
269
|
|
|
266
270
|
def __sub__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber:
|
|
267
271
|
if isinstance(other, numbers.Number):
|
|
268
272
|
if self.unit != 'dimensionless':
|
|
269
|
-
raise UnitError(
|
|
273
|
+
raise UnitError('Numbers can only be subtracted from dimensionless values')
|
|
270
274
|
new_value = self.full_value - other
|
|
271
275
|
elif type(other) is DescriptorNumber:
|
|
272
276
|
original_unit = other.unit
|
|
273
277
|
try:
|
|
274
278
|
other.convert_unit(self.unit)
|
|
275
279
|
except UnitError:
|
|
276
|
-
raise UnitError(f
|
|
280
|
+
raise UnitError(f'Values with units {self.unit} and {other.unit} cannot be subtracted') from None
|
|
277
281
|
new_value = self.full_value - other.full_value
|
|
278
282
|
other.convert_unit(original_unit)
|
|
279
283
|
else:
|
|
280
284
|
return NotImplemented
|
|
281
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
282
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
285
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
286
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
283
287
|
return descriptor_number
|
|
284
|
-
|
|
288
|
+
|
|
285
289
|
def __rsub__(self, other: numbers.Number) -> DescriptorNumber:
|
|
286
290
|
if isinstance(other, numbers.Number):
|
|
287
291
|
if self.unit != 'dimensionless':
|
|
288
|
-
raise UnitError(
|
|
292
|
+
raise UnitError('Numbers can only be subtracted from dimensionless values')
|
|
289
293
|
new_value = other - self.full_value
|
|
290
294
|
else:
|
|
291
295
|
return NotImplemented
|
|
292
|
-
descriptor= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
293
|
-
descriptor.name=descriptor.unique_name
|
|
296
|
+
descriptor = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
297
|
+
descriptor.name = descriptor.unique_name
|
|
294
298
|
return descriptor
|
|
295
|
-
|
|
299
|
+
|
|
296
300
|
def __mul__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber:
|
|
297
301
|
if isinstance(other, numbers.Number):
|
|
298
302
|
new_value = self.full_value * other
|
|
@@ -302,46 +306,46 @@ class DescriptorNumber(DescriptorBase):
|
|
|
302
306
|
return NotImplemented
|
|
303
307
|
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
304
308
|
descriptor_number.convert_unit(descriptor_number._base_unit())
|
|
305
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
309
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
306
310
|
return descriptor_number
|
|
307
|
-
|
|
311
|
+
|
|
308
312
|
def __rmul__(self, other: numbers.Number) -> DescriptorNumber:
|
|
309
313
|
if isinstance(other, numbers.Number):
|
|
310
314
|
new_value = other * self.full_value
|
|
311
315
|
else:
|
|
312
316
|
return NotImplemented
|
|
313
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
314
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
317
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
318
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
315
319
|
return descriptor_number
|
|
316
|
-
|
|
320
|
+
|
|
317
321
|
def __truediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber:
|
|
318
322
|
if isinstance(other, numbers.Number):
|
|
319
323
|
original_other = other
|
|
320
324
|
if other == 0:
|
|
321
|
-
raise ZeroDivisionError(
|
|
325
|
+
raise ZeroDivisionError('Cannot divide by zero')
|
|
322
326
|
new_value = self.full_value / other
|
|
323
327
|
elif type(other) is DescriptorNumber:
|
|
324
328
|
original_other = other.value
|
|
325
329
|
if original_other == 0:
|
|
326
|
-
raise ZeroDivisionError(
|
|
330
|
+
raise ZeroDivisionError('Cannot divide by zero')
|
|
327
331
|
new_value = self.full_value / other.full_value
|
|
328
332
|
other.value = original_other
|
|
329
333
|
else:
|
|
330
334
|
return NotImplemented
|
|
331
335
|
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
332
336
|
descriptor_number.convert_unit(descriptor_number._base_unit())
|
|
333
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
337
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
334
338
|
return descriptor_number
|
|
335
|
-
|
|
339
|
+
|
|
336
340
|
def __rtruediv__(self, other: numbers.Number) -> DescriptorNumber:
|
|
337
341
|
if isinstance(other, numbers.Number):
|
|
338
342
|
if self.value == 0:
|
|
339
|
-
raise ZeroDivisionError(
|
|
343
|
+
raise ZeroDivisionError('Cannot divide by zero')
|
|
340
344
|
new_value = other / self.full_value
|
|
341
345
|
else:
|
|
342
346
|
return NotImplemented
|
|
343
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
344
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
347
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
348
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
345
349
|
return descriptor_number
|
|
346
350
|
|
|
347
351
|
def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber:
|
|
@@ -349,51 +353,51 @@ class DescriptorNumber(DescriptorBase):
|
|
|
349
353
|
exponent = other
|
|
350
354
|
elif type(other) is DescriptorNumber:
|
|
351
355
|
if other.unit != 'dimensionless':
|
|
352
|
-
raise UnitError(
|
|
356
|
+
raise UnitError('Exponents must be dimensionless')
|
|
353
357
|
if other.variance is not None:
|
|
354
|
-
raise ValueError(
|
|
358
|
+
raise ValueError('Exponents must not have variance')
|
|
355
359
|
exponent = other.value
|
|
356
360
|
else:
|
|
357
361
|
return NotImplemented
|
|
358
362
|
try:
|
|
359
|
-
new_value = self.full_value
|
|
363
|
+
new_value = self.full_value**exponent
|
|
360
364
|
except Exception as message:
|
|
361
365
|
raise message from None
|
|
362
366
|
if np.isnan(new_value.value):
|
|
363
|
-
raise ValueError(
|
|
364
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
365
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
367
|
+
raise ValueError('The result of the exponentiation is not a number')
|
|
368
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
369
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
366
370
|
return descriptor_number
|
|
367
|
-
|
|
371
|
+
|
|
368
372
|
def __rpow__(self, other: numbers.Number) -> numbers.Number:
|
|
369
373
|
if isinstance(other, numbers.Number):
|
|
370
374
|
if self.unit != 'dimensionless':
|
|
371
|
-
raise UnitError(
|
|
375
|
+
raise UnitError('Exponents must be dimensionless')
|
|
372
376
|
if self.variance is not None:
|
|
373
|
-
raise ValueError(
|
|
374
|
-
new_value = other
|
|
377
|
+
raise ValueError('Exponents must not have variance')
|
|
378
|
+
new_value = other**self.value
|
|
375
379
|
else:
|
|
376
380
|
return NotImplemented
|
|
377
381
|
return new_value
|
|
378
382
|
|
|
379
383
|
def __neg__(self) -> DescriptorNumber:
|
|
380
384
|
new_value = -self.full_value
|
|
381
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
382
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
385
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
386
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
383
387
|
return descriptor_number
|
|
384
|
-
|
|
388
|
+
|
|
385
389
|
def __abs__(self) -> DescriptorNumber:
|
|
386
390
|
new_value = abs(self.full_value)
|
|
387
|
-
descriptor_number= DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
388
|
-
descriptor_number.name=descriptor_number.unique_name
|
|
391
|
+
descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value)
|
|
392
|
+
descriptor_number.name = descriptor_number.unique_name
|
|
389
393
|
return descriptor_number
|
|
390
394
|
|
|
391
395
|
def _base_unit(self) -> str:
|
|
392
396
|
string = str(self._scalar.unit)
|
|
393
397
|
for i, letter in enumerate(string):
|
|
394
|
-
if letter ==
|
|
395
|
-
if string[i:i+2] not in [
|
|
398
|
+
if letter == 'e':
|
|
399
|
+
if string[i : i + 2] not in ['e+', 'e-']:
|
|
396
400
|
return string[i:]
|
|
397
|
-
elif letter not in [
|
|
401
|
+
elif letter not in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '+', '-']:
|
|
398
402
|
return string[i:]
|
|
399
|
-
return
|
|
403
|
+
return ''
|