easyscience 0.6.1__tar.gz → 1.0.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.
Files changed (73) hide show
  1. {easyscience-0.6.1 → easyscience-1.0.0}/PKG-INFO +5 -4
  2. {easyscience-0.6.1 → easyscience-1.0.0}/README.md +1 -1
  3. {easyscience-0.6.1 → easyscience-1.0.0}/pyproject.toml +4 -3
  4. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Datasets/xarray.py +12 -13
  5. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/Groups.py +15 -16
  6. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/Inferface.py +29 -19
  7. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/ObjectClasses.py +79 -57
  8. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/Variable.py +54 -32
  9. easyscience-1.0.0/src/easyscience/Objects/job/analysis.py +64 -0
  10. easyscience-0.6.1/src/easyscience/Objects/Job/Job.py → easyscience-1.0.0/src/easyscience/Objects/job/job.py +6 -8
  11. easyscience-0.6.1/src/easyscience/Objects/Job/Theory.py → easyscience-1.0.0/src/easyscience/Objects/job/theoreticalmodel.py +3 -3
  12. easyscience-1.0.0/src/easyscience/Objects/new_variable/__init__.py +4 -0
  13. easyscience-1.0.0/src/easyscience/Objects/new_variable/descriptor_base.py +211 -0
  14. easyscience-1.0.0/src/easyscience/Objects/new_variable/descriptor_bool.py +70 -0
  15. easyscience-1.0.0/src/easyscience/Objects/new_variable/descriptor_number.py +399 -0
  16. easyscience-1.0.0/src/easyscience/Objects/new_variable/descriptor_str.py +69 -0
  17. easyscience-1.0.0/src/easyscience/Objects/new_variable/parameter.py +722 -0
  18. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/virtual.py +45 -52
  19. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/classTools.py +19 -19
  20. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/decorators.py +2 -2
  21. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/io/template.py +3 -3
  22. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/io/xml.py +19 -21
  23. easyscience-1.0.0/src/easyscience/__init__.py +28 -0
  24. easyscience-1.0.0/src/easyscience/__version__.py +1 -0
  25. {easyscience-0.6.1/src/easyscience/Fitting → easyscience-1.0.0/src/easyscience/fitting}/Constraints.py +120 -84
  26. easyscience-1.0.0/src/easyscience/fitting/__init__.py +8 -0
  27. easyscience-1.0.0/src/easyscience/fitting/available_minimizers.py +88 -0
  28. easyscience-1.0.0/src/easyscience/fitting/fitter.py +278 -0
  29. easyscience-1.0.0/src/easyscience/fitting/minimizers/__init__.py +9 -0
  30. easyscience-1.0.0/src/easyscience/fitting/minimizers/factory.py +43 -0
  31. easyscience-1.0.0/src/easyscience/fitting/minimizers/minimizer_base.py +296 -0
  32. easyscience-1.0.0/src/easyscience/fitting/minimizers/minimizer_bumps.py +273 -0
  33. easyscience-1.0.0/src/easyscience/fitting/minimizers/minimizer_dfo.py +279 -0
  34. easyscience-1.0.0/src/easyscience/fitting/minimizers/minimizer_lmfit.py +278 -0
  35. easyscience-1.0.0/src/easyscience/fitting/minimizers/utils.py +62 -0
  36. easyscience-1.0.0/src/easyscience/fitting/multi_fitter.py +135 -0
  37. easyscience-1.0.0/src/easyscience/global_object/__init__.py +4 -0
  38. easyscience-1.0.0/src/easyscience/global_object/global_object.py +69 -0
  39. easyscience-0.6.1/src/easyscience/Utils/Hugger/Property.py → easyscience-1.0.0/src/easyscience/global_object/hugger/property.py +39 -38
  40. easyscience-0.6.1/src/easyscience/Objects/Graph.py → easyscience-1.0.0/src/easyscience/global_object/map.py +87 -141
  41. easyscience-0.6.1/src/easyscience/Utils/UndoRedo.py → easyscience-1.0.0/src/easyscience/global_object/undo_redo.py +7 -7
  42. easyscience-0.6.1/src/easyscience/Fitting/DFO_LS.py +0 -288
  43. easyscience-0.6.1/src/easyscience/Fitting/Fitting.py +0 -473
  44. easyscience-0.6.1/src/easyscience/Fitting/__init__.py +0 -35
  45. easyscience-0.6.1/src/easyscience/Fitting/bumps.py +0 -314
  46. easyscience-0.6.1/src/easyscience/Fitting/fitting_template.py +0 -272
  47. easyscience-0.6.1/src/easyscience/Fitting/lmfit.py +0 -324
  48. easyscience-0.6.1/src/easyscience/Objects/Borg.py +0 -48
  49. easyscience-0.6.1/src/easyscience/Objects/Job/Analysis.py +0 -21
  50. easyscience-0.6.1/src/easyscience/Utils/io/star.py +0 -520
  51. easyscience-0.6.1/src/easyscience/Utils/typing.py +0 -14
  52. easyscience-0.6.1/src/easyscience/__init__.py +0 -18
  53. easyscience-0.6.1/src/easyscience/__version__.py +0 -1
  54. {easyscience-0.6.1 → easyscience-1.0.0}/.gitignore +0 -0
  55. {easyscience-0.6.1 → easyscience-1.0.0}/LICENSE +0 -0
  56. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Datasets/__init__.py +0 -0
  57. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/__init__.py +0 -0
  58. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Objects/core.py +0 -0
  59. {easyscience-0.6.1/src/easyscience/Objects/Job → easyscience-1.0.0/src/easyscience/Objects/job}/__init__.py +0 -0
  60. /easyscience-0.6.1/src/easyscience/Objects/Job/Experiment.py → /easyscience-1.0.0/src/easyscience/Objects/job/experiment.py +0 -0
  61. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/REDIRECT.py +0 -0
  62. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/Exceptions.py +0 -0
  63. {easyscience-0.6.1/src/easyscience/Utils/Hugger → easyscience-1.0.0/src/easyscience/Utils}/__init__.py +0 -0
  64. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/classUtils.py +0 -0
  65. {easyscience-0.6.1/src/easyscience/Utils → easyscience-1.0.0/src/easyscience/Utils/io}/__init__.py +0 -0
  66. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/io/dict.py +0 -0
  67. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/io/json.py +0 -0
  68. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/Utils/string.py +0 -0
  69. {easyscience-0.6.1/src/easyscience/Utils/io → easyscience-1.0.0/src/easyscience/global_object/hugger}/__init__.py +0 -0
  70. /easyscience-0.6.1/src/easyscience/Utils/Hugger/Hugger.py → /easyscience-1.0.0/src/easyscience/global_object/hugger/hugger.py +0 -0
  71. /easyscience-0.6.1/src/easyscience/Utils/Logging.py → /easyscience-1.0.0/src/easyscience/global_object/logger.py +0 -0
  72. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/models/__init__.py +0 -0
  73. {easyscience-0.6.1 → easyscience-1.0.0}/src/easyscience/models/polynomial.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: easyscience
