Distribution Fitting (nemora.fit)
nemora.fit hosts the shared estimators, grouped-data solvers, and helper utilities that power
the current alpha milestone. The module is designed to work with the canonical distribution registry
in nemora.distributions and the shared dataclasses in nemora.core.
Key Concepts
FitConfigencapsulates starting values, optional bounds, and weights used during optimisation.fit_inventoryaccepts anInventorySpecand evaluates one or more candidate distributions. Grouped estimators are selected automatically wheninventory.metadata["grouped"]evaluates toTrue.Grouped estimators for Weibull, Johnson SB, Birnbaum–Saunders, and generalised secant mixtures live under
nemora.fit.grouped. They expose diagnostics describing the solver path (grouped-ls,grouped-em,grouped-mle).Mixture utilities (
fit_mixture_grouped,fit_mixture_samples,mixture_pdf,mixture_cdf,sample_mixture) support finite mixtures with grouped tallies or sample-level data.All fitted results include a
diagnostics["method"]entry (curve-fit,lmfit-model,grouped-ls,grouped-mle, …) plus residual summaries and per-fit metadata for downstream reporting.
Module-level functions return FitResult or MixtureFitResult instances from nemora.core.
import numpy as np
from nemora.fit import MixtureComponentSpec, fit_mixture_grouped
hist, edges = np.histogram(samples, bins=40)
midpoints = 0.5 * (edges[:-1] + edges[1:])
mixture = fit_mixture_grouped(
midpoints,
hist,
[MixtureComponentSpec("gamma"), MixtureComponentSpec("gamma")],
random_state=42,
)
print(mixture.components[0].weight)
API Reference
.. py:module:: nemora.fit
Shared fitting strategies for nemora.
.. py:class:: FitConfig(distribution, initial, bounds=None, weights=None) :module: nemora.fit
Bases: :py:class:object
Configuration payload describing how a candidate distribution should be fitted.
:type distribution: :sphinx_autodoc_typehints_type:\:py\:class\:\str` :param distribution: Registry name for the distribution to evaluate. :type initial: :sphinx_autodoc_typehints_type::py:class:`dict`\ \[:py:class:`str`, :py:class:`float`] :param initial: Mapping of parameter names to initial values supplied to the optimiser. :type bounds: :sphinx_autodoc_typehints_type::py:class:`dict`\ \[:py:class:`str`, :py:class:`tuple`\ \[:py:class:`float` | :py:obj:`None`, :py:class:`float` | :py:obj:`None`]] | :py:obj:`None` :param bounds: Optional parameter bounds expressed as ``(lower, upper)`` tuples. ``None`` disables bounding for that parameter. :type weights: :sphinx_autodoc_typehints_type::py:class:`~numpy.ndarray` | :py:obj:`None``
:param weights: Optional vector of observation weights (e.g., compression factors); when provided they are
forwarded to the underlying optimiser.
.. py:attribute:: FitConfig.bounds :module: nemora.fit :type: dict[str, tuple[float | None, float | None]] | None
.. py:attribute:: FitConfig.distribution :module: nemora.fit :type: str
.. py:attribute:: FitConfig.initial :module: nemora.fit :type: dict[str, float]
.. py:attribute:: FitConfig.weights :module: nemora.fit :type: ~numpy.ndarray | None
.. py:class:: MixtureComponentSpec(distribution, initial=None) :module: nemora.fit :canonical: nemora.fit.mixture.MixtureComponentSpec
Bases: :py:class:object
Describe one component of a finite mixture.
.. py:attribute:: MixtureComponentSpec.distribution :module: nemora.fit :type: str
.. py:attribute:: MixtureComponentSpec.initial :module: nemora.fit :type: dict[str, float] | None
.. py:function:: default_fit_config(name, x, y) :module: nemora.fit
Construct a heuristic :class:FitConfig for the requested distribution.
The helper inspects the supplied stand table and synthesises parameter seeds and bounds that
keep the optimiser on a sensible domain. The seeds are conservative—callers can refine the
result or provide their own configuration via FitConfig.
:type name: :sphinx_autodoc_typehints_type:\:py\:class\:\str` :param name: Registry name of the distribution. :type x: :sphinx_autodoc_typehints_type::py:class:`~numpy.ndarray` :param x: Bin midpoints or sample observations in centimetres. :type y: :sphinx_autodoc_typehints_type::py:class:`~numpy.ndarray``
:param y: Observed tallies or density values aligned with x.
:returns: Heuristic configuration populated with seeds, bounds, and (when appropriate) scale terms. :rtype: FitConfig
.. py:function:: fit_inventory(inventory, distributions, configs, *, fitter=
Fit one or more candidate distributions to a stand table or grouped inventory.
:type inventory: :sphinx_autodoc_typehints_type:\:py\:class\:\~nemora.core.InventorySpec` :param inventory: Inventory payload describing the bins/tallies and metadata (e.g., ``metadata['grouped']``). :type distributions: :sphinx_autodoc_typehints_type::py:class:`~collections.abc.Iterable`\ \[:py:class:`str`] :param distributions: Sequence of registry names to evaluate. :type configs: :sphinx_autodoc_typehints_type::py:class:`~collections.abc.Mapping`\ \[:py:class:`str`, :py:class:`~nemora.fit.FitConfig`] :param configs: Mapping of distribution names to :class:FitConfig instances. Missing entries are populated via :func:default_fit_config. :type fitter: :sphinx_autodoc_typehints_type::py:class:`~collections.abc.Callable`\ \[\[:py:class:`~numpy.ndarray`, :py:class:`~numpy.ndarray`, :py:class:`~nemora.distributions.base.Distribution`, :py:class:`~nemora.fit.FitConfig`], :py:class:`~nemora.core.FitResult`]`
:param fitter: Callable implementing the optimisation primitive. Defaults to SciPy curve_fit; grouped
inventories automatically invoke specialised estimators when available.
:returns: Fitted results in the order requested. :rtype: list[FitResult]
.. py:function:: fit_mixture_grouped(bins, tallies, components, *, max_iter=200, tol=1e-06, min_weight=0.0001, random_state=None) :module: nemora.fit
Fit a finite mixture to grouped (binned) tallies via EM.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~nemora.core.MixtureFitResult``
.. py:function:: fit_mixture_samples(samples, components, *, bins=None, max_iter=200, tol=1e-06, min_weight=0.0001, random_state=None) :module: nemora.fit
Wrapper that converts raw samples into grouped tallies before fitting.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~nemora.core.MixtureFitResult``
.. py:function:: mixture_cdf(x, components) :module: nemora.fit
Evaluate the mixture CDF at points x.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~numpy.ndarray``
.. py:function:: mixture_pdf(x, components) :module: nemora.fit
Evaluate the PDF of a fitted mixture at points x.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~numpy.ndarray``
.. py:function:: sample_mixture(size, components, *, random_state=None, lower=None, upper=None, weight_overrides=None) :module: nemora.fit
Draw random samples from a fitted mixture.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~numpy.ndarray``
.. py:module:: nemora.fit.grouped
Grouped-data estimators for selected distributions.
.. py:function:: get_grouped_estimator(name) :module: nemora.fit.grouped
Return a grouped estimator for the given distribution, if available.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~collections.abc.Callable`\ \[\[:py:class:`~nemora.core.InventorySpec`, :py:class:`~nemora.fit.FitConfig` | :py:obj:`None`], :py:class:`~nemora.core.FitResult`] | :py:obj:`None``
.. py:module:: nemora.fit.mixture
Finite mixture fitting utilities.
.. py:class:: MixtureComponentSpec(distribution, initial=None) :module: nemora.fit.mixture
Bases: :py:class:object
Describe one component of a finite mixture.
.. py:attribute:: MixtureComponentSpec.distribution :module: nemora.fit.mixture :type: str
.. py:attribute:: MixtureComponentSpec.initial :module: nemora.fit.mixture :type: dict[str, float] | None
.. py:function:: fit_mixture_grouped(bins, tallies, components, *, max_iter=200, tol=1e-06, min_weight=0.0001, random_state=None) :module: nemora.fit.mixture
Fit a finite mixture to grouped (binned) tallies via EM.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~nemora.core.MixtureFitResult``
.. py:function:: fit_mixture_samples(samples, components, *, bins=None, max_iter=200, tol=1e-06, min_weight=0.0001, random_state=None) :module: nemora.fit.mixture
Wrapper that converts raw samples into grouped tallies before fitting.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~nemora.core.MixtureFitResult``
.. py:function:: mixture_cdf(x, components) :module: nemora.fit.mixture
Evaluate the mixture CDF at points x.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~numpy.ndarray``
.. py:function:: mixture_pdf(x, components) :module: nemora.fit.mixture
Evaluate the PDF of a fitted mixture at points x.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~numpy.ndarray``
.. py:function:: sample_mixture(size, components, *, random_state=None, lower=None, upper=None, weight_overrides=None) :module: nemora.fit.mixture
Draw random samples from a fitted mixture.
:rtype: :sphinx_autodoc_typehints_type:\:py\:class\:\~numpy.ndarray``
.. todo:: Expand this page with grouped-fitting theory notes and worked examples once the ingest and sampling modules are in place.