r"""
Gaussian models
===============
.. moduleauthor:: Benjamin Ye <GitHub: @bbye98>
The Gaussian model fits peaks, and is given by
.. math::
y=\sum_{k=1}^na_k\exp{\left[-\left(\frac{x-b_k}{c_k}\right)^2\right]}
where :math:`a` is the amplitude, :math:`b` is the centroid (location),
:math:`c` is related to the peak width, and :math:`n` is the number of
peaks to fit.
This module provides the general Gaussian model above for any number of
terms :math:`k`, as well as convenience functions for Gaussian models
with :math:`1\leq n\leq8` analogous to MATLAB's :code:`gauss1`,
:code:`gauss2`, etc.
"""
import numpy as np
[docs]
def gauss(x: np.ndarray, *args: float) -> np.ndarray:
r"""
General Gaussian model.
.. math::
y=\sum_{k=1}^na_k\exp{\left[
-\left(\frac{x-b_k}{c_k}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
:math:`x`-values.
*args : `float`
Fitting parameters for the Gaussian term(s), ordered as
:math:`a_1,\,b_1,\,c_1,\,a_2,\,b_2,\,c_2,\ldots,\,a_n,\,b_n,\,c_n`,
where :math:`n` is the number of terms in the model. As such,
the number of variable positional arguments must be divisible by
:math:`3`.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
Examples
--------
Generate :math:`x`- and :math:`y`-values (with error), and then use
:func:`scipy.optimize.curve_fit` to fit coefficients for a one-term
Gaussian model.
>>> from scipy import optimize
>>> rng = np.random.default_rng()
>>> x = np.linspace(-3, 7, 10)
>>> err = (2 * rng.random(x.shape) - 1) / 10
>>>y=np.exp(-((x - 2) / 3) ** 2) + err
>>> pk, _ = optimize.curve_fit(lambda x, a1, b1, c1: gauss(x, a1, b1, c1), x, y)
>>> pk
array([1.07262377, 1.90290018, 2.90033242])
Evaluate the fitted :math:`y`-values using the coefficients.
>>> gauss(x, *pk)
array([0.06157175, 0.19415629, 0.45650326, 0.80031095, 1.04615509,
1.01966105, 0.74103382, 0.40155281, 0.16224441, 0.04887866])
"""
n = len(args)
assert n >= 3 and n % 3 == 0, \
"Number of fitting parameters must be greater than and divisible by 3."
return np.exp(-((x[:, None] - args[1::3]) / args[2::3]) ** 2) @ args[::3]
[docs]
def gauss1(x: np.ndarray, a1: float, b1: float, c1: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss1` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1)
[docs]
def gauss2(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss2` model from MATLAB:
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2)
[docs]
def gauss3(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float, a3: float, b3: float, c3: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss3` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
+a_3\exp{\left[-\left(\frac{x-b_3}{c_3}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
a3 : `float`
Amplitude :math:`a_3` of the third Gaussian term.
b3 : `float`
Centroid :math:`b_3` of the third Gaussian term.
c3 : `float`
Peak width :math:`c_3` of the third Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2, a3, b3, c3)
[docs]
def gauss4(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float, a3: float, b3: float, c3: float, a4: float, b4: float,
c4: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss4` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
+a_3\exp{\left[-\left(\frac{x-b_3}{c_3}\right)^2\right]}
+a_4\exp{\left[-\left(\frac{x-b_4}{c_4}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
a3 : `float`
Amplitude :math:`a_3` of the third Gaussian term.
b3 : `float`
Centroid :math:`b_3` of the third Gaussian term.
c3 : `float`
Peak width :math:`c_3` of the third Gaussian term.
a4 : `float`
Amplitude :math:`a_4` of the fourth Gaussian term.
b4 : `float`
Centroid :math:`b_4` of the fourth Gaussian term.
c4 : `float`
Peak width :math:`c_4` of the fourth Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, b4, c4)
[docs]
def gauss5(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float, a3: float, b3: float, c3: float, a4: float, b4: float,
c4: float, a5: float, b5: float, c5: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss5` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
+\cdots+a_5\exp{\left[-\left(\frac{x-b_5}{c_5}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
a3 : `float`
Amplitude :math:`a_3` of the third Gaussian term.
b3 : `float`
Centroid :math:`b_3` of the third Gaussian term.
c3 : `float`
Peak width :math:`c_3` of the third Gaussian term.
a4 : `float`
Amplitude :math:`a_4` of the fourth Gaussian term.
b4 : `float`
Centroid :math:`b_4` of the fourth Gaussian term.
c4 : `float`
Peak width :math:`c_4` of the fourth Gaussian term.
a5 : `float`
Amplitude :math:`a_5` of the fifth Gaussian term.
b5 : `float`
Centroid :math:`b_5` of the fifth Gaussian term.
c5 : `float`
Peak width :math:`c_5` of the fifth Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, b4, c4,
a5, b5, c5)
[docs]
def gauss6(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float, a3: float, b3: float, c3: float, a4: float, b4: float,
c4: float, a5: float, b5: float, c5: float, a6: float, b6: float,
c6: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss6` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
+\cdots+a_6\exp{\left[-\left(\frac{x-b_6}{c_6}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
a3 : `float`
Amplitude :math:`a_3` of the third Gaussian term.
b3 : `float`
Centroid :math:`b_3` of the third Gaussian term.
c3 : `float`
Peak width :math:`c_3` of the third Gaussian term.
a4 : `float`
Amplitude :math:`a_4` of the fourth Gaussian term.
b4 : `float`
Centroid :math:`b_4` of the fourth Gaussian term.
c4 : `float`
Peak width :math:`c_4` of the fourth Gaussian term.
a5 : `float`
Amplitude :math:`a_5` of the fifth Gaussian term.
b5 : `float`
Centroid :math:`b_5` of the fifth Gaussian term.
c5 : `float`
Peak width :math:`c_5` of the fifth Gaussian term.
a6 : `float`
Amplitude :math:`a_6` of the sixth Gaussian term.
b6 : `float`
Centroid :math:`b_6` of the sixth Gaussian term.
c6 : `float`
Peak width :math:`c_6` of the sixth Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, b4, c4,
a5, b5, c5, a6, b6, c6)
[docs]
def gauss7(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float, a3: float, b3: float, c3: float, a4: float, b4: float,
c4: float, a5: float, b5: float, c5: float, a6: float, b6: float,
c6: float, a7: float, b7: float, c7: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss7` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
+\cdots+a_7\exp{\left[-\left(\frac{x-b_7}{c_7}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
a3 : `float`
Amplitude :math:`a_3` of the third Gaussian term.
b3 : `float`
Centroid :math:`b_3` of the third Gaussian term.
c3 : `float`
Peak width :math:`c_3` of the third Gaussian term.
a4 : `float`
Amplitude :math:`a_4` of the fourth Gaussian term.
b4 : `float`
Centroid :math:`b_4` of the fourth Gaussian term.
c4 : `float`
Peak width :math:`c_4` of the fourth Gaussian term.
a5 : `float`
Amplitude :math:`a_5` of the fifth Gaussian term.
b5 : `float`
Centroid :math:`b_5` of the fifth Gaussian term.
c5 : `float`
Peak width :math:`c_5` of the fifth Gaussian term.
a6 : `float`
Amplitude :math:`a_6` of the sixth Gaussian term.
b6 : `float`
Centroid :math:`b_6` of the sixth Gaussian term.
c6 : `float`
Peak width :math:`c_6` of the sixth Gaussian term.
a7 : `float`
Amplitude :math:`a_7` of the seventh Gaussian term.
b7 : `float`
Centroid :math:`b_7` of the seventh Gaussian term.
c7 : `float`
Peak width :math:`c_7` of the seventh Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, b4, c4,
a5, b5, c5, a6, b6, c6, a7, b7, c7)
[docs]
def gauss8(
x: np.ndarray, a1: float, b1: float, c1: float, a2: float, b2: float,
c2: float, a3: float, b3: float, c3: float, a4: float, b4: float,
c4: float, a5: float, b5: float, c5: float, a6: float, b6: float,
c6: float, a7: float, b7: float, c7: float, a8: float, b8: float,
c8: float) -> np.ndarray:
r"""
Convenience function for the :code:`gauss8` model from MATLAB.
.. math::
y=a_1\exp{\left[-\left(\frac{x-b_1}{c_1}\right)^2\right]}
+a_2\exp{\left[-\left(\frac{x-b_2}{c_2}\right)^2\right]}
+\cdots+a_8\exp{\left[-\left(\frac{x-b_8}{c_8}\right)^2\right]}
Parameters
----------
x : `numpy.ndarray`
One-dimensional array containing :math:`x`-values.
a1 : `float`
Amplitude :math:`a_1` of the first Gaussian term.
b1 : `float`
Centroid :math:`b_1` of the first Gaussian term.
c1 : `float`
Peak width :math:`c_1` of the first Gaussian term.
a2 : `float`
Amplitude :math:`a_2` of the second Gaussian term.
b2 : `float`
Centroid :math:`b_2` of the second Gaussian term.
c2 : `float`
Peak width :math:`c_2` of the second Gaussian term.
a3 : `float`
Amplitude :math:`a_3` of the third Gaussian term.
b3 : `float`
Centroid :math:`b_3` of the third Gaussian term.
c3 : `float`
Peak width :math:`c_3` of the third Gaussian term.
a4 : `float`
Amplitude :math:`a_4` of the fourth Gaussian term.
b4 : `float`
Centroid :math:`b_4` of the fourth Gaussian term.
c4 : `float`
Peak width :math:`c_4` of the fourth Gaussian term.
a5 : `float`
Amplitude :math:`a_5` of the fifth Gaussian term.
b5 : `float`
Centroid :math:`b_5` of the fifth Gaussian term.
c5 : `float`
Peak width :math:`c_5` of the fifth Gaussian term.
a6 : `float`
Amplitude :math:`a_6` of the sixth Gaussian term.
b6 : `float`
Centroid :math:`b_6` of the sixth Gaussian term.
c6 : `float`
Peak width :math:`c_6` of the sixth Gaussian term.
a7 : `float`
Amplitude :math:`a_7` of the seventh Gaussian term.
b7 : `float`
Centroid :math:`b_7` of the seventh Gaussian term.
c7 : `float`
Peak width :math:`c_7` of the seventh Gaussian term.
a8 : `float`
Amplitude :math:`a_8` of the eigth Gaussian term.
b8 : `float`
Centroid :math:`b_8` of the eigth Gaussian term.
c8 : `float`
Peak width :math:`c_8` of the eigth Gaussian term.
Returns
-------
fit : `numpy.ndarray`
Fitted :math:`y`-values.
"""
return gauss(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, a4, b4, c4,
a5, b5, c5, a6, b6, c6, a7, b7, c7, a8, b8, c8)