3
- Version: 0.6.1
3
+ Version: 1.0.0
4
4
  Summary: Generic logic for easyScience libraries
5
5
  Project-URL: homepage, https://docs.easyscience.org
6
6
  Project-URL: documentation, https://docs.easyscience.org
@@ -51,8 +51,9 @@ Requires-Dist: asteval
51
51
  Requires-Dist: bumps
52
52
  Requires-Dist: dfo-ls
53
53
  Requires-Dist: lmfit
54
- Requires-Dist: numpy
55
- Requires-Dist: pint
54
+ Requires-Dist: numpy==1.26
55
+ Requires-Dist: pint==0.23
56
+ Requires-Dist: scipp
56
57
  Requires-Dist: uncertainties
57
58
  Requires-Dist: xarray
58
59
  Provides-Extra: dev
@@ -111,6 +112,6 @@ Documentation can be found at:
111
112
  We absolutely welcome contributions. **EasyScience** is maintained by the ESS and on a volunteer basis and thus we need to foster a community that can support user questions and develop new features to make this software a useful tool for all users while encouraging every member of the community to share their ideas.
112
113
 
113
114
  ## License
114
- While **EasyScience** is under the BSD-3 license, DFO_LS is subject to the GPL license.
115
+ While **EasyScience** is under the BSD-3 license, DFO-LS is subject to the GPL license.
115
116
 
116
117
 
@@ -35,6 +35,6 @@ Documentation can be found at:
35
35
  We absolutely welcome contributions. **EasyScience** is maintained by the ESS and on a volunteer basis and thus we need to foster a community that can support user questions and develop new features to make this software a useful tool for all users while encouraging every member of the community to share their ideas.
36
36
 
37
37
  ## License
38
- While **EasyScience** is under the BSD-3 license, DFO_LS is subject to the GPL license.
38
+ While **EasyScience** is under the BSD-3 license, DFO-LS is subject to the GPL license.
39
39
 
40
40
 
@@ -34,10 +34,11 @@ dependencies = [
34
34
  "bumps",
35
35
  "DFO-LS",
36
36
  "lmfit",
37
- "numpy",
38
- "pint",
37
+ "numpy==1.26", # Should be updated to numpy 2.0
39
38
  "uncertainties",
40
- "xarray"
39
+ "xarray",
40
+ "pint==0.23", # Only to ensure that unit is reported as dimensionless rather than empty string
41
+ "scipp"
41
42
  ]
42
43
 
43
44
  [project.optional-dependencies]
@@ -20,7 +20,7 @@ import numpy as np
20
20
  import xarray as xr
21
21
 
22
22
  from easyscience import ureg
23
- from easyscience.Fitting.fitting_template import FitResults
23
+ from easyscience.fitting import FitResults
24
24
 
25
25
  T_ = TypeVar('T_')
26
26
 
@@ -281,14 +281,13 @@ class EasyScienceDatasetAccessor:
281
281
 
282
282
  :param variable_label: Name of the DataArray to perform the calculation on
