Skip to content
7 changes: 6 additions & 1 deletion docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ extra_css:
- assets/stylesheets/extra.css
extra_javascript:
- assets/javascripts/extra.js
- javascripts/mathjax.js
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js

# A list of extensions beyond the ones that MkDocs uses by default (meta, toc, tables, and fenced_code)
markdown_extensions:
Expand All @@ -94,6 +96,8 @@ markdown_extensions:
- attr_list
- def_list
- footnotes
- pymdownx.arithmatex:
generic: true
- pymdownx.blocks.caption
- pymdownx.details
- pymdownx.emoji:
Expand Down Expand Up @@ -132,7 +136,7 @@ plugins:
allow_errors: false
include_source: true
include_requirejs: true # Required for Plotly
custom_mathjax_url: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS_CHTML-full,Safe'
# custom_mathjax_url: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS_CHTML-full,Safe'
ignore_h1_titles: true # Use titles defined in the nav section below
remove_tag_config:
remove_input_tags:
Expand All @@ -143,6 +147,7 @@ plugins:
paths: ['src'] # Change 'src' to your actual sources directory
options:
docstring_style: google
render_markdown: true
group_by_category: false
heading_level: 1
show_root_heading: true
Expand Down
115 changes: 93 additions & 22 deletions src/easydynamics/sample_model/components/damped_harmonic_oscillator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,38 @@


class DampedHarmonicOscillator(CreateParametersMixin, ModelComponent):
"""
Damped Harmonic Oscillator (DHO).
2*area*center^2*width/pi / ( (x^2 - center^2)^2 + (2*width*x)^2 )
r"""Model of a Damped Harmonic Oscillator (DHO).

The intensity is given by
$$
I(x) = \frac{2 A x_0^2 \gamma}{\pi \left( (x^2 - x_0^2)^2 +
(2 \gamma x)^2 \right)},
$$
where $A$ is the area, $x_0$ is the center, and $\gamma$ is the
width.


Args:
display_name (str): Display name of the component.
center (Int or float): Resonance frequency, approximately the
peak position.
width (Int or float): Damping constant, approximately the
half width at half max (HWHM) of the peaks.
area (Int or float): Area under the curve.
unit (str or sc.Unit): Unit of the parameters.
Defaults to "meV".
area (Int | float): Area under the curve.
center (Int | float): Resonance frequency, approximately the
peak position.
width (Int | float): Damping constant, approximately the
half width at half max (HWHM) of the peaks.
unit (str | sc.Unit): Unit of the parameters.
Defaults to "meV".
display_name (str | None): Display name of the component.
unique_name (str | None): Unique name of the component.
If None, a unique_name is automatically generated.

Attributes:
area (Parameter): Area under the curve.
center (Parameter): Resonance frequency, approximately the
peak position.
width (Parameter): Damping constant, approximately the
half width at half max (HWHM) of the peaks.
unit (str | sc.Unit): Unit of the parameters.
display_name (str | None): Display name of the component.
unique_name (str | None): Unique name of the component.
"""

def __init__(
Expand Down Expand Up @@ -62,50 +81,95 @@ def __init__(

@property
def area(self) -> Parameter:
"""Get the area parameter."""
"""Get the area parameter.

Returns:
Parameter: The area parameter.
"""
return self._area

@area.setter
def area(self, value: Numeric) -> None:
"""Set the area parameter value."""
"""Set the value of the area parameter."""
if not isinstance(value, Numeric):
raise TypeError('area must be a number')
self._area.value = value

@property
def center(self) -> Parameter:
"""Get the center parameter."""
"""Get the center parameter.

Returns:
Parameter: The center parameter.
"""
return self._center

@center.setter
def center(self, value: Numeric) -> None:
"""Set the center parameter value."""
"""Set the value of the center parameter.

Args:
value (Numeric): The new value for the center parameter.

Raises:
TypeError: If the value is not a number.
ValueError: If the value is not positive.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need the Raises information . . .

"""
if not isinstance(value, Numeric):
raise TypeError('center must be a number')

if value <= 0:
if float(value) <= 0:
raise ValueError('center must be positive')
self._center.value = value

@property
def width(self) -> Parameter:
"""Get the width parameter."""
"""Get the width parameter.

Returns:
Parameter: The width parameter.
"""
return self._width

@width.setter
def width(self, value: Numeric) -> None:
"""Set the width parameter value."""
"""Set the value of the width parameter.

Args:
value (Numeric): The new value for the width parameter.

