Components¶
Components are the basic ingredients for all models. Currently, the available components are Gaussian, Lorentzian, Voigt (the convolution of a Gaussian with a Lorentzian), delta function, damped harmonic oscillator, stretched exponential and polynomial. This notebooks shows how to use the components.
Note in particular that a Gaussian, Lorentzian, Voigt or delta function where the center has not been given will be centered at 0.
import matplotlib.pyplot as plt
import numpy as np
import scipp as sc
import easydynamics as edyn
%matplotlib widget
# Creating a component
gaussian = edyn.Gaussian(display_name='Gaussian', width=0.5, area=1)
dho = edyn.DampedHarmonicOscillator(display_name='DHO', center=1.0, width=0.3, area=2.0)
lorentzian = edyn.Lorentzian(display_name='Lorentzian', center=-1.0, width=0.2, area=1.0)
polynomial = edyn.Polynomial(
display_name='Polynomial', coefficients=[-0.2, 0, 0.5]
) # y=-0.2+0.5*x^2
exponential = edyn.Exponential(display_name='Exponential', amplitude=1.0, rate=-0.5)
x = np.linspace(-2, 2, 100)
plt.figure()
y = gaussian.evaluate(x)
plt.plot(x, y, label='Gaussian')
y = dho.evaluate(x)
plt.plot(x, y, label='DHO')
y = lorentzian.evaluate(x)
plt.plot(x, y, label='Lorentzian')
y = polynomial.evaluate(x)
plt.plot(x, y, label='Polynomial')
y = exponential.evaluate(x)
plt.plot(x, y, label='Exponential')
plt.legend()
plt.show()
/tmp/ipykernel_2612/3811506240.py:19: UserWarning: The Polynomial with unique_name Polynomial_0 has negative values, which may not be physically meaningful. y = polynomial.evaluate(x)
# Suppress the warning from the Polynomial:
polynomial.suppress_warnings = True
y = polynomial.evaluate(x)
# The area under the DHO curve is indeed equal to the area parameter.
xx = np.linspace(-15, 15, 10000)
yy = dho.evaluate(xx)
area = np.trapezoid(yy, xx)
print(f'Area under DHO curve: {area:.4f}')
Area under DHO curve: 1.9999
delta = edyn.DeltaFunction(display_name='Delta', center=0.0, area=1.0)
x1 = np.linspace(-2, 2, 100)
y = delta.evaluate(x1)
x2 = np.linspace(-2, 2, 51)
y2 = delta.evaluate(x2)
plt.figure()
plt.plot(x1, y, label='Delta Function')
plt.plot(x2, y2, label='Delta Function (coarser)')
plt.legend()
plt.show()
# The area under the Delta function is indeed equal to
# the area parameter.
xx = np.linspace(-2, 2, 10000)
yy = delta.evaluate(xx)
area = np.trapezoid(y, x1)
print(area)
0.9999999999999999
x1 = sc.linspace(dim='x', start=-2.0, stop=2.0, num=100, unit='meV')
x2 = sc.linspace(dim='x', start=-2.0 * 1e3, stop=2.0 * 1e3, num=101, unit='microeV')
polynomial = edyn.Polynomial(
display_name='Polynomial', coefficients=[0.1, 0, 0.5]
) # y=0.1+0.5*x^2
y1 = polynomial.evaluate(x1)
y2 = polynomial.evaluate(x2)
plt.figure()
plt.plot(x1.values, y1, label='Polynomial meV', color='blue')
plt.plot(x2.values / 1000, y2, label='Polynomial microeV', linestyle='dashed', color='orange')
plt.legend()
plt.show()
The ExpressionComponent can create almost any function you would like. Units are supported and must be given for each parameter either at construction as below, or afterwards as properties. The individual parameters can be accessed by their name in the usual way. You must use x fore the x-axis. It will warn if the units are not consistent.
expr = edyn.ExpressionComponent(
'A * exp(-(x - x0)**2 / (2*sigma**2)) +B*sin(2*pi*x/period)',
parameters={'A': 10, 'x0': 0, 'sigma': 1},
parameter_units={
'A': 'dimensionless',
'x0': 'meV',
'sigma': 'meV',
'B': 'dimensionless',
'period': 'meV',
},
x_unit='meV',
y_unit='dimensionless',
)
expr.A = 5
expr.sigma = 0.5
expr.period = 2.0
x = np.linspace(-5, 5, 100)
y = expr.evaluate(x)
plt.figure()
plt.plot(x, y, label='Expression Component')
plt.legend()
plt.show()
plt.xlabel('Energy (meV)')
plt.ylabel('Intensity (arb. units)')
Text(43.722222222222214, 0.5, 'Intensity (arb. units)')
expr = edyn.ExpressionComponent(
'A*erf(B*x)',
)
expr.A = 1.0
expr.B = 0.5
x = np.linspace(-5, 5, 100)
y = expr.evaluate(x)
plt.figure()
plt.plot(x, y, label='erf')
plt.legend()
plt.show()
stretched_lorz = edyn.StretchedExponential(area=1.0, relaxation_time=10.0, beta=1.0)
lorentzian = edyn.Lorentzian(center=0.0, width=0.6582 / 10, area=1.0)
stretched = edyn.StretchedExponential(area=1.0, relaxation_time=10.0, beta=0.5)
x = np.linspace(-1, 1, 1001)
y = stretched_lorz.evaluate(x)
y2 = lorentzian.evaluate(x)
y3 = stretched.evaluate(x)
plt.figure()
plt.plot(x, y, label='Stretched exponential (β=1)')
plt.plot(x, y2, label='Lorentzian', linestyle='dotted')
plt.plot(x, y3, label='Stretched exponential (β=0.5)')
plt.xlabel('Energy (meV)')
plt.ylabel('Intensity (arb. units)')
plt.legend()
plt.show()