283
283
  :type variable_label: str
284
- :param sigma_func: Function to generate the sigmas. Must be of the form f(x) and return an array of the same
285
- shape as the input. DEFAULT: sqrt(|data|)
284
+ :param sigma_func: Function to generate the sigmas. Must be of the form f(x) and return an array of the same shape as the input. Default sqrt(\|x\|)
286
285
  :type sigma_func: Callable
287
286
  :param label_prefix: What prefix should be used to designate a sigma DataArray from a data DataArray
288
287
  :type label_prefix: str
289
288
  :return: None
290
289
  :rtype: None
291
- """
290
+ """ # noqa: E501
292
291
  sigma_values = sigma_func(self._obj[variable_label])
293
292
  self.sigma_attach(variable_label, sigma_values, label_prefix)
294
293
 
@@ -371,13 +370,13 @@ class EasyScienceDatasetAccessor:
371
370
  **kwargs,
372
371
  ) -> List[FitResults]:
373
372
  """
374
- Perform a fit on one or more DataArrays. This fit utilises a given fitter from `EasyScience.Fitting.Fitter`, though
373
+ Perform a fit on one or more DataArrays. This fit utilises a given fitter from `EasyScience.fitting.Fitter`, though
375
374
  there are a few differences to a standard EasyScience fit. In particular, key-word arguments to control the
376
375
  optimisation algorithm go in the `fit_kwargs` dictionary, fit function key-word arguments go in the `fn_kwargs`
377
376
  and given key-word arguments control the `xarray.apply_ufunc` function.
378
377
 
379
378
  :param fitter: Fitting object which controls the fitting
380
- :type fitter: EasyScience.Fitting.Fitter
379
+ :type fitter: EasyScience.fitting.Fitter
381
380
  :param args: Arguments to go to the fit function
382
381
  :type args: Any
383
382
  :param dask: Dask control string. See `xarray.apply_ufunc` documentation
@@ -612,13 +611,13 @@ class EasyScienceDataarrayAccessor:
612
611
 
613
612
  def fit_prep(self, func_in: Callable, bdims=None, dask_chunks=None) -> Tuple[xr.DataArray, Callable]:
614
613
  """
615
- Generate boradcasted coordinates for fitting and reform the fitting function into one which can handle xarrays
614
+ Generate broadcasted coordinates for fitting and reform the fitting function into one which can handle xarrays.
616
615
 
617
- :param func_in: Function to be wrapped and made xarray fitting compatable.
616
+ :param func_in: Function to be wrapped and made xarray fitting compatible.
618
617
  :type func_in: Callable
619
618
  :param bdims: Optional precomputed broadcasted dimensions.
620
619
  :type bdims: xarray.DataArray
621
- :param dask_chunks: How to split to broadcasted dimensions for dask.
620
+ :param dask_chunks: How to split the broadcasted dimensions for dask.
622
621
  :type dask_chunks: Tuple[int..]
623
622
  :return: Tuple of broadcasted fit arrays and wrapped fit function.
624
623
  :rtype: xarray.DataArray, Callable
@@ -681,13 +680,13 @@ class EasyScienceDataarrayAccessor:
681
680
  **kwargs,
682
681
  ) -> FitResults:
683
682
  """
684
- Perform a fit on the given DataArray. This fit utilises a given fitter from `EasyScience.Fitting.Fitter`, though
683
+ Perform a fit on the given DataArray. This fit utilises a given fitter from `EasyScience.fitting.Fitter`, though
685
684
  there are a few differences to a standard EasyScience fit. In particular, key-word arguments to control the
686
685
  optimisation algorithm go in the `fit_kwargs` dictionary, fit function key-word arguments go in the `fn_kwargs`
687
686
  and given key-word arguments control the `xarray.apply_ufunc` function.
688
687
 
689
688
  :param fitter: Fitting object which controls the fitting
690
- :type fitter: EasyScience.Fitting.Fitter
689
+ :type fitter: EasyScience.fitting.Fitter
691
690
  :param args: Arguments to go to the fit function
692
691
  :type args: Any
693
692
  :param dask: Dask control string. See `xarray.apply_ufunc` documentation
@@ -732,7 +731,7 @@ class EasyScienceDataarrayAccessor:
732
731
 
733
732
  # Set the new callable to the fitter and initialize
734
733
  fitter.initialize(fitter.fit_object, local_fit_func)
735
- # Make EasyScience.Fitting.Fitter compatible `x`
734
+ # Make EasyScience.fitting.Fitter compatible `x`
736
735
  x_for_fit = xr.concat(bdims, dim='fit_dim')
737
736
  x_for_fit = x_for_fit.stack(all_x=[d.name for d in bdims])
738
737
  try:
@@ -803,7 +802,7 @@ def check_sanity_multiple(fit_results: FitResults, originals: List[xr.DataArray]
803
802
  current_results = fit_results.__class__()
804
803
  # Fill out the basic stuff....
805
804
  current_results.engine_result = fit_results.engine_result
806
- current_results.fitting_engine = fit_results.fitting_engine
805
+ current_results.minimizer_engine = fit_results.minimizer_engine
807
806
  current_results.success = fit_results.success
808
807
  current_results.p = fit_results.p
809
808
  current_results.p0 = fit_results.p0
@@ -17,15 +17,14 @@ from typing import Optional
17
17
  from typing import Tuple
18
18
  from typing import Union
19
19
 
20
- from easyscience import borg
20
+ from easyscience.global_object.undo_redo import NotarizedDict
21
21
  from easyscience.Objects.ObjectClasses import BasedBase
22
22
  from easyscience.Objects.ObjectClasses import Descriptor
23
- from easyscience.Utils.UndoRedo import NotarizedDict
24
23
 
25
24
  if TYPE_CHECKING:
26
- from easyscience.Utils.typing import B
27
- from easyscience.Utils.typing import V
28
- from easyscience.Utils.typing import iF
25
+ from easyscience.Objects.Inferface import iF
26
+ from easyscience.Objects.ObjectClasses import B
27
+ from easyscience.Objects.Variable import V
29
28
 
30
29
 
31
30
  class BaseCollection(BasedBase, MutableSequence):
@@ -75,8 +74,8 @@ class BaseCollection(BasedBase, MutableSequence):
75
74
  for key, item in kwargs.items():
76
75
  _kwargs[key] = item
77
76
  for arg in args:
78
- kwargs[str(borg.map.convert_id_to_key(arg))] = arg
79
- _kwargs[str(borg.map.convert_id_to_key(arg))] = arg
77
+ kwargs[arg.unique_name] = arg
78
+ _kwargs[arg.unique_name] = arg
80
79
 
81
80
  # Set kwargs, also useful for serialization
82
81
  self._kwargs = NotarizedDict(**_kwargs)
@@ -84,8 +83,8 @@ class BaseCollection(BasedBase, MutableSequence):
84
83
  for key in kwargs.keys():
85
84
  if key in self.__dict__.keys() or key in self.__slots__:
86
85
  raise AttributeError(f'Given kwarg: `{key}`, is an internal attribute. Please rename.')
87
- self._borg.map.add_edge(self, kwargs[key])
88
- self._borg.map.reset_type(kwargs[key], 'created_internal')
86
+ self._global_object.map.add_edge(self, kwargs[key])
87
+ self._global_object.map.reset_type(kwargs[key], 'created_internal')
89
88
  if interface is not None:
90
89
  kwargs[key].interface = interface
91
90
  # TODO wrap getter and setter in Logger
@@ -109,13 +108,13 @@ class BaseCollection(BasedBase, MutableSequence):
109
108
  update_key = list(self._kwargs.keys())
110
109
  values = list(self._kwargs.values())
111
110
  # Update the internal dict
112
- new_key = str(borg.map.convert_id_to_key(value))
111
+ new_key = value.unique_name
113
112
  update_key.insert(index, new_key)
114
113
  values.insert(index, value)
115
114
  self._kwargs.reorder(**{k: v for k, v in zip(update_key, values)})
116
115
  # ADD EDGE
117
- self._borg.map.add_edge(self, value)
118
- self._borg.map.reset_type(value, 'created_internal')
116
+ self._global_object.map.add_edge(self, value)
117
+ self._global_object.map.reset_type(value, 'created_internal')
119
118
  value.interface = self.interface
120
119
  else:
121
120
  raise AttributeError('Only EasyScience objects can be put into an EasyScience group')
@@ -174,11 +173,11 @@ class BaseCollection(BasedBase, MutableSequence):
174
173
  update_dict = {update_key[key]: value}
175
174
  self._kwargs.update(update_dict)
176
175
  # ADD EDGE
177
- self._borg.map.add_edge(self, value)
178
- self._borg.map.reset_type(value, 'created_internal')
176
+ self._global_object.map.add_edge(self, value)
177
+ self._global_object.map.reset_type(value, 'created_internal')
179
178
  value.interface = self.interface
180
179
  # REMOVE EDGE
181
- self._borg.map.prune_vertex_from_edge(self, old_item)
180
+ self._global_object.map.prune_vertex_from_edge(self, old_item)
182
181
  else:
183
182
  raise NotImplementedError('At the moment only numerical values or EasyScience objects can be set.')
184
183
 
@@ -193,7 +192,7 @@ class BaseCollection(BasedBase, MutableSequence):
193
192
  """
194
193
  keys = list(self._kwargs.keys())
195
194
  item = self._kwargs[keys[key]]
196
- self._borg.map.prune_vertex_from_edge(self, item)
195
+ self._global_object.map.prune_vertex_from_edge(self, item)
197
196
  del self._kwargs[keys[key]]
198
197
 
199
198
  def __len__(self) -> int:
@@ -4,8 +4,8 @@ from __future__ import annotations
4
4
  # SPDX-License-Identifier: BSD-3-Clause
5
5
  # © 2021-2023 Contributors to the EasyScience project <https://github.com/easyScience/EasyScience
6
6
 
