diff --git a/docs/docs/tutorials/tutorial0_basics.ipynb b/docs/docs/tutorials/tutorial0_basics.ipynb index 4f1ad48e..f82781f9 100644 --- a/docs/docs/tutorials/tutorial0_basics.ipynb +++ b/docs/docs/tutorials/tutorial0_basics.ipynb @@ -125,7 +125,7 @@ " \n", "\n", "\n", - "In this data we see a single Gaussian shaped peak and a background that seems to be zero on average. We now want to fit this data, e.g. to determine how the Gaussian changes with $Q$. We define a `Gaussian` like this:" + "In this data we see a single Gaussian shaped peak and a background that seems to be zero on average. We now want to fit this data, e.g. to determine how the Gaussian changes with $Q$. We define a `Gaussian` like this. The `name` will soon be used for indexing, while the `display_name` is what is displayed in figures. By defalut, `display_name` is the same as `name`." ] }, { @@ -135,7 +135,7 @@ "metadata": {}, "outputs": [], "source": [ - "gaussian = sm.Gaussian(display_name='Gaussian', area=1, width=0.05)" + "gaussian = sm.Gaussian(name='Gaussian', area=1, width=0.05)" ] }, { diff --git a/docs/docs/tutorials/tutorial0_more_advanced.ipynb b/docs/docs/tutorials/tutorial0_more_advanced.ipynb index ee1e4e57..70a54d2d 100644 --- a/docs/docs/tutorials/tutorial0_more_advanced.ipynb +++ b/docs/docs/tutorials/tutorial0_more_advanced.ipynb @@ -73,9 +73,9 @@ "metadata": {}, "outputs": [], "source": [ - "gaussian = sm.Gaussian(display_name='Gaussian', area=3, width=0.05)\n", - "lorentzian = sm.Lorentzian(display_name='Lorentzian', area=2, width=0.3)\n", - "dho = sm.DampedHarmonicOscillator(display_name='DHO', area=1.5, width=0.2, center=1.5)\n", + "gaussian = sm.Gaussian(name='Gaussian', area=3, width=0.05)\n", + "lorentzian = sm.Lorentzian(name='Lorentzian', area=2, width=0.3)\n", + "dho = sm.DampedHarmonicOscillator(name='DHO', area=1.5, width=0.2, center=1.5)\n", "\n", "collection = sm.ComponentCollection()\n", "collection.append_component(gaussian)\n", @@ -245,7 +245,7 @@ "id": "af4103fb", "metadata": {}, "source": [ - "The fit looks very good. We can again get a list of the parameters for this fit by accesing the corresponding `Analysis1d` object. Note ethat the Gaussian and Lorentzian centers are both zero, but that the `energy_offset` is non-zero." + "The fit looks very good. We can again get a list of the parameters for this fit by accesing the corresponding `Analysis1d` object. Note that the Gaussian and Lorentzian centers are both zero, but that the `energy_offset` is non-zero." ] }, { diff --git a/docs/docs/tutorials/tutorial1_brownian.ipynb b/docs/docs/tutorials/tutorial1_brownian.ipynb index ea0b90df..9985bc16 100644 --- a/docs/docs/tutorials/tutorial1_brownian.ipynb +++ b/docs/docs/tutorials/tutorial1_brownian.ipynb @@ -120,7 +120,7 @@ "metadata": {}, "outputs": [], "source": [ - "delta_function = DeltaFunction(display_name='DeltaFunction', area=1)\n", + "delta_function = DeltaFunction(name='DeltaFunction', area=1)\n", "sample_model = SampleModel(components=delta_function)" ] }, @@ -144,7 +144,7 @@ "outputs": [], "source": [ "resolution_components = ComponentCollection()\n", - "res_gauss = Gaussian(width=0.1, area=1, display_name='Res. Gauss')\n", + "res_gauss = Gaussian(width=0.1, area=1, name='Res. Gauss')\n", "res_gauss.area.fixed = True\n", "resolution_components.append_component(res_gauss)\n", "resolution_model = ResolutionModel(components=resolution_components)" @@ -352,8 +352,8 @@ "metadata": {}, "outputs": [], "source": [ - "delta_function = DeltaFunction(display_name='DeltaFunction', area=0.2)\n", - "lorentzian = Lorentzian(display_name='Lorentzian', area=0.5, width=0.3)\n", + "delta_function = DeltaFunction(name='DeltaFunction', area=0.2)\n", + "lorentzian = Lorentzian(name='Lorentzian', area=0.5, width=0.3)\n", "component_collection = ComponentCollection(\n", " components=[delta_function, lorentzian],\n", ")\n", @@ -596,12 +596,12 @@ "metadata": {}, "outputs": [], "source": [ - "delta_function = DeltaFunction(display_name='DeltaFunction', area=0.2)\n", + "delta_function = DeltaFunction(name='DeltaFunction', area=0.2)\n", "component_collection = ComponentCollection(\n", " components=[delta_function],\n", ")\n", "diffusion_model = BrownianTranslationalDiffusion(\n", - " display_name='Brownian Translational Diffusion', diffusion_coefficient=2.4e-9, scale=0.5\n", + " name='Brownian Translational Diffusion', diffusion_coefficient=2.4e-9, scale=0.5\n", ")\n", "\n", "sample_model = SampleModel(\n", diff --git a/docs/docs/tutorials/tutorial2_nanoparticles.ipynb b/docs/docs/tutorials/tutorial2_nanoparticles.ipynb index 42eb15ed..a881db87 100644 --- a/docs/docs/tutorials/tutorial2_nanoparticles.ipynb +++ b/docs/docs/tutorials/tutorial2_nanoparticles.ipynb @@ -262,15 +262,15 @@ "outputs": [], "source": [ "sample_model = SampleModel()\n", - "water_delta_function = DeltaFunction(display_name='Water delta function', area=100)\n", - "water_lorentzian = Lorentzian(display_name='Water Lorentzian', area=10, width=0.2)\n", + "water_delta_function = DeltaFunction(name='Water delta function', area=100)\n", + "water_lorentzian = Lorentzian(name='Water Lorentzian', area=10, width=0.2)\n", "sample_model.append_component(water_delta_function)\n", "sample_model.append_component(water_lorentzian)\n", "sample_model.temperature = 150\n", "\n", "\n", "background_model = BackgroundModel()\n", - "polynomial = Polynomial(coefficients=[0.15])\n", + "polynomial = Polynomial(name='Polynomial', coefficients=[0.15])\n", "polynomial.coefficients[0].min = 0.0\n", "background_model.components = polynomial\n", "\n", @@ -396,21 +396,21 @@ "source": [ "# Now make a new analysis with this sample model\n", "mag_sample_model = SampleModel()\n", - "water_delta_function = DeltaFunction(display_name='Water delta function', area=100)\n", - "water_lorentzian = Lorentzian(display_name='Water Lorentzian', area=100, width=0.2)\n", + "water_delta_function = DeltaFunction(name='Water delta function', area=100)\n", + "water_lorentzian = Lorentzian(name='Water Lorentzian', area=100, width=0.2)\n", "mag_sample_model.append_component(water_delta_function)\n", "mag_sample_model.append_component(water_lorentzian)\n", "\n", "# Add all the magnetic components\n", - "DHO1 = DampedHarmonicOscillator(display_name='DHO1', area=5, center=0.35, width=0.2)\n", - "DHO2 = DampedHarmonicOscillator(display_name='DHO2', area=1, center=1.1, width=0.1)\n", - "mag_lorz = Lorentzian(display_name='Magnetic Lorentzian', area=30, width=0.01)\n", + "DHO1 = DampedHarmonicOscillator(name='DHO1', area=5, center=0.35, width=0.2)\n", + "DHO2 = DampedHarmonicOscillator(name='DHO2', area=1, center=1.1, width=0.1)\n", + "mag_lorz = Lorentzian(name='Magnetic Lorentzian', area=30, width=0.01)\n", "mag_sample_model.append_component(DHO1)\n", "mag_sample_model.append_component(DHO2)\n", "mag_sample_model.append_component(mag_lorz)\n", "\n", "background_model = BackgroundModel()\n", - "polynomial = Polynomial(coefficients=[0.15])\n", + "polynomial = Polynomial(name='Polynomial', coefficients=[0.15])\n", "background_model.components = polynomial\n", "\n", "instrument_model = InstrumentModel(\n", diff --git a/src/easydynamics/base_classes/easydynamics_base.py b/src/easydynamics/base_classes/easydynamics_base.py index 1f38c9d3..a5ee70bb 100644 --- a/src/easydynamics/base_classes/easydynamics_base.py +++ b/src/easydynamics/base_classes/easydynamics_base.py @@ -9,8 +9,8 @@ class EasyDynamicsBase(NewBase): def __init__( self, - name: str | None = 'MyEasyDynamicsModel', - display_name: str | None = 'MyEasyDynamicsModel', + name: str = 'MyEasyDynamicsModel', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -18,52 +18,55 @@ def __init__( Parameters ---------- - name : str | None, default='MyEasyDynamicsModel' + name : str, default='MyEasyDynamicsModel' Name of the model. - display_name : str | None, default='MyEasyDynamicsModel' - Display name of the model. + display_name : str | None, default=None + Display name of the model. If None, the name will be used. unique_name : str | None, default=None Unique name of the model. If None, a unique name will be generated. Raises ------ TypeError - If name is not a string or None. + If name is not a string. """ - super().__init__(display_name=display_name, unique_name=unique_name) - - if name is not None and not isinstance(name, str): - raise TypeError('Name must be a string or None.') + if not isinstance(name, str): + raise TypeError('Name must be a string.') self._name = name + if display_name is None: + display_name = name + + super().__init__(display_name=display_name, unique_name=unique_name) + @property - def name(self) -> str | None: + def name(self) -> str: """ Get the name of the model. Returns ------- - str | None + str The name of the model. """ return self._name @name.setter - def name(self, name_str: str | None) -> None: + def name(self, name_str: str) -> None: """ Set the name of the model. Parameters ---------- - name_str : str | None + name_str : str The new name to set. Raises ------ TypeError - If name_str is not a string or None. + If name_str is not a string. """ - if name_str is not None and not isinstance(name_str, str): - raise TypeError('Name must be a string or None.') + if not isinstance(name_str, str): + raise TypeError('Name must be a string.') self._name = name_str diff --git a/src/easydynamics/base_classes/easydynamics_modelbase.py b/src/easydynamics/base_classes/easydynamics_modelbase.py index bf266086..8d21b2b1 100644 --- a/src/easydynamics/base_classes/easydynamics_modelbase.py +++ b/src/easydynamics/base_classes/easydynamics_modelbase.py @@ -13,8 +13,8 @@ class EasyDynamicsModelBase(ModelBase): def __init__( self, unit: str | sc.Unit = 'meV', - name: str | None = 'MyEasyDynamicsModel', - display_name: str | None = 'MyEasyDynamicsModel', + name: str = 'MyEasyDynamicsModel', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -24,25 +24,28 @@ def __init__( ---------- unit : str | sc.Unit, default='meV' Unit of the model. - name : str | None, default='MyEasyDynamicsModel' + name : str, default='MyEasyDynamicsModel' Name of the model. - display_name : str | None, default='MyEasyDynamicsModel' - Display name of the model. + display_name : str | None, default=None + Display name of the model. If None, the name will be used. unique_name : str | None, default=None Unique name of the model. If None, a unique name will be generated. Raises ------ TypeError - If name is not a string or None. + If name is not a string. """ + if not isinstance(name, str): + raise TypeError('Name must be a string.') + self._name = name + + if display_name is None: + display_name = name + super().__init__(display_name=display_name, unique_name=unique_name) self._unit = _validate_unit(unit) - if name is not None and not isinstance(name, str): - raise TypeError('Name must be a string or None.') - self._name = name - @property def unit(self) -> str | sc.Unit | None: """ @@ -77,13 +80,13 @@ def unit(self, _unit_str: str) -> None: ) @property - def name(self) -> str | None: + def name(self) -> str: """ Get the name of the model. Returns ------- - str | None + str The name of the model. """ return self._name @@ -101,9 +104,9 @@ def name(self, name_str: str) -> None: Raises ------ TypeError - If name_str is not a string or None. + If name_str is not a string. """ - if name_str is not None and not isinstance(name_str, str): - raise TypeError('Name must be a string or None.') + if not isinstance(name_str, str): + raise TypeError('Name must be a string.') self._name = name_str diff --git a/src/easydynamics/sample_model/component_collection.py b/src/easydynamics/sample_model/component_collection.py index f5f1a45a..61bf1057 100644 --- a/src/easydynamics/sample_model/component_collection.py +++ b/src/easydynamics/sample_model/component_collection.py @@ -8,41 +8,44 @@ import numpy as np import scipp as sc -from easyscience.base_classes.model_base import ModelBase from easyscience.variable import DescriptorBase from easyscience.variable import Parameter +from easydynamics.base_classes.easydynamics_modelbase import EasyDynamicsModelBase from easydynamics.sample_model.components.model_component import ModelComponent if TYPE_CHECKING: from easydynamics.utils.utils import Numeric -class ComponentCollection(ModelBase): +class ComponentCollection(EasyDynamicsModelBase): """ Collection of model components representing a sample, background or resolution model. """ def __init__( self, + components: list[ModelComponent] | None = None, unit: str | sc.Unit = 'meV', - display_name: str | None = 'MyComponentCollection', + name: str = 'ComponentCollection', + display_name: str | None = None, unique_name: str | None = None, - components: list[ModelComponent] | None = None, ) -> None: """ Initialize a new ComponentCollection. Parameters ---------- + components : list[ModelComponent] | None, default=None + Initial model components to add to the ComponentCollection. unit : str | sc.Unit, default='meV' Unit of the collection. - display_name : str | None, default='MyComponentCollection' + name : str, default='ComponentCollection' + Name of the collection. + display_name : str | None, default=None Display name of the collection. unique_name : str | None, default=None Unique name of the collection. - components : list[ModelComponent] | None, default=None - Initial model components to add to the ComponentCollection. Raises ------ @@ -50,13 +53,13 @@ def __init__( If unit is not a string or sc.Unit, or if components is not a list of ModelComponent. """ - super().__init__(display_name=display_name, unique_name=unique_name) + super().__init__( + unit=unit, + name=name, + display_name=display_name, + unique_name=unique_name, + ) - if unit is not None and not isinstance(unit, (str, sc.Unit)): - raise TypeError( - f'unit must be None, a string, or a scipp Unit, got {type(unit).__name__}' - ) - self._unit = unit self._components = [] # Add initial components if provided. Used for serialization. @@ -142,39 +145,6 @@ def is_empty(self, _value: bool) -> None: 'whether the collection has components.' ) - @property - def unit(self) -> str | sc.Unit | None: - """ - Get the unit of the ComponentCollection. - - Returns - ------- - str | sc.Unit | None - The unit of the ComponentCollection, which is the same as the unit of its components. - """ - return self._unit - - @unit.setter - def unit(self, _unit_str: str) -> None: - """ - Unit is read-only and cannot be set directly. - - Parameters - ---------- - _unit_str : str - The unit to set (ignored). - - Raises - ------ - AttributeError - Always raised since unit is read-only. - """ - - raise AttributeError( - f'Unit is read-only. Use convert_unit to change the unit between allowed types ' - f'or create a new {self.__class__.__name__} with the desired unit.' - ) - def convert_unit(self, unit: str | sc.Unit) -> None: """ Convert the unit of the ComponentCollection and all its components. diff --git a/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py b/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py index d74b9116..86fd6c0b 100644 --- a/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py +++ b/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py @@ -30,7 +30,8 @@ def __init__( center: Numeric | Parameter = 1.0, width: Numeric | Parameter = 1.0, unit: str | sc.Unit = 'meV', - display_name: str | None = 'DampedHarmonicOscillator', + name: str = 'DampedHarmonicOscillator', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -47,7 +48,9 @@ def __init__( default, 1.0. unit : str | sc.Unit, default='meV' Unit of the parameters. - display_name : str | None, default='DampedHarmonicOscillator' + name : str, default='DampedHarmonicOscillator' + Name of the component for indexing. + display_name : str | None, default=None Display name of the component. unique_name : str | None, default=None Unique name of the component. If None, a unique_name is automatically generated. By @@ -55,22 +58,23 @@ def __init__( """ super().__init__( + name=name, display_name=display_name, unique_name=unique_name, unit=unit, ) # These methods live in ValidationMixin - area = self._create_area_parameter(area=area, name=display_name, unit=self._unit) + area = self._create_area_parameter(area=area, name=name, unit=self._unit) center = self._create_center_parameter( center=center, - name=display_name, + name=name, fix_if_none=False, unit=self._unit, enforce_minimum_center=True, ) - width = self._create_width_parameter(width=width, name=display_name, unit=self._unit) + width = self._create_width_parameter(width=width, name=name, unit=self._unit) self._area = area self._center = center @@ -217,7 +221,9 @@ def __repr__(self) -> str: A string representation of the Damped Harmonic Oscillator. """ return ( - f'DampedHarmonicOscillator(display_name = {self.display_name}, ' + f'DampedHarmonicOscillator(name = {self.name}, display_name = {self.display_name}, ' f'unit = {self._unit},\n ' - f'area = {self.area},\n center = {self.center},\n width = {self.width})' + f' area = {self.area},\n ' + f' center = {self.center},\n ' + f' width = {self.width})' ) diff --git a/src/easydynamics/sample_model/components/delta_function.py b/src/easydynamics/sample_model/components/delta_function.py index e3720f8b..d63780fa 100644 --- a/src/easydynamics/sample_model/components/delta_function.py +++ b/src/easydynamics/sample_model/components/delta_function.py @@ -33,7 +33,8 @@ def __init__( center: Numeric | Parameter | None = None, area: Numeric | Parameter = 1.0, unit: str | sc.Unit = 'meV', - display_name: str | None = 'DeltaFunction', + name: str = 'DeltaFunction', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -42,28 +43,31 @@ def __init__( Parameters ---------- center : Numeric | Parameter | None, default=None - Center of the delta function. If None. + Center of the delta function. If None, it will be centered at 0 and fixed. area : Numeric | Parameter, default=1.0 Total area under the curve. unit : str | sc.Unit, default='meV' Unit of the parameters. - display_name : str | None, default='DeltaFunction' - Name of the component. + name : str, default='DeltaFunction' + Name of the component for indexing. + display_name : str | None, default=None + Display name of the component. unique_name : str | None, default=None Unique name of the component. If None, a unique_name is automatically generated. By default, None. """ # Validate inputs and create Parameters if not given super().__init__( - display_name=display_name, unit=unit, + name=name, + display_name=display_name, unique_name=unique_name, ) # These methods live in ValidationMixin - area = self._create_area_parameter(area=area, name=display_name, unit=self._unit) + area = self._create_area_parameter(area=area, name=name, unit=self._unit) center = self._create_center_parameter( - center=center, name=display_name, fix_if_none=True, unit=self._unit + center=center, name=name, fix_if_none=True, unit=self._unit ) self._area = area @@ -196,6 +200,8 @@ def __repr__(self) -> str: """ return ( - f'DeltaFunction(unique_name = {self.unique_name}, unit = {self._unit},\n' - f'area = {self.area},\n center = {self.center})' + f'DeltaFunction(name = {self.name}, display_name = {self.display_name}, ' + f'unit = {self.unit},\n' + f' area = {self.area},\n' + f' center = {self.center})' ) diff --git a/src/easydynamics/sample_model/components/exponential.py b/src/easydynamics/sample_model/components/exponential.py index f06e8138..b331b162 100644 --- a/src/easydynamics/sample_model/components/exponential.py +++ b/src/easydynamics/sample_model/components/exponential.py @@ -29,7 +29,8 @@ def __init__( center: Numeric | Parameter | None = None, rate: Numeric | Parameter = 1.0, unit: str | sc.Unit = 'meV', - display_name: str | None = 'Exponential', + name: str = 'Exponential', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -45,10 +46,12 @@ def __init__( Decay or growth constant of the Exponential. unit : str | sc.Unit, default='meV' Unit of the parameters. - display_name : str | None, default='Exponential' - Name of the component. + name : str, default='Exponential' + Name of the component for indexing. + display_name : str | None, default=None + Display name of the component. unique_name : str | None, default=None - Unique name of the component. if None, a unique_name is automatically generated. By + Unique name of the component. If None, a unique_name is automatically generated. By default, None. Raises @@ -60,8 +63,9 @@ def __init__( """ # Validate inputs and create Parameters if not given super().__init__( - display_name=display_name, unit=unit, + name=name, + display_name=display_name, unique_name=unique_name, ) @@ -72,12 +76,10 @@ def __init__( if not np.isfinite(amplitude): raise ValueError('amplitude must be a finite number or a Parameter') - amplitude = Parameter( - name=display_name + ' amplitude', value=float(amplitude), unit=unit - ) + amplitude = Parameter(name=name + ' amplitude', value=float(amplitude), unit=unit) center = self._create_center_parameter( - center=center, name=display_name, fix_if_none=True, unit=self._unit + center=center, name=name, fix_if_none=True, unit=self._unit ) if not isinstance(rate, (Parameter, Numeric)): @@ -87,7 +89,7 @@ def __init__( if not np.isfinite(rate): raise ValueError('rate must be a finite number or a Parameter') - rate = Parameter(name=display_name + ' rate', value=float(rate), unit='1/' + str(unit)) + rate = Parameter(name=name + ' rate', value=float(rate), unit='1/' + str(unit)) self._amplitude = amplitude self._center = center @@ -270,5 +272,10 @@ def __repr__(self) -> str: A string representation of the Exponential. """ - return f'Exponential(unique_name = {self.unique_name}, unit = {self._unit},\n \ - amplitude = {self.amplitude},\n center = {self.center},\n rate = {self.rate})' + return ( + f'Exponential(name = {self.name}, display_name = {self.display_name}, ' + f'unit = {self._unit},\n ' + f' amplitude = {self.amplitude},\n ' + f' center = {self.center},\n ' + f' rate = {self.rate})' + ) diff --git a/src/easydynamics/sample_model/components/expression_component.py b/src/easydynamics/sample_model/components/expression_component.py index e51de905..5255a940 100644 --- a/src/easydynamics/sample_model/components/expression_component.py +++ b/src/easydynamics/sample_model/components/expression_component.py @@ -71,7 +71,8 @@ def __init__( expression: str, parameters: dict[str, Numeric] | None = None, unit: str | sc.Unit = 'meV', - display_name: str | None = 'Expression', + name: str = 'Expression', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -85,7 +86,9 @@ def __init__( Dictionary of parameter names and their initial values. unit : str | sc.Unit, default='meV' Unit of the output. - display_name : str | None, default='Expression' + name : str, default='Expression' + Name of the component for indexing. + display_name : str | None, default=None Display name for the component. unique_name : str | None, default=None Unique name for the component. @@ -109,7 +112,7 @@ def __init__( >>> expr.A = 5 >>> y = expr.evaluate(x) """ - super().__init__(unit=unit, display_name=display_name, unique_name=unique_name) + super().__init__(unit=unit, name=name, display_name=display_name, unique_name=unique_name) if 'np.' in expression: raise ValueError( @@ -367,9 +370,8 @@ def __repr__(self) -> str: """ param_str = ', '.join(f'{k}={v.value}' for k, v in self._parameters.items()) return ( - f'{self.__class__.__name__}(\n' - f" expr='{self._expression_str}',\n" - f' unit={self._unit},\n' - f' parameters={{ {param_str} }}\n' - f')' + f'ExpressionComponent(name={self.name}, display_name={self.display_name}, ' + f'unit={self._unit},\n' + f" expr='{self._expression_str}',\n" + f' parameters={{ {param_str} }} )' ) diff --git a/src/easydynamics/sample_model/components/gaussian.py b/src/easydynamics/sample_model/components/gaussian.py index 4e9629c1..54cfe97c 100644 --- a/src/easydynamics/sample_model/components/gaussian.py +++ b/src/easydynamics/sample_model/components/gaussian.py @@ -37,7 +37,8 @@ def __init__( center: Numeric | Parameter | None = None, width: Numeric | Parameter = 1.0, unit: str | sc.Unit = 'meV', - display_name: str | None = 'Gaussian', + name: str = 'Gaussian', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -53,7 +54,9 @@ def __init__( Standard deviation. unit : str | sc.Unit, default='meV' Unit of the parameters. - display_name : str | None, default='Gaussian' + name : str, default='Gaussian' + Name of the component for indexing. + display_name : str | None, default=None Name of the component. unique_name : str | None, default=None Unique name of the component. if None, a unique_name is automatically generated. By @@ -61,17 +64,18 @@ def __init__( """ # Validate inputs and create Parameters if not given super().__init__( - display_name=display_name, unit=unit, + name=name, + display_name=display_name, unique_name=unique_name, ) # These methods live in ValidationMixin - area = self._create_area_parameter(area=area, name=display_name, unit=self._unit) + area = self._create_area_parameter(area=area, name=name, unit=self._unit) center = self._create_center_parameter( - center=center, name=display_name, fix_if_none=True, unit=self._unit + center=center, name=name, fix_if_none=True, unit=self._unit ) - width = self._create_width_parameter(width=width, name=display_name, unit=self._unit) + width = self._create_width_parameter(width=width, name=name, unit=self._unit) self._area = area self._center = center @@ -225,6 +229,9 @@ def __repr__(self) -> str: """ return ( - f'Gaussian(unique_name = {self.unique_name}, unit = {self._unit},\n' - f'area = {self.area},\n center = {self.center},\n width = {self.width})' + f'Gaussian(name = {self.name}, display_name = {self.display_name}, ' + f'unit = {self._unit},\n' + f' area = {self.area},\n' + f' center = {self.center},\n' + f' width = {self.width})' ) diff --git a/src/easydynamics/sample_model/components/lorentzian.py b/src/easydynamics/sample_model/components/lorentzian.py index d86b1ed6..81453fb8 100644 --- a/src/easydynamics/sample_model/components/lorentzian.py +++ b/src/easydynamics/sample_model/components/lorentzian.py @@ -34,7 +34,8 @@ def __init__( center: Numeric | Parameter | None = None, width: Numeric | Parameter = 1.0, unit: str | sc.Unit = 'meV', - display_name: str | None = 'Lorentzian', + name: str = 'Lorentzian', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -45,30 +46,33 @@ def __init__( area : Numeric | Parameter, default=1.0 Area of the Lorentzian. center : Numeric | Parameter | None, default=None - Center of the Lorentzian. If None. + Center of the Lorentzian. If None, defaults to 0 and is fixed. width : Numeric | Parameter, default=1.0 Half width at half maximum (HWHM). unit : str | sc.Unit, default='meV' Unit of the parameters. - display_name : str | None, default='Lorentzian' - Name of the component. + name : str, default='Lorentzian' + Name of the component for indexing. + display_name : str | None, default=None + Display name for the component. unique_name : str | None, default=None Unique name of the component. If None, a unique_name is automatically generated. By default, None. """ super().__init__( - display_name=display_name, unit=unit, + name=name, + display_name=display_name, unique_name=unique_name, ) # These methods live in ValidationMixin - area = self._create_area_parameter(area=area, name=display_name, unit=self._unit) + area = self._create_area_parameter(area=area, name=name, unit=self._unit) center = self._create_center_parameter( - center=center, name=display_name, fix_if_none=True, unit=self._unit + center=center, name=name, fix_if_none=True, unit=self._unit ) - width = self._create_width_parameter(width=width, name=display_name, unit=self._unit) + width = self._create_width_parameter(width=width, name=name, unit=self._unit) self._area = area self._center = center @@ -216,6 +220,9 @@ def __repr__(self) -> str: A string representation of the Lorentzian. """ return ( - f'Lorentzian(unique_name = {self.unique_name}, unit = {self._unit},\n' - f'area = {self.area},\n center = {self.center},\n width = {self.width})' + f'Lorentzian(name = {self.name}, display_name = {self.display_name}, ' + f'unit = {self._unit},\n' + f' area = {self.area},\n' + f' center = {self.center},\n' + f' width = {self.width})' ) diff --git a/src/easydynamics/sample_model/components/model_component.py b/src/easydynamics/sample_model/components/model_component.py index 6d0f9a0e..84c88453 100644 --- a/src/easydynamics/sample_model/components/model_component.py +++ b/src/easydynamics/sample_model/components/model_component.py @@ -20,6 +20,7 @@ class ModelComponent(EasyDynamicsModelBase): def __init__( self, unit: str | sc.Unit = 'meV', + name: str = 'ModelComponent', display_name: str | None = None, unique_name: str | None = None, ) -> None: @@ -30,13 +31,19 @@ def __init__( ---------- unit : str | sc.Unit, default='meV' The unit of the model component. + name : str, default='ModelComponent' + The name of the model component for indexing. display_name : str | None, default=None A human-readable name for the component. unique_name : str | None, default=None A unique identifier for the component. """ - super().__init__(unit=unit, display_name=display_name, unique_name=unique_name) - self._unit = unit + super().__init__( + unit=unit, + name=name, + display_name=display_name, + unique_name=unique_name, + ) @property def unit(self) -> str: diff --git a/src/easydynamics/sample_model/components/polynomial.py b/src/easydynamics/sample_model/components/polynomial.py index cd3cd997..03e7eae7 100644 --- a/src/easydynamics/sample_model/components/polynomial.py +++ b/src/easydynamics/sample_model/components/polynomial.py @@ -31,7 +31,8 @@ def __init__( self, coefficients: Sequence[Numeric | Parameter] = (0.0,), unit: str | sc.Unit = 'meV', - display_name: str | None = 'Polynomial', + name: str = 'Polynomial', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -43,7 +44,9 @@ def __init__( Coefficients c0, c1, ..., cN. unit : str | sc.Unit, default='meV' Unit of the Polynomial component. - display_name : str | None, default='Polynomial' + name : str, default='Polynomial' + Name of the component for indexing. + display_name : str | None, default=None Display name of the Polynomial component. unique_name : str | None, default=None Unique name of the component. If None, a unique_name is automatically generated. By @@ -58,7 +61,12 @@ def __init__( If coefficients is an empty sequence. """ - super().__init__(display_name=display_name, unit=unit, unique_name=unique_name) + super().__init__( + unit=unit, + name=name, + display_name=display_name, + unique_name=unique_name, + ) if not isinstance(coefficients, (list, tuple, np.ndarray)): raise TypeError( @@ -77,7 +85,7 @@ def __init__( if isinstance(coef, Parameter): param = coef elif isinstance(coef, Numeric): - param = Parameter(name=f'{display_name}_c{i}', value=float(coef)) + param = Parameter(name=f'{name}_c{i}', value=float(coef)) else: raise TypeError('Each coefficient must be either a numeric value or a Parameter.') self._coefficients.append(param) @@ -264,6 +272,7 @@ def __repr__(self) -> str: coeffs_str = ', '.join(f'{param.name}={param.value}' for param in self._coefficients) return ( - f'Polynomial(unique_name = {self.unique_name}, ' - f'unit = {self._unit},\n coefficients = [{coeffs_str}])' + f'Polynomial(name = {self.name}, display_name = {self.display_name}, ' + f'unit = {self._unit},\n' + f' coefficients = [{coeffs_str}])' ) diff --git a/src/easydynamics/sample_model/components/voigt.py b/src/easydynamics/sample_model/components/voigt.py index 4aafd03b..5c5787b6 100644 --- a/src/easydynamics/sample_model/components/voigt.py +++ b/src/easydynamics/sample_model/components/voigt.py @@ -34,7 +34,8 @@ def __init__( gaussian_width: Numeric | Parameter = 1.0, lorentzian_width: Numeric | Parameter = 1.0, unit: str | sc.Unit = 'meV', - display_name: str | None = 'Voigt', + name: str = 'Voigt', + display_name: str | None = None, unique_name: str | None = None, ) -> None: """ @@ -52,7 +53,9 @@ def __init__( Half width at half max (HWHM) of the Lorentzian part. unit : str | sc.Unit, default='meV' Unit of the parameters. - display_name : str | None, default='Voigt' + name : str, default='Voigt' + Name of the component for indexing. + display_name : str | None, default=None Display name of the component. unique_name : str | None, default=None Unique name of the component. If None, a unique_name is automatically generated. By @@ -60,25 +63,26 @@ def __init__( """ super().__init__( - display_name=display_name, unit=unit, + name=name, + display_name=display_name, unique_name=unique_name, ) # These methods live in ValidationMixin - area = self._create_area_parameter(area=area, name=display_name, unit=self._unit) + area = self._create_area_parameter(area=area, name=name, unit=self._unit) center = self._create_center_parameter( - center=center, name=display_name, fix_if_none=True, unit=self._unit + center=center, name=name, fix_if_none=True, unit=self._unit ) gaussian_width = self._create_width_parameter( width=gaussian_width, - name=display_name, + name=name, param_name='gaussian_width', unit=self._unit, ) lorentzian_width = self._create_width_parameter( width=lorentzian_width, - name=display_name, + name=name, param_name='lorentzian_width', unit=self._unit, ) @@ -261,9 +265,9 @@ def __repr__(self) -> str: """ return ( - f'Voigt(unique_name = {self.unique_name}, unit = {self._unit},\n' - f'area = {self.area},\n' - f'center = {self.center},\n' - f'gaussian_width = {self.gaussian_width},\n' - f'lorentzian_width = {self.lorentzian_width})' + f'Voigt(name = {self.name}, display_name = {self.display_name}, unit = {self._unit},\n' + f' area = {self.area},\n' + f' center = {self.center},\n' + f' gaussian_width = {self.gaussian_width},\n' + f' lorentzian_width = {self.lorentzian_width})' ) diff --git a/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py b/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py index b3872d9a..a3d43ab7 100644 --- a/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py +++ b/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py @@ -26,38 +26,45 @@ class BrownianTranslationalDiffusion(DiffusionModelBase): have units of 1/angstrom. Creates ComponentCollections with Lorentzian components for given Q-values. - Example: >>>Q=np.linspace(0.5,2,7) >>>energy=np.linspace(-2, 2, 501) >>>scale=1.0 - >>>diffusion_coefficient = 2.4e-9 # m^2/s - >>>diffusion_model=BrownianTranslationalDiffusion(display_name="DiffusionModel", - >>>scale=scale, diffusion_coefficient= diffusion_coefficient) - >>>component_collections=diffusion_model.create_component_collections(Q) See also the - tutorials. + Examples + -------- + >>> Q=np.linspace(0.5,2,7) >>>energy=np.linspace(-2, 2, 501) + >>> scale = 1.0 + >>> diffusion_coefficient = 2.4e-9 # m^2/s + >>> diffusion_model=BrownianTranslationalDiffusion(name="DiffusionModel", + >>> scale=scale, diffusion_coefficient= diffusion_coefficient,) + >>> component_collections = diffusion_model.create_component_collections(Q) + + See also the tutorials. """ def __init__( self, - display_name: str | None = 'BrownianTranslationalDiffusion', - unique_name: str | None = None, - unit: str | sc.Unit = 'meV', scale: Numeric = 1.0, diffusion_coefficient: Numeric = 1.0, + unit: str | sc.Unit = 'meV', + name: str = 'BrownianTranslationalDiffusion', + display_name: str | None = 'BrownianTranslationalDiffusion', + unique_name: str | None = None, ) -> None: """ Initialize a new BrownianTranslationalDiffusion model. Parameters ---------- + scale : Numeric, default=1.0 + Scale factor for the diffusion model. Must be a non-negative number. + diffusion_coefficient : Numeric, default=1.0 + Diffusion coefficient D in m^2/s. + unit : str | sc.Unit, default='meV' + Unit of the diffusion model. Must be convertible to meV. + name : str, default='BrownianTranslationalDiffusion' + Name of the diffusion model. display_name : str | None, default='BrownianTranslationalDiffusion' Display name of the diffusion model. unique_name : str | None, default=None Unique name of the diffusion model. If None, a unique name will be generated. By default, None. - unit : str | sc.Unit, default='meV' - Unit of the diffusion model. Must be convertible to meV. - scale : Numeric, default=1.0 - Scale factor for the diffusion model. Must be a non-negative number. - diffusion_coefficient : Numeric, default=1.0 - Diffusion coefficient D in m^2/s. Raises ------ @@ -78,10 +85,11 @@ def __init__( min=0.0, ) super().__init__( - display_name=display_name, - unique_name=unique_name, unit=unit, scale=scale, + name=name, + display_name=display_name, + unique_name=unique_name, ) self._hbar = hbar self._angstrom = angstrom @@ -191,6 +199,7 @@ def calculate_QISF(self, Q: Q_type) -> np.ndarray: def create_component_collections( self, Q: Q_type, + component_name: str = 'Brownian diffusion', component_display_name: str = 'Brownian diffusion', ) -> list[ComponentCollection]: r""" @@ -201,13 +210,15 @@ def create_component_collections( ---------- Q : Q_type Scattering vector values. + component_name : str, default='Brownian diffusion' + Name of the Brownian diffusion component. component_display_name : str, default='Brownian diffusion' - Name of the Lorentzian component. + Display name of the Brownian diffusion component. Raises ------ TypeError - If component_display_name is not a string. + If component_display_name is not a string. If component_name is not a string. Returns ------- @@ -219,6 +230,9 @@ def create_component_collections( Q = _validate_and_convert_Q(Q) if not isinstance(component_display_name, str): + raise TypeError('component_display_name must be a string.') + + if not isinstance(component_name, str): raise TypeError('component_name must be a string.') component_collection_list = [None] * len(Q) @@ -231,10 +245,13 @@ def create_component_collections( # No delta function, as the EISF is 0. for i, Q_value in enumerate(Q): component_collection_list[i] = ComponentCollection( - display_name=f'{self.display_name}_Q{Q_value:.2f}', unit=self.unit + name=f'{self.name}_Q{Q_value:.2f}', + display_name=f'{self.display_name}_Q{Q_value:.2f}', + unit=self.unit, ) lorentzian_component = Lorentzian( + name=component_name, display_name=component_display_name, unit=self.unit, ) @@ -356,6 +373,8 @@ def __repr__(self) -> str: String representation of the BrownianTranslationalDiffusion model. """ return ( - f'BrownianTranslationalDiffusion(display_name={self.display_name},' - f'diffusion_coefficient={self.diffusion_coefficient}, scale={self.scale})' + f'BrownianTranslationalDiffusion(name={self.name}, ' + f'display_name={self.display_name}, \n' + f' diffusion_coefficient={self.diffusion_coefficient}, \n' + f' scale={self.scale})' ) diff --git a/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py b/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py index 0e83351e..95732680 100644 --- a/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py +++ b/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py @@ -15,25 +15,28 @@ class DiffusionModelBase(EasyDynamicsModelBase): def __init__( self, - display_name: str | None = 'MyDiffusionModel', - unique_name: str | None = None, scale: Numeric = 1.0, unit: str | sc.Unit = 'meV', + name: str = 'DiffusionModel', + display_name: str | None = 'MyDiffusionModel', + unique_name: str | None = None, ) -> None: """ Initialize a new DiffusionModel. Parameters ---------- + scale : Numeric, default=1.0 + Scale factor for the diffusion model. Must be a non-negative number. + unit : str | sc.Unit, default='meV' + Unit of the diffusion model. Must be convertible to meV. + name : str, default='DiffusionModel' + Name of the diffusion model. display_name : str | None, default='MyDiffusionModel' Display name of the diffusion model. unique_name : str | None, default=None Unique name of the diffusion model. If None, a unique name will be generated. By default, None. - scale : Numeric, default=1.0 - Scale factor for the diffusion model. Must be a non-negative number. - unit : str | sc.Unit, default='meV' - Unit of the diffusion model. Must be convertible to meV. Raises ------ @@ -56,7 +59,7 @@ def __init__( scale = Parameter(name='scale', value=float(scale), fixed=False, min=0.0, unit=unit) - super().__init__(display_name=display_name, unique_name=unique_name, unit=unit) + super().__init__(unit=unit, name=name, display_name=display_name, unique_name=unique_name) self._scale = scale # ------------------------------------------------------------------ @@ -97,7 +100,7 @@ def scale(self, scale: Numeric) -> None: if float(scale) < 0: raise ValueError('scale must be non-negative.') - self._scale.value = scale + self._scale.value = float(scale) # ------------------------------------------------------------------ # dunder methods @@ -112,4 +115,8 @@ def __repr__(self) -> str: str String representation of the DiffusionModel. """ - return f'{self.__class__.__name__}(display_name={self.display_name}, unit={self.unit})' + return ( + f'{self.__class__.__name__}(name={self.name}, display_name={self.display_name}, ' + f'unit={self.unit}), \n' + f' scale={self.scale})' + ) diff --git a/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py b/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py index 346ce152..0d4b4441 100644 --- a/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py +++ b/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py @@ -29,40 +29,53 @@ class JumpTranslationalDiffusion(DiffusionModelBase): units of 1/angstrom. Creates ComponentCollections with Lorentzian components for given Q-values. - Example: >>> Q = np.linspace(0.5, 2, 7) >>> energy = np.linspace(-2, 2, 501) >>> scale = 1.0 - >>> diffusion_coefficient = 2.4e-9 # m^2/s >>> relaxation_time = 1.0 # ps >>> - diffusion_model=JumpTranslationalDiffusion( >>> scale = scale, diffusion_coefficient = - (diffusion_coefficient,) >>> relaxation_time=relaxation_time) >>> component_collections= >>> - diffusion_model.create_component_collections(Q) See also the tutorials.. + Examples + -------- + >>> Q = np.linspace(0.5, 2, 7) + >>> energy = np.linspace(-2, 2, 501) + >>> scale = 1.0 + >>> diffusion_coefficient = 2.4e-9 # m^2/s + >>> relaxation_time = 1.0 # ps + >>> diffusion_model = JumpTranslationalDiffusion( + ... scale=scale, + ... diffusion_coefficient=diffusion_coefficient, + ... relaxation_time=relaxation_time, + ... ) + >>> component_collections = diffusion_model.create_component_collections(Q) + + See also the tutorials.. """ def __init__( self, - display_name: str | None = 'JumpTranslationalDiffusion', - unique_name: str | None = None, - unit: str | sc.Unit = 'meV', scale: Numeric = 1.0, diffusion_coefficient: Numeric = 1.0, relaxation_time: Numeric = 1.0, + unit: str | sc.Unit = 'meV', + name: str = 'JumpTranslationalDiffusion', + display_name: str | None = 'JumpTranslationalDiffusion', + unique_name: str | None = None, ) -> None: """ Initialize a new JumpTranslationalDiffusion model. Parameters ---------- - display_name : str | None, default='JumpTranslationalDiffusion' - Display name of the diffusion model. - unique_name : str | None, default=None - Unique name of the diffusion model. If None, a unique name will be generated. By - default, None. - unit : str | sc.Unit, default='meV' - Unit of the diffusion model. Must be convertible to meV. scale : Numeric, default=1.0 Scale factor for the diffusion model. Must be a non-negative number. diffusion_coefficient : Numeric, default=1.0 Diffusion coefficient D in m^2/s. relaxation_time : Numeric, default=1.0 Relaxation time t in ps. + unit : str | sc.Unit, default='meV' + Unit of the diffusion model. Must be convertible to meV. + name : str, default='JumpTranslationalDiffusion' + Name of the diffusion model. + display_name : str | None, default='JumpTranslationalDiffusion' + Display name of the diffusion model. + unique_name : str | None, default=None + Unique name of the diffusion model. If None, a unique name will be generated. By + default, None. Raises ------ @@ -70,6 +83,7 @@ def __init__( If scale, diffusion_coefficient, or relaxation_time are not numbers. """ super().__init__( + name=name, display_name=display_name, unique_name=unique_name, unit=unit, @@ -251,6 +265,7 @@ def calculate_QISF(self, Q: Q_type) -> np.ndarray: def create_component_collections( self, Q: Q_type, + component_name: str = 'Jump translational diffusion', component_display_name: str = 'Jump translational diffusion', ) -> list[ComponentCollection]: """ @@ -260,13 +275,15 @@ def create_component_collections( ---------- Q : Q_type Scattering vector in 1/angstrom. Can be a single value or an array of values. + component_name : str, default='Jump translational diffusion' + Name of the Jump Diffusion Lorentzian component. component_display_name : str, default='Jump translational diffusion' Name of the Jump Diffusion Lorentzian component. Raises ------ TypeError - If component_display_name is not a string. + If component_display_name is not a string. If component_name is not a string. Returns ------- @@ -276,6 +293,9 @@ def create_component_collections( Q = _validate_and_convert_Q(Q) if not isinstance(component_display_name, str): + raise TypeError('component_display_name must be a string.') + + if not isinstance(component_name, str): raise TypeError('component_name must be a string.') component_collection_list = [None] * len(Q) @@ -288,10 +308,13 @@ def create_component_collections( # is 0. for i, Q_value in enumerate(Q): component_collection_list[i] = ComponentCollection( - display_name=f'{self.display_name}_Q{Q_value:.2f}', unit=self.unit + name=f'{self.name}_Q{Q_value:.2f}', + display_name=f'{self.display_name}_Q{Q_value:.2f}', + unit=self.unit, ) lorentzian_component = Lorentzian( + name=component_name, display_name=component_display_name, unit=self.unit, ) @@ -415,6 +438,7 @@ def __repr__(self) -> str: String representation of the JumpTranslationalDiffusion model. """ return ( - f'JumpTranslationalDiffusion(display_name={self.display_name}, ' - f'diffusion_coefficient={self._diffusion_coefficient}, scale={self._scale})' + f'JumpTranslationalDiffusion(name={self.name}, display_name={self.display_name},\n ' + f' diffusion_coefficient={self._diffusion_coefficient}, \n' + f' scale={self._scale})' ) diff --git a/tests/unit/easydynamics/analysis/test_analysis.py b/tests/unit/easydynamics/analysis/test_analysis.py index 64949fa6..cf9594db 100644 --- a/tests/unit/easydynamics/analysis/test_analysis.py +++ b/tests/unit/easydynamics/analysis/test_analysis.py @@ -30,7 +30,9 @@ def analysis(self): data_array = sc.DataArray(data=data, coords={'Q': Q, 'energy': energy}) experiment = Experiment(data=data_array) - sample_model = SampleModel(components=Gaussian(), display_name='Gaussian') + sample_model = SampleModel( + components=Gaussian(name='GaussianName'), display_name='Gaussian' + ) instrument_model = InstrumentModel() return Analysis( @@ -55,7 +57,9 @@ def analysis_single_Q(self): experiment = Experiment(data=data_array) experiment.rebin({'Q': 1}) - sample_model = SampleModel(components=Gaussian(), display_name='Gaussian') + sample_model = SampleModel( + components=Gaussian(name='GaussianName'), display_name='Gaussian' + ) instrument_model = InstrumentModel() return Analysis( @@ -400,19 +404,21 @@ def test_data_and_model_to_datagroup_include_components_not_bool_raises(self, an def test_parameters_to_dataset(self, analysis): # WHEN - analysis.sample_model.append_component(Gaussian(display_name='Gaussian2', area=0.5)) + analysis.sample_model.append_component( + Gaussian(name='Gaussian2Name', display_name='Gaussian2', area=0.5) + ) # THEN parameters_dataset = analysis.parameters_to_dataset() # EXPECT assert isinstance(parameters_dataset, sc.Dataset) parameter_names = [ - 'Gaussian area', - 'Gaussian center', - 'Gaussian width', - 'Gaussian2 area', - 'Gaussian2 center', - 'Gaussian2 width', + 'GaussianName area', + 'GaussianName center', + 'GaussianName width', + 'Gaussian2Name area', + 'Gaussian2Name center', + 'Gaussian2Name width', 'energy_offset', ] for parameter_name in parameter_names: @@ -422,7 +428,9 @@ def test_parameters_to_dataset(self, analysis): def test_parameters_to_dataset_different_units(self, analysis): # WHEN - analysis.sample_model.append_component(Gaussian(display_name='Gaussian2', area=0.5)) + analysis.sample_model.append_component( + Gaussian(name='Gaussian2Name', display_name='Gaussian2', area=0.5) + ) # Convert the unit of a component to eV. analysis.sample_model.get_component_collection(Q_index=1).components[0].convert_unit('eV') @@ -433,12 +441,12 @@ def test_parameters_to_dataset_different_units(self, analysis): # EXPECT assert isinstance(parameters_dataset, sc.Dataset) parameter_names = [ - 'Gaussian area', - 'Gaussian center', - 'Gaussian width', - 'Gaussian2 area', - 'Gaussian2 center', - 'Gaussian2 width', + 'GaussianName area', + 'GaussianName center', + 'GaussianName width', + 'Gaussian2Name area', + 'Gaussian2Name center', + 'Gaussian2Name width', 'energy_offset', ] for parameter_name in parameter_names: diff --git a/tests/unit/easydynamics/base_classes/test_easydynamics_base.py b/tests/unit/easydynamics/base_classes/test_easydynamics_base.py index 90d62c1a..78c5c936 100644 --- a/tests/unit/easydynamics/base_classes/test_easydynamics_base.py +++ b/tests/unit/easydynamics/base_classes/test_easydynamics_base.py @@ -20,22 +20,20 @@ def test_initialization(self, easy_dynamics_base): # WHEN THEN EXPECT assert easy_dynamics_base.name == 'TestModel' - assert easy_dynamics_base.display_name == 'MyEasyDynamicsModel' + assert easy_dynamics_base.display_name == 'TestModel' assert easy_dynamics_base.unique_name is not None def test_init_raises_type_error_for_invalid_name(self): """Test that initializing with an invalid name raises a TypeError.""" # WHEN THEN EXPECT - with pytest.raises(TypeError, match=r'Name must be a string or None.'): + with pytest.raises(TypeError, match=r'Name must be a string.'): EasyDynamicsBase(name=123) # Not a string - def test_init_name_can_be_none(self): - """Test that initializing with name as None works correctly.""" + def test_init_name_cannot_be_none(self): + """Test that initializing with name as None raises a TypeError.""" # WHEN THEN EXPECT - model = EasyDynamicsBase(name=None) - - # THEN EXPECT - assert model.name is None + with pytest.raises(TypeError, match=r'Name must be a string.'): + EasyDynamicsBase(name=None) def test_name_setter_and_getter(self, easy_dynamics_base): """Test that the name setter and getter work correctly.""" @@ -49,10 +47,8 @@ def test_name_setter_and_getter(self, easy_dynamics_base): assert easy_dynamics_base.name == 'NewName' # THEN - easy_dynamics_base.name = None - - # EXPECT - assert easy_dynamics_base.name is None + with pytest.raises(TypeError, match=r'Name must be a string.'): + easy_dynamics_base.name = None @pytest.mark.parametrize( 'invalid_name', @@ -66,5 +62,5 @@ def test_name_setter_and_getter(self, easy_dynamics_base): def test_name_setter_invalid_type(self, easy_dynamics_base, invalid_name): """Test that setting the name to an invalid type raises a TypeError.""" # WHEN THEN EXPECT - with pytest.raises(TypeError, match=r'Name must be a string or None.'): + with pytest.raises(TypeError, match=r'Name must be a string.'): easy_dynamics_base.name = invalid_name diff --git a/tests/unit/easydynamics/base_classes/test_easydynamics_modelbase.py b/tests/unit/easydynamics/base_classes/test_easydynamics_modelbase.py index c2d30f71..6767640a 100644 --- a/tests/unit/easydynamics/base_classes/test_easydynamics_modelbase.py +++ b/tests/unit/easydynamics/base_classes/test_easydynamics_modelbase.py @@ -20,22 +20,20 @@ def test_initialization(self, easy_dynamics_modelbase): # WHEN THEN EXPECT assert easy_dynamics_modelbase.name == 'TestModel' - assert easy_dynamics_modelbase.display_name == 'MyEasyDynamicsModel' + assert easy_dynamics_modelbase.display_name == 'TestModel' assert easy_dynamics_modelbase.unique_name is not None def test_init_raises_type_error_for_invalid_name(self): """Test that initializing with an invalid name raises a TypeError.""" # WHEN THEN EXPECT - with pytest.raises(TypeError, match=r'Name must be a string or None.'): + with pytest.raises(TypeError, match=r'Name must be a string.'): EasyDynamicsModelBase(name=123) # Not a string - def test_init_name_can_be_none(self): - """Test that initializing with name as None works correctly.""" + def test_init_name_cannot_be_none(self): + """Test that initializing with name as None raises a TypeError.""" # WHEN THEN EXPECT - model = EasyDynamicsModelBase(name=None) - - # THEN EXPECT - assert model.name is None + with pytest.raises(TypeError, match=r'Name must be a string.'): + EasyDynamicsModelBase(name=None) def test_name_setter_and_getter(self, easy_dynamics_modelbase): """Test that the name setter and getter work correctly.""" @@ -48,11 +46,9 @@ def test_name_setter_and_getter(self, easy_dynamics_modelbase): # EXPECT assert easy_dynamics_modelbase.name == 'NewName' - # THEN - easy_dynamics_modelbase.name = None - - # EXPECT - assert easy_dynamics_modelbase.name is None + # THEN EXPECT + with pytest.raises(TypeError, match=r'Name must be a string.'): + easy_dynamics_modelbase.name = None @pytest.mark.parametrize( 'invalid_name', @@ -66,7 +62,7 @@ def test_name_setter_and_getter(self, easy_dynamics_modelbase): def test_name_setter_invalid_type(self, easy_dynamics_modelbase, invalid_name): """Test that setting the name to an invalid type raises a TypeError.""" # WHEN THEN EXPECT - with pytest.raises(TypeError, match=r'Name must be a string or None.'): + with pytest.raises(TypeError, match=r'Name must be a string.'): easy_dynamics_modelbase.name = invalid_name def test_unit_property(self, easy_dynamics_modelbase): diff --git a/tests/unit/easydynamics/sample_model/components/test_damped_harmonic_oscillator.py b/tests/unit/easydynamics/sample_model/components/test_damped_harmonic_oscillator.py index 79e1913f..a420fa40 100644 --- a/tests/unit/easydynamics/sample_model/components/test_damped_harmonic_oscillator.py +++ b/tests/unit/easydynamics/sample_model/components/test_damped_harmonic_oscillator.py @@ -15,7 +15,12 @@ class TestDampedHarmonicOscillator: @pytest.fixture def dho(self): return DampedHarmonicOscillator( - display_name='TestDHO', area=2.0, center=1.5, width=0.3, unit='meV' + name='TestDHOName', + display_name='TestDHO', + area=2.0, + center=1.5, + width=0.3, + unit='meV', ) def test_init_no_inputs(self): @@ -164,9 +169,9 @@ def test_get_all_parameters(self, dho: DampedHarmonicOscillator): assert len(params) == 3 assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestDHO area', - 'TestDHO center', - 'TestDHO width', + 'TestDHOName area', + 'TestDHOName center', + 'TestDHOName width', } actual_names = {param.name for param in params} assert actual_names == expected_names @@ -219,7 +224,7 @@ def test_repr(self, dho: DampedHarmonicOscillator): # EXPECT assert 'DampedHarmonicOscillator' in repr_str - assert 'name = TestDHO' in repr_str + assert 'name = TestDHOName' in repr_str assert 'unit = meV' in repr_str assert 'area =' in repr_str assert 'center =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/components/test_delta_function.py b/tests/unit/easydynamics/sample_model/components/test_delta_function.py index be1e33a0..0747731b 100644 --- a/tests/unit/easydynamics/sample_model/components/test_delta_function.py +++ b/tests/unit/easydynamics/sample_model/components/test_delta_function.py @@ -15,7 +15,13 @@ class TestDeltaFunction: @pytest.fixture def delta_function(self): - return DeltaFunction(display_name='TestDeltaFunction', area=2.0, center=0.5, unit='meV') + return DeltaFunction( + name='DeltaFunctionName', + display_name='TestDeltaFunction', + area=2.0, + center=0.5, + unit='meV', + ) def test_init_no_inputs(self): # WHEN THEN @@ -178,8 +184,8 @@ def test_get_all_parameters(self, delta_function: DeltaFunction): assert len(params) == 2 assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestDeltaFunction area', - 'TestDeltaFunction center', + 'DeltaFunctionName area', + 'DeltaFunctionName center', } actual_names = {param.name for param in params} assert actual_names == expected_names @@ -215,7 +221,7 @@ def test_repr(self, delta_function: DeltaFunction): # EXPECT assert 'DeltaFunction' in repr_str - assert 'unique_name = DeltaFunction' in repr_str + assert 'name = DeltaFunctionName' in repr_str assert 'unit = meV' in repr_str assert 'area =' in repr_str assert 'center =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/components/test_exponential.py b/tests/unit/easydynamics/sample_model/components/test_exponential.py index 2a824532..97df632e 100644 --- a/tests/unit/easydynamics/sample_model/components/test_exponential.py +++ b/tests/unit/easydynamics/sample_model/components/test_exponential.py @@ -15,6 +15,7 @@ class TestExponential: @pytest.fixture def exponential(self): return Exponential( + name='ExponentialName', display_name='TestExponential', amplitude=2.0, center=0.5, @@ -156,9 +157,9 @@ def test_get_all_parameters(self, exponential: Exponential): assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestExponential amplitude', - 'TestExponential center', - 'TestExponential rate', + 'ExponentialName amplitude', + 'ExponentialName center', + 'ExponentialName rate', } actual_names = {param.name for param in params} @@ -226,7 +227,7 @@ def test_repr(self, exponential: Exponential): # THEN EXPECT assert 'Exponential' in repr_str - assert 'unique_name = Exponential' in repr_str + assert 'name = ExponentialName' in repr_str assert 'unit = meV' in repr_str assert 'amplitude =' in repr_str assert 'center =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/components/test_gaussian.py b/tests/unit/easydynamics/sample_model/components/test_gaussian.py index ef339cc2..9bf0b13d 100644 --- a/tests/unit/easydynamics/sample_model/components/test_gaussian.py +++ b/tests/unit/easydynamics/sample_model/components/test_gaussian.py @@ -14,7 +14,14 @@ class TestGaussian: @pytest.fixture def gaussian(self): - return Gaussian(display_name='TestGaussian', area=2.0, center=0.5, width=0.6, unit='meV') + return Gaussian( + name='GaussianName', + display_name='TestGaussian', + area=2.0, + center=0.5, + width=0.6, + unit='meV', + ) def test_init_no_inputs(self): # WHEN THEN @@ -164,9 +171,9 @@ def test_get_all_parameters(self, gaussian: Gaussian): assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestGaussian area', - 'TestGaussian center', - 'TestGaussian width', + 'GaussianName area', + 'GaussianName center', + 'GaussianName width', } actual_names = {param.name for param in params} assert actual_names == expected_names @@ -208,6 +215,7 @@ def test_copy(self, gaussian: Gaussian): # EXPECT assert gaussian_copy is not gaussian assert gaussian_copy.display_name == gaussian.display_name + assert gaussian_copy.name == gaussian.name assert gaussian_copy.area.value == gaussian.area.value assert gaussian_copy.area.fixed == gaussian.area.fixed @@ -231,7 +239,7 @@ def test_repr(self, gaussian: Gaussian): repr_str = repr(gaussian) # EXPECT assert 'Gaussian' in repr_str - assert 'unique_name = Gaussian' in repr_str + assert 'name = GaussianName' in repr_str assert 'unit = meV' in repr_str assert 'area =' in repr_str assert 'center =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/components/test_lorentzian.py b/tests/unit/easydynamics/sample_model/components/test_lorentzian.py index 4ce1e1db..3c7809c6 100644 --- a/tests/unit/easydynamics/sample_model/components/test_lorentzian.py +++ b/tests/unit/easydynamics/sample_model/components/test_lorentzian.py @@ -15,7 +15,12 @@ class TestLorentzian: @pytest.fixture def lorentzian(self): return Lorentzian( - display_name='TestLorentzian', area=2.0, center=0.5, width=0.6, unit='meV' + name='LorentzianName', + display_name='TestLorentzian', + area=2.0, + center=0.5, + width=0.6, + unit='meV', ) def test_init_no_inputs(self): @@ -163,9 +168,9 @@ def test_get_all_parameters(self, lorentzian: Lorentzian): assert len(params) == 3 assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestLorentzian area', - 'TestLorentzian center', - 'TestLorentzian width', + 'LorentzianName area', + 'LorentzianName center', + 'LorentzianName width', } actual_names = {param.name for param in params} assert actual_names == expected_names @@ -218,7 +223,7 @@ def test_repr(self, lorentzian: Lorentzian): # EXPECT assert 'Lorentzian' in repr_str - assert 'unique_name = Lorentzian' in repr_str + assert 'name = LorentzianName' in repr_str assert 'unit = meV' in repr_str assert 'area =' in repr_str assert 'center =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/components/test_polynomial.py b/tests/unit/easydynamics/sample_model/components/test_polynomial.py index 5e42e677..3111c00a 100644 --- a/tests/unit/easydynamics/sample_model/components/test_polynomial.py +++ b/tests/unit/easydynamics/sample_model/components/test_polynomial.py @@ -14,7 +14,11 @@ class TestPolynomial: @pytest.fixture def polynomial(self): - return Polynomial(display_name='TestPolynomial', coefficients=[1.0, -2.0, 3.0]) + return Polynomial( + name='PolynomialName', + display_name='TestPolynomial', + coefficients=[1.0, -2.0, 3.0], + ) def test_init_no_inputs(self): # WHEN THEN @@ -150,9 +154,9 @@ def test_get_all_parameters(self, polynomial: Polynomial): assert len(params) == 3 assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestPolynomial_c0', - 'TestPolynomial_c1', - 'TestPolynomial_c2', + 'PolynomialName_c0', + 'PolynomialName_c1', + 'PolynomialName_c2', } actual_names = {param.name for param in params} assert actual_names == expected_names @@ -193,6 +197,5 @@ def test_repr(self, polynomial: Polynomial): repr_str = repr(polynomial) # EXPECT - assert 'Polynomial' in repr_str - assert 'unique_name = Polynomial' in repr_str + assert 'name = PolynomialName' in repr_str assert 'coefficients =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/components/test_voigt.py b/tests/unit/easydynamics/sample_model/components/test_voigt.py index 5bf866d8..4d28c73a 100644 --- a/tests/unit/easydynamics/sample_model/components/test_voigt.py +++ b/tests/unit/easydynamics/sample_model/components/test_voigt.py @@ -16,6 +16,7 @@ class TestVoigt: @pytest.fixture def voigt(self): return Voigt( + name='VoigtName', display_name='TestVoigt', area=2.0, center=0.5, @@ -234,7 +235,6 @@ def test_evaluate(self, voigt: Voigt): def test_center_is_fixed_if_init_to_None(self): # WHEN THEN test_voigt = Voigt( - display_name='TestVoigt', area=2.0, center=None, gaussian_width=0.6, @@ -265,10 +265,10 @@ def test_get_all_parameters(self, voigt: Voigt): assert len(params) == 4 assert all(isinstance(param, Parameter) for param in params) expected_names = { - 'TestVoigt area', - 'TestVoigt center', - 'TestVoigt gaussian_width', - 'TestVoigt lorentzian_width', + 'VoigtName area', + 'VoigtName center', + 'VoigtName gaussian_width', + 'VoigtName lorentzian_width', } actual_names = {param.name for param in params} assert actual_names == expected_names @@ -318,7 +318,7 @@ def test_repr(self, voigt: Voigt): # EXPECT assert 'Voigt' in repr_str - assert 'unique_name = Voigt' in repr_str + assert 'name = VoigtName' in repr_str assert 'unit = meV' in repr_str assert 'area =' in repr_str assert 'center =' in repr_str diff --git a/tests/unit/easydynamics/sample_model/diffusion_model/test_brownian_translational_diffusion.py b/tests/unit/easydynamics/sample_model/diffusion_model/test_brownian_translational_diffusion.py index be25890e..8c813ec7 100644 --- a/tests/unit/easydynamics/sample_model/diffusion_model/test_brownian_translational_diffusion.py +++ b/tests/unit/easydynamics/sample_model/diffusion_model/test_brownian_translational_diffusion.py @@ -171,6 +171,15 @@ def test_create_component_collections_component_name_must_be_string( ): # WHEN THEN EXPECT with pytest.raises(TypeError, match=r'component_name must be a string.'): + brownian_diffusion_model.create_component_collections( + Q=np.array([0.1, 0.2, 0.3]), component_name=123 + ) + + def test_create_component_collections_component_display_name_must_be_string( + self, brownian_diffusion_model + ): + # WHEN THEN EXPECT + with pytest.raises(TypeError, match=r'component_display_name must be a string.'): brownian_diffusion_model.create_component_collections( Q=np.array([0.1, 0.2, 0.3]), component_display_name=123 ) diff --git a/tests/unit/easydynamics/sample_model/diffusion_model/test_jump_translational_diffusion.py b/tests/unit/easydynamics/sample_model/diffusion_model/test_jump_translational_diffusion.py index 9388a2db..a2b8022a 100644 --- a/tests/unit/easydynamics/sample_model/diffusion_model/test_jump_translational_diffusion.py +++ b/tests/unit/easydynamics/sample_model/diffusion_model/test_jump_translational_diffusion.py @@ -209,6 +209,15 @@ def test_create_component_collections_component_name_must_be_string( ): # WHEN THEN EXPECT with pytest.raises(TypeError, match=r'component_name must be a string.'): + jump_diffusion_model.create_component_collections( + Q=np.array([0.1, 0.2, 0.3]), component_name=123 + ) + + def test_create_component_collections_component_display_name_must_be_string( + self, jump_diffusion_model + ): + # WHEN THEN EXPECT + with pytest.raises(TypeError, match=r'component_display_name must be a string.'): jump_diffusion_model.create_component_collections( Q=np.array([0.1, 0.2, 0.3]), component_display_name=123 ) diff --git a/tests/unit/easydynamics/sample_model/test_component_collection.py b/tests/unit/easydynamics/sample_model/test_component_collection.py index 692486ff..a50dca06 100644 --- a/tests/unit/easydynamics/sample_model/test_component_collection.py +++ b/tests/unit/easydynamics/sample_model/test_component_collection.py @@ -19,6 +19,7 @@ class TestComponentCollection: def component_collection(self): model = ComponentCollection(display_name='TestComponentCollection') component1 = Gaussian( + name='TestGaussian1Name', display_name='TestGaussian1', area=1.0, center=0.0, @@ -27,6 +28,7 @@ def component_collection(self): unique_name='TestGaussian1', ) component2 = Lorentzian( + name='TestLorentzian1Name', display_name='TestLorentzian1', area=2.0, center=1.0, @@ -345,12 +347,12 @@ def test_get_all_parameters(self, component_collection): assert len(parameters) == 6 expected_names = { - 'TestGaussian1 area', - 'TestGaussian1 center', - 'TestGaussian1 width', - 'TestLorentzian1 area', - 'TestLorentzian1 center', - 'TestLorentzian1 width', + 'TestGaussian1Name area', + 'TestGaussian1Name center', + 'TestGaussian1Name width', + 'TestLorentzian1Name area', + 'TestLorentzian1Name center', + 'TestLorentzian1Name width', } actual_names = {param.name for param in parameters} assert actual_names == expected_names @@ -380,10 +382,10 @@ def test_get_fit_parameters(self, component_collection): assert len(fit_parameters) == 4 expected_names = { - 'TestGaussian1 center', - 'TestGaussian1 width', - 'TestLorentzian1 area', - 'TestLorentzian1 center', + 'TestGaussian1Name center', + 'TestGaussian1Name width', + 'TestLorentzian1Name area', + 'TestLorentzian1Name center', } actual_names = {param.name for param in fit_parameters} assert actual_names == expected_names diff --git a/tests/unit/easydynamics/sample_model/test_model_base.py b/tests/unit/easydynamics/sample_model/test_model_base.py index 5ad066a2..34fea244 100644 --- a/tests/unit/easydynamics/sample_model/test_model_base.py +++ b/tests/unit/easydynamics/sample_model/test_model_base.py @@ -18,6 +18,7 @@ class TestModelBase: @pytest.fixture def model_base(self): component1 = Gaussian( + name='TestGaussian1Name', display_name='TestGaussian1', area=1.0, center=0.0, @@ -25,6 +26,7 @@ def model_base(self): unit='meV', ) component2 = Lorentzian( + name='TestLorentzian1Name', display_name='TestLorentzian1', area=2.0, center=1.0, @@ -126,12 +128,12 @@ def test_get_all_variables(self, model_base): # THEN expected_var_display_names = { - 'TestGaussian1 area', - 'TestGaussian1 center', - 'TestGaussian1 width', - 'TestLorentzian1 area', - 'TestLorentzian1 center', - 'TestLorentzian1 width', + 'TestGaussian1Name area', + 'TestGaussian1Name center', + 'TestGaussian1Name width', + 'TestLorentzian1Name area', + 'TestLorentzian1Name center', + 'TestLorentzian1Name width', } retrieved_var_display_names = {var.display_name for var in all_vars} @@ -145,12 +147,12 @@ def test_get_all_variables_with_Q_index(self, model_base): # THEN expected_var_display_names = { - 'TestGaussian1 area', - 'TestGaussian1 center', - 'TestGaussian1 width', - 'TestLorentzian1 area', - 'TestLorentzian1 center', - 'TestLorentzian1 width', + 'TestGaussian1Name area', + 'TestGaussian1Name center', + 'TestGaussian1Name width', + 'TestLorentzian1Name area', + 'TestLorentzian1Name center', + 'TestLorentzian1Name width', } retrieved_var_display_names = {var.display_name for var in all_vars}