Source code for pymultifit.generators.generators

"""Created on Jul 18 00:35:26 2024"""

from typing import List, Tuple, Type, Union

import numpy as np
from custom_inherit import doc_inherit

from .. import distributions as dist, doc_style, GAUSSIAN, LAPLACE, LINE, LOG_NORMAL, SKEW_NORMAL
from ..distributions.backend import BaseDistribution

listOfTuples = List[Tuple[float, ...]]
listOfTuplesOrArray = Union[listOfTuples, np.ndarray]


[docs] def multi_base(x: np.ndarray, distribution_func: Type[BaseDistribution], params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: """Generate data based on a combination of distributions with optional noise. Parameters ---------- x : np.ndarray Input array of values. distribution_func: Type[BaseDistribution] The distribution function to be used to generate data. params : listOfTuplesOrArray List of tuples containing the parameters for the required distribution. noise_level : float, optional Standard deviation of the noise to be added to the data. Defaults to 0.0. normalize : bool, optional If ``True``, the distribution is normalized so that the total area under the PDF equals 1. Defaults to ``False``. Returns ------- np.ndarray Array of the same shape as :math:`x`, containing the evaluated values. """ y = np.zeros_like(x, dtype=float) for param_set in params: if isinstance(param_set, float): param_set = [param_set] y += distribution_func(*param_set, normalize=normalize).pdf(x) if noise_level > 0: y += noise_level * np.random.normal(size=x.size) return y
[docs] def multi_chi_squared(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r""" Generate multi-:class:`~pymultifit.distributions.chiSquare_d.ChiSquareDistribution` data with optional noise. Parameters ---------- x : np.ndarray Input array of values. params : listOfTuplesOrArray List of tuples containing the parameters for the required distribution. noise_level : float, optional Standard deviation of the noise to be added to the data. Defaults to 0.0. normalize : bool, optional If ``True``, the distribution is normalized so that the total area under the PDF equals 1. Defaults to ``False``. Returns ------- np.ndarray Array of the same shape as :math:`x`, containing the evaluated values. """ return multi_base(x=x, distribution_func=dist.ChiSquareDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_gamma_sr(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.gamma_d.GammaDistributionSR` data with optional noise.""" return multi_base(x=x, distribution_func=dist.GammaDistributionSR, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_gamma_ss(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.gamma_d.GammaDistributionSS` data with optional noise.""" return multi_base(x=x, distribution_func=dist.GammaDistributionSS, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_exponential(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.exponential_d.ExponentialDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.ExponentialDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_folded_normal(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.foldedNormal_d.FoldedNormalDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.FoldedNormalDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_gaussian(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.gaussian_d.GaussianDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.GaussianDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_half_normal(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.halfNormal_d.HalfNormalDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.HalfNormalDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_laplace(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.laplace_d.LaplaceDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.LaplaceDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_log_normal(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.logNormal_d.LogNormalDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.LogNormalDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] @doc_inherit(parent=multi_chi_squared, style=doc_style) def multi_skew_normal(x: np.ndarray, params: listOfTuplesOrArray, noise_level: float = 0.0, normalize: bool = False) -> np.ndarray: r"""Generate multi-:class:`~pymultifit.distributions.skewNormal_d.SkewNormalDistribution` data with optional noise.""" return multi_base(x=x, distribution_func=dist.SkewNormalDistribution, params=params, noise_level=noise_level, normalize=normalize)
[docs] def multiple_models(x: np.ndarray, params: listOfTuplesOrArray, model_list, noise_level=0.0, normalize: bool = False) -> np.ndarray: r""" Generate data based on a combination of different models with optional noise. Parameters ---------- x : np.ndarray Input array of values. params : listOfTuplesOrArray List of tuples containing the parameters for each model. model_list : list A list of model names corresponding to the models to be used. noise_level : float, optional Standard deviation of the noise to be added to the data, by default 0.0. normalize : bool, optional If ``True``, the distribution is normalized so that the total area under the PDF equals 1. Defaults to ``False``. Returns ------- np.ndarray Array of the same shape as :math:`x`, containing the evaluated values. """ y = np.zeros_like(x, dtype=float) model_mapping = {GAUSSIAN: dist.GaussianDistribution, LOG_NORMAL: dist.LogNormalDistribution, LAPLACE: dist.LaplaceDistribution, SKEW_NORMAL: dist.SkewNormalDistribution, LINE: dist.line} for par_index, model in enumerate(model_list): if model in model_mapping: if model == LINE: y += model_mapping[model](x, *params[par_index]) else: y += model_mapping[model](*params[par_index], normalize=normalize).pdf(x) if noise_level > 0: y += noise_level * np.random.normal(size=x.size) return y