7
- __author__ = "github.com/wardsimon"
8
- __version__ = "0.1.0"
7
+ __author__ = 'github.com/wardsimon'
8
+ __version__ = '0.1.0'
9
9
 
10
10
  from abc import ABCMeta
11
11
  from typing import TYPE_CHECKING
@@ -16,10 +16,10 @@ from typing import Optional
16
16
  from typing import Type
17
17
  from typing import TypeVar
18
18
 
19
- _C = TypeVar("_C", bound=ABCMeta)
20
- _M = TypeVar("_M")
19
+ _C = TypeVar('_C', bound=ABCMeta)
20
+ _M = TypeVar('_M')
21
21
  if TYPE_CHECKING:
22
- from easyscience.Fitting.Fitting import Fitter
22
+ from easyscience.fitting import Fitter
23
23
 
24
24
 
25
25
  class InterfaceFactoryTemplate:
@@ -44,14 +44,14 @@ class InterfaceFactoryTemplate:
44
44
  :return: None
45
45
  :rtype: noneType
46
46
  """
47
- if kwargs.get("interface_name", None) is None:
47
+ if kwargs.get('interface_name', None) is None:
48
48
  if len(self._interfaces) > 0:
49
49
  # Fallback name
50
50
  interface_name = self.return_name(self._interfaces[0])
51
51
  else:
52
52
  raise NotImplementedError
53
53
  else:
54
- interface_name = kwargs.pop("interface_name")
54
+ interface_name = kwargs.pop('interface_name')
55
55
  interfaces = self.available_interfaces
56
56
  if interface_name in interfaces:
57
57
  self._current_interface = self._interfaces[interfaces.index(interface_name)]
@@ -65,7 +65,7 @@ class InterfaceFactoryTemplate:
65
65
  :param new_interface: name of new interface to be created
66
66
  :type new_interface: str
67
67
  :param fitter: Fitting interface which contains the fitting object which may have bindings which will be updated.
68
- :type fitter: EasyScience.Fitting.Fitting.Fitter
68
+ :type fitter: EasyScience.fitting.Fitter
69
69
  :return: None
70
70
  :rtype: noneType
71
71
  """
@@ -74,20 +74,20 @@ class InterfaceFactoryTemplate:
74
74
  self._current_interface = self._interfaces[interfaces.index(new_interface)]
75
75
  self.__interface_obj = self._current_interface()
76
76
  else:
77
- raise AttributeError("The user supplied interface is not valid.")
77
+ raise AttributeError('The user supplied interface is not valid.')
78
78
  if fitter is not None:
79
- if hasattr(fitter, "_fit_object"):
80
- obj = getattr(fitter, "_fit_object")
79
+ if hasattr(fitter, '_fit_object'):
80
+ obj = getattr(fitter, '_fit_object')
81
81
  try:
82
- if hasattr(obj, "update_bindings"):
82
+ if hasattr(obj, 'update_bindings'):
83
83
  obj.update_bindings()
84
84
  except Exception as e:
85
- print(f"Unable to auto generate bindings.\n{e}")
86
- elif hasattr(fitter, "generate_bindings"):
85
+ print(f'Unable to auto generate bindings.\n{e}')
86
+ elif hasattr(fitter, 'generate_bindings'):
87
87
  try:
88
88
  fitter.generate_bindings()
89
89
  except Exception as e:
90
- print(f"Unable to auto generate bindings.\n{e}")
90
+ print(f'Unable to auto generate bindings.\n{e}')
91
91
 
92
92
  @property
93
93
  def available_interfaces(self) -> List[str]:
@@ -152,6 +152,8 @@ class InterfaceFactoryTemplate:
152
152
  :return: binding property
153
153
  :rtype: property
154
154
  """
155
+ import easyscience.Objects.new_variable.parameter
156
+
155
157
  class_links = self.__interface_obj.create(model)
156
158
  props = model._get_linkable_attributes()
157
159
  props_names = [prop.name for prop in props]
@@ -161,8 +163,16 @@ class InterfaceFactoryTemplate:
161
163
  continue
162
164
  idx = props_names.index(item_key)
163
165
  prop = props[idx]
166
+
167
+ ## TODO clean when full move to new_variable
168
+ if isinstance(prop, easyscience.Objects.new_variable.parameter.Parameter):
169
+ # Should be fetched this way to ensure we don't get value from callback
170
+ prop_value = prop.value_no_call_back
171
+ else:
172
+ prop_value = prop.raw_value
173
+
164
174
  prop._callback = item.make_prop(item_key)
165
- prop._callback.fset(prop.raw_value)
175
+ prop._callback.fset(prop_value)
166
176
 
167
177
  def __call__(self, *args, **kwargs) -> _M:
168
178
  return self.__interface_obj
@@ -189,8 +199,8 @@ class InterfaceFactoryTemplate:
189
199
  Return an interfaces name
190
200
  """
191
201
  interface_name = this_interface.__name__