Raises:
TypeError: If the value is not a number.
ValueError: If the value is not positive.
"""
if not isinstance(value, Numeric):
raise TypeError('width must be a number')

if float(value) <= 0:
raise ValueError('width must be positive')

self._width.value = value

def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray) -> np.ndarray:
"""Evaluate the Damped Harmonic Oscillator at the given x
r"""Evaluate the Damped Harmonic Oscillator at the given x
values.

If x is a scipp Variable, the unit of the DHO will be converted
to match x. The DHO evaluates to
2*area*center^2*width/pi / ((x^2 - center^2)^2 + (2*width*x)^2)
to match x. The intensity is given by
$$
I(x) = \frac{2 A x_0^2 \gamma}{\pi \left( (x^2 - x_0^2)^2 +
(2 \gamma x)^2 \right)},
$$
where $A$ is the area, $x_0$ is the center, and $\gamma$ is the
width.

Args:
x (Numeric | list | np.ndarray | sc.Variable |
sc.DataArray): The x values at which to evaluate the
DHO.

Returns:
np.ndarray: The intensity of the DHO at the given x values.
"""

x = self._prepare_x_for_evaluate(x)
Expand All @@ -116,7 +180,14 @@ def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray)

return self.area.value * normalization / (denominator)

def __repr__(self):
def __repr__(self) -> str:
"""Return a string representation of the Damped Harmonic
Oscillator.

Returns:
str: A string representation of the Damped Harmonic
Oscillator.
"""
return (
f'DampedHarmonicOscillator(display_name = {self.display_name}, unit = {self._unit},\n \
area = {self.area},\n center = {self.center},\n width = {self.width})'
Expand Down
85 changes: 68 additions & 17 deletions src/easydynamics/sample_model/components/delta_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,29 @@


class DeltaFunction(CreateParametersMixin, ModelComponent):
"""Delta function. Evaluates to zero everywhere, except in
convolutions, where it acts as an identity. This is handled in the
ResolutionHandler. If the center is not provided, it will be
centered at 0 and fixed, which is typically what you want in QENS.
"""Delta function.

Evaluates to zero everywhere, except in convolutions, where it acts
as an identity. This is handled by the Convolution method. If the
center is not provided, it will be centered at 0 and fixed, which is
typically what you want in QENS.

Args:
center (Int or float or None): Center of the delta function.
If None, defaults to 0 and is fixed.
area (Int or float): Total area under the curve.
unit (str or sc.Unit): Unit of the parameters.
Defaults to "meV".
display_name (str): Name of the component.
unique_name (str or None): Unique name of the component.
If None, a unique_name is automatically generated.
center (Int | float | None): Center of the delta function. If
None, defaults to 0 and is fixed.
area (Int | float): Total area under the curve.
unit (str | sc.Unit): Unit of the parameters.
Defaults to "meV".
display_name (str | None): Name of the component.
unique_name (str | None): Unique name of the component.
If None, a unique_name is automatically generated.

Attributes:
center (Parameter): Center of the delta function.
area (Parameter): Total area under the curve.
unit (str | sc.Unit): Unit of the parameters.
display_name (str | None): Name of the component.
unique_name (str | None): Unique name of the component.
"""

def __init__(
Expand Down Expand Up @@ -58,24 +67,51 @@ def __init__(

@property
def area(self) -> Parameter:
"""Get the area parameter."""
"""Get the area parameter.

Returns:
Parameter: The area parameter.
"""

return self._area

@area.setter
def area(self, value: Numeric) -> None:
"""Set the area parameter value."""
"""Set the value of the area parameter.

Args:
value (Numeric): The new value for the area parameter.

Raises:
TypeError: If the value is not a number.
"""

if not isinstance(value, Numeric):
raise TypeError('area must be a number')
self._area.value = value

@property
def center(self) -> Parameter:
"""Get the center parameter."""
"""Get the center parameter.

Returns:
Parameter: The center parameter.
"""

return self._center

@center.setter
def center(self, value: Numeric | None) -> None:
"""Set the center parameter value."""
"""Set the center parameter value.

Args:
value (Numeric | None): The new value for the center
parameter. If None, defaults to 0 and is fixed.

Raises:
TypeError: If the value is not a number or None.
"""

if value is None:
value = 0.0
self._center.fixed = True
Expand All @@ -89,6 +125,15 @@ def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray)
The Delta function evaluates to zero everywhere, except at the
center. Its numerical integral is equal to the area. It acts as
an identity in convolutions.

Args:
x (Numeric | list | np.ndarray | sc.Variable |
sc.DataArray): The x values at which to evaluate the
Delta function.

Returns:
np.ndarray: The evaluated Delta function at the given x
values.
"""

# x assumed sorted, 1D numpy array
Expand Down Expand Up @@ -120,6 +165,12 @@ def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray)

return model

def __repr__(self):
def __repr__(self) -> str:
"""Return a string representation of the Delta function.

Returns:
str: A string representation of the Delta function.
"""

return f'DeltaFunction(unique_name = {self.unique_name}, unit = {self._unit},\n \
area = {self.area},\n center = {self.center}'
Loading
Loading