192
- if hasattr(this_interface, "name"):
193
- interface_name = getattr(this_interface, "name")
202
+ if hasattr(this_interface, 'name'):
203
+ interface_name = getattr(this_interface, 'name')
194
204
  return interface_name
195
205
 
196
206
 
@@ -225,4 +235,4 @@ class ItemContainer(NamedTuple):
225
235
  return set_value
226
236
 
227
237
 
228
- iF = TypeVar("iF", bound=InterfaceFactoryTemplate)
238
+ iF = TypeVar('iF', bound=InterfaceFactoryTemplate)
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- __author__ = "github.com/wardsimon"
4
- __version__ = "0.1.0"
3
+ __author__ = 'github.com/wardsimon'
4
+ __version__ = '0.1.0'
5
5
 
6
6
  # SPDX-FileCopyrightText: 2023 EasyScience contributors <core@easyscience.software>
7
7
  # SPDX-License-Identifier: BSD-3-Clause
@@ -16,35 +16,41 @@ from typing import List
16
16
  from typing import Optional
17
17
  from typing import Set
18
18
  from typing import TypeVar
19
+ from typing import Union
19
20
 
20
- from easyscience import borg
21
+ from easyscience import global_object
21
22
  from easyscience.Utils.classTools import addLoggedProp
22
23
 
23
24
  from .core import ComponentSerializer
25
+ from .new_variable import Parameter as NewParameter
26
+ from .new_variable.descriptor_base import DescriptorBase
24
27
  from .Variable import Descriptor
25
28
  from .Variable import Parameter
26
29
 
27
30
  if TYPE_CHECKING:
28
- from easyscience.Utils.typing import C
29
- from easyscience.Utils.typing import V
30
- from easyscience.Utils.typing import iF
31
+ from easyscience.fitting.Constraints import C
32
+ from easyscience.Objects.Inferface import iF
33
+ from easyscience.Objects.Variable import V
31
34
 
32
35
 
33
36
  class BasedBase(ComponentSerializer):
34
- __slots__ = ["_name", "_borg", "user_data", "_kwargs"]
37
+ __slots__ = ['_name', '_global_object', 'user_data', '_kwargs']
35
38
 
36
39
  _REDIRECT = {}
37
40
 
38
- def __init__(self, name: str, interface: Optional[iF] = None):
39
- self._borg = borg
40
- self._borg.map.add_vertex(self, obj_type="created")
41
+ def __init__(self, name: str, interface: Optional[iF] = None, unique_name: Optional[str] = None):
42
+ self._global_object = global_object
43
+ if unique_name is None:
44
+ unique_name = self._global_object.generate_unique_name(self.__class__.__name__)
45
+ self._unique_name = unique_name
46
+ self._name = name
47
+ self._global_object.map.add_vertex(self, obj_type='created')
41
48
  self.interface = interface
42
49
  self.user_data: dict = {}
43
- self._name: str = name
44
50
 
45
51
  @property
46
52
  def _arg_spec(self) -> Set[str]:
47
- base_cls = getattr(self, "__old_class__", self.__class__)
53
+ base_cls = getattr(self, '__old_class__', self.__class__)
48
54
  spec = getfullargspec(base_cls.__init__)
49
55
  names = set(spec.args[1:])
50
56
  return names
@@ -58,9 +64,24 @@ class BasedBase(ComponentSerializer):
58
64
  :rtype: tuple
59
65
  """
60
66
  state = self.encode()
61
- cls = getattr(self, "__old_class__", self.__class__)
67
+ cls = getattr(self, '__old_class__', self.__class__)
62
68
  return cls.from_dict, (state,)
63
69
 
70
+ @property
71
+ def unique_name(self) -> str:
72
+ """Get the unique name of the object."""
73
+ return self._unique_name
74
+
75
+ @unique_name.setter
76
+ def unique_name(self, new_unique_name: str):
77
+ """Set a new unique name for the object. The old name is still kept in the map.
78
+
79
+ :param new_unique_name: New unique name for the object"""
80
+ if not isinstance(new_unique_name, str):
81
+ raise TypeError('Unique name has to be a string.')
82
+ self._unique_name = new_unique_name
83
+ self._global_object.map.add_vertex(self)
84
+
64
85
  @property
65
86
  def name(self) -> str:
66
87
  """
@@ -109,16 +130,14 @@ class BasedBase(ComponentSerializer):
109
130
  :raises: AttributeError
110
131
  """
111
132
  if self.interface is None:
112
- raise AttributeError(
113
- "Interface error for generating bindings. `interface` has to be set."
114
- )
133
+ raise AttributeError('Interface error for generating bindings. `interface` has to be set.')
115
134
  interfaceable_children = [
116
135
  key
117
- for key in self._borg.map.get_edges(self)
118
- if issubclass(type(self._borg.map.get_item_by_key(key)), BasedBase)
136
+ for key in self._global_object.map.get_edges(self)
137
+ if issubclass(type(self._global_object.map.get_item_by_key(key)), BasedBase)
119
138
  ]
120
139
  for child_key in interfaceable_children:
121
- child = self._borg.map.get_item_by_key(child_key)
140
+ child = self._global_object.map.get_item_by_key(child_key)
122
141
  child.interface = self.interface
123
142
  self.interface.generate_bindings(self)
124
143
 
@@ -127,9 +146,7 @@ class BasedBase(ComponentSerializer):
127
146
  Switch or create a new interface.
128
147
  """
129
148
  if self.interface is None:
130
- raise AttributeError(
131
- "Interface error for generating bindings. `interface` has to be set."
132
- )
149
+ raise AttributeError('Interface error for generating bindings. `interface` has to be set.')
133
150
  self.interface.switch(new_interface_name)
134
151
  self.generate_bindings()
135
152
 
@@ -143,7 +160,8 @@ class BasedBase(ComponentSerializer):
143
160
  constraints.append(con[key])
144
161
  return constraints
145
162
 
146
- def get_parameters(self) -> List[Parameter]:
163
+ ## TODO clean when full move to new_variable
164
+ def get_parameters(self) -> Union[List[Parameter], List[NewParameter]]:
147
165
  """
148
166
  Get all parameter objects as a list.
149
167
 
@@ -151,12 +169,13 @@ class BasedBase(ComponentSerializer):
151
169
  """
152
170
  par_list = []
153
171
  for key, item in self._kwargs.items():
154
- if hasattr(item, "get_parameters"):
172
+ if hasattr(item, 'get_parameters'):
155
173
  par_list = [*par_list, *item.get_parameters()]
156
- elif isinstance(item, Parameter):
174
+ elif isinstance(item, Parameter) or isinstance(item, NewParameter):
157
175
  par_list.append(item)
158
176
  return par_list
159
177
 
178
+ ## TODO clean when full move to new_variable
160
179
  def _get_linkable_attributes(self) -> List[V]:
161
180
  """
162
181
  Get all objects which can be linked against as a list.
@@ -165,13 +184,14 @@ class BasedBase(ComponentSerializer):
165
184
  """
166
185
  item_list = []
167
186
  for key, item in self._kwargs.items():
168
- if hasattr(item, "_get_linkable_attributes"):
187
+ if hasattr(item, '_get_linkable_attributes'):
169
188
  item_list = [*item_list, *item._get_linkable_attributes()]
170
- elif issubclass(type(item), Descriptor):
189
+ elif issubclass(type(item), Descriptor) or issubclass(type(item), DescriptorBase):
171
190
  item_list.append(item)
172
191
  return item_list
173
192
 
174
- def get_fit_parameters(self) -> List[Parameter]:
193
+ ## TODO clean when full move to new_variable
194
+ def get_fit_parameters(self) -> Union[List[Parameter], List[NewParameter]]:
175
195
  """
176
196
  Get all objects which can be fitted (and are not fixed) as a list.
177
197
 
@@ -179,10 +199,11 @@ class BasedBase(ComponentSerializer):
179
199
  """
180
200
  fit_list = []
181
201
  for key, item in self._kwargs.items():
182
- if hasattr(item, "get_fit_parameters"):
202
+ if hasattr(item, 'get_fit_parameters'):
183
203
  fit_list = [*fit_list, *item.get_fit_parameters()]
184
- elif isinstance(item, Parameter) and item.enabled and not item.fixed:
185
- fit_list.append(item)
204
+ elif isinstance(item, Parameter) or isinstance(item, NewParameter):
205
+ if item.enabled and not item.fixed:
206
+ fit_list.append(item)
186
207
  return fit_list
187
208
 
188
209
  def __dir__(self) -> Iterable[str]:
@@ -191,13 +212,13 @@ class BasedBase(ComponentSerializer):
191
212
 
192
213
  :return: list of function and parameter names for auto-completion
193
214
  """
194
- new_class_objs = list(k for k in dir(self.__class__) if not k.startswith("_"))
215
+ new_class_objs = list(k for k in dir(self.__class__) if not k.startswith('_'))
195
216
  return sorted(new_class_objs)
196
217
 
197
218
 
198
219
  if TYPE_CHECKING:
199
- B = TypeVar("B", bound=BasedBase)
200
- BV = TypeVar("BV", bound=ComponentSerializer)
220
+ B = TypeVar('B', bound=BasedBase)
221
+ BV = TypeVar('BV', bound=ComponentSerializer)
201
222
 
202
223
 
203
224
  class BaseObj(BasedBase):
@@ -208,9 +229,11 @@ class BaseObj(BasedBase):
208
229
  cheat with `BaseObj(*[Descriptor(...), Parameter(...), ...])`.
209
230
  """
210
231
 
232
+ ## TODO clean when full move to new_variable
211
233
  def __init__(
212
234
  self,
213
235
  name: str,
236
+ unique_name: Optional[str] = None,
214
237
  *args: Optional[BV],
215
238
  **kwargs: Optional[BV],
216
239
  ):
@@ -221,22 +244,22 @@ class BaseObj(BasedBase):
221
244
  :param args: Any arguments?
222
245
  :param kwargs: Fields which this class should contain
223
246
  """
224
- super(BaseObj, self).__init__(name)
247
+ super(BaseObj, self).__init__(name=name, unique_name=unique_name)
225
248
  # If Parameter or Descriptor is given as arguments...
226
249
  for arg in args:
227
- if issubclass(type(arg), (BaseObj, Descriptor)):
228
- kwargs[getattr(arg, "name")] = arg
250
+ if issubclass(type(arg), (BaseObj, Descriptor, DescriptorBase)):
251
+ kwargs[getattr(arg, 'name')] = arg
229
252
  # Set kwargs, also useful for serialization
230
253
  known_keys = self.__dict__.keys()
231
254
  self._kwargs = kwargs
232
255
  for key in kwargs.keys():
233
256
  if key in known_keys:
234
- raise AttributeError
235
- if issubclass(
236
- type(kwargs[key]), (BasedBase, Descriptor)
237
- ) or "BaseCollection" in [c.__name__ for c in type(kwargs[key]).__bases__]:
238
- self._borg.map.add_edge(self, kwargs[key])
239
- self._borg.map.reset_type(kwargs[key], "created_internal")
257
+ raise AttributeError('Kwargs cannot overwrite class attributes in BaseObj.')
258
+ if issubclass(type(kwargs[key]), (BasedBase, Descriptor, DescriptorBase)) or 'BaseCollection' in [
259
+ c.__name__ for c in type(kwargs[key]).__bases__
260
+ ]:
261
+ self._global_object.map.add_edge(self, kwargs[key])
262
+ self._global_object.map.reset_type(kwargs[key], 'created_internal')
240
263
  addLoggedProp(
241
264
  self,
242
265
  key,
@@ -269,8 +292,8 @@ class BaseObj(BasedBase):
269
292
  :return: None
270
293
  """
271
294
  self._kwargs[key] = component
272
- self._borg.map.add_edge(self, component)
273
- self._borg.map.reset_type(component, "created_internal")
295
+ self._global_object.map.add_edge(self, component)
296
+ self._global_object.map.reset_type(component, 'created_internal')
274
297
  addLoggedProp(
275
298
  self,
276
299
  key,
@@ -281,31 +304,32 @@ class BaseObj(BasedBase):
281
304
  test_class=BaseObj,
282
305
  )
283
306
 
307
+ ## TODO clean when full move to new_variable
284
308
  def __setattr__(self, key: str, value: BV) -> None:
285
309
  # Assume that the annotation is a ClassVar
286
310
  old_obj = None
287
311
  if (
288
- hasattr(self.__class__, "__annotations__")
312
+ hasattr(self.__class__, '__annotations__')
289
313
  and key in self.__class__.__annotations__
290
- and hasattr(self.__class__.__annotations__[key], "__args__")
314
+ and hasattr(self.__class__.__annotations__[key], '__args__')
291
315
  and issubclass(
292
- getattr(value, "__old_class__", value.__class__),
316
+ getattr(value, '__old_class__', value.__class__),
293
317
  self.__class__.__annotations__[key].__args__,
294
318
  )
295
319
  ):
296
- if issubclass(type(getattr(self, key, None)), (BasedBase, Descriptor)):
320
+ if issubclass(type(getattr(self, key, None)), (BasedBase, Descriptor, DescriptorBase)):
297
321
  old_obj = self.__getattribute__(key)
298
- self._borg.map.prune_vertex_from_edge(self, old_obj)
322
+ self._global_object.map.prune_vertex_from_edge(self, old_obj)
299
323
  self._add_component(key, value)
300
324
  else:
301
- if hasattr(self, key) and issubclass(type(value), (BasedBase, Descriptor)):
325
+ if hasattr(self, key) and issubclass(type(value), (BasedBase, Descriptor, DescriptorBase)):
302
326
  old_obj = self.__getattribute__(key)
303
- self._borg.map.prune_vertex_from_edge(self, old_obj)
304
- self._borg.map.add_edge(self, value)
327
+ self._global_object.map.prune_vertex_from_edge(self, old_obj)
328
+ self._global_object.map.add_edge(self, value)
305
329
  super(BaseObj, self).__setattr__(key, value)
306
330
  # Update the interface bindings if something changed (BasedBase and Descriptor)
307
331
  if old_obj is not None:
308
- old_interface = getattr(self, "interface", None)
332
+ old_interface = getattr(self, 'interface', None)
309
333
  if old_interface is not None:
310
334
  self.generate_bindings()
311
335
 
@@ -322,9 +346,7 @@ class BaseObj(BasedBase):
322
346
  @staticmethod
323
347
  def __setter(key: str) -> Callable[[BV], None]:
324
348
  def setter(obj: BV, value: float) -> None:
325
- if issubclass(obj._kwargs[key].__class__, Descriptor) and not issubclass(
326
- value.__class__, Descriptor
327
- ):
349
+ if issubclass(obj._kwargs[key].__class__, Descriptor) and not issubclass(value.__class__, Descriptor):
328
350
  obj._kwargs[key].value = value
329
351
  else:
330
352
  obj._kwargs[key] = value