curvefit_stats.estimators ¶
Joint least-squares estimation with explicit shared-parameter mappings.
GlobalFitGroup fits independent datasets jointly; eiv_curve_fit accounts for independent measurement uncertainty in both axes through SciPy ODR. Numerical helpers are shared with inference without circular imports.
GlobalFitGroup ¶
Fit named datasets with shared and dataset-specific model parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
callable
|
Common model |
required |
datasets
|
mapping
|
Nonempty mapping of dataset names to dictionaries containing x, y, and optional sigma. Scalar/vector y and x with observations on the last axis are supported. sigma is a positive scalar/vector standard deviation or a positive-definite observation covariance. Inputs are copied. |
required |
shared_parameters
|
set or mapping
|
Set of local model parameter names shared across all datasets, or a map from local names to shared global aliases. Explicit repeated aliases tie those model parameters to one global variable. Unlisted parameters receive independent dataset-specific variables. |
frozenset()
|
parameter_names
|
sequence of str
|
Explicit names in model argument order, required for ambiguous/variadic model signatures. Overrides names but must match an inferable count. |
None
|
Returns:
| Type | Description |
|---|---|
GlobalFitGroup
|
Configured fitting group; call fit to obtain parameter estimates, covariance, predictions, residuals, and diagnostics. |
Raises:
| Type | Description |
|---|---|
ValueError
|
Invalid dataset names/shapes, uncertainties, parameter names, or sharing mappings. Optimizer validation is deferred to fit. |
Notes
The joint objective is sum_d r_d.T @ inv(C_d) @ r_d, using one optimized variable for each shared global degree of freedom. Global covariance is obtained from the joint whitened residual Jacobian.
Shared globals follow first occurrence in model argument order. Dataset names are sorted lexically; their local globals follow model argument order and are named 'dataset.parameter'. Shared aliases are bare identifiers. The public parameter_indices property exposes local-to-global integer maps.
Errors are independent between datasets. sigma=None means unit relative weight, or known unit variance when absolute_sigma=True. With False one unknown scale multiplies the entire block-diagonal observation covariance; separate unknown variance scales per dataset are not estimated. Cross-dataset error covariance is unsupported. The solver finds a local optimum, and rank diagnoses local numerical dependence rather than structural identifiability.
Examples:
>>> import numpy as np
>>> model = lambda x, slope, intercept: slope*x+intercept
>>> group = GlobalFitGroup(model, {
... 'a': {'x': np.arange(3.), 'y': [1., 3., 5.]},
... 'b': {'x': np.arange(4.), 'y': [3., 5., 7., 9.]},
... }, shared_parameters={'slope'})
>>> result = group.fit([1., 0., 0.], absolute_sigma=True)
>>> result.parameter_names
('slope', 'a.intercept', 'b.intercept')
>>> np.allclose(result.popt, [2., 1., 3.])
True
>>> result.success
True
parameter_names
property
¶
parameter_names: tuple[str, ...]
Return global parameter names in their optimization vector order.
model_parameter_names
property
¶
model_parameter_names: tuple[str, ...]
Return local names in model argument order.
dataset_names
property
¶
dataset_names: tuple[str, ...]
Return datasets in residual-concatenation order.
parameter_indices
property
¶
parameter_indices: Mapping[str, _Index]
Return independent local-to-global index copies for each dataset.
__init__ ¶
__init__(model: _Model, datasets: Mapping[str, Mapping[str, ArrayLike | None]], shared_parameters: Set[str] | Mapping[str, str] = frozenset(), *, parameter_names: Sequence[str] | None = None) -> None
Validate data and build an explicit deterministic parameter mapping.
fit ¶
fit(p0: ArrayLike | Mapping[str, float] | None = None, bounds: tuple[Any, Any] | Mapping[str, tuple[float, float]] = (-np.inf, np.inf), *, absolute_sigma: bool = False, jac: _Jacobian = '3-point', rank_tolerance: float | None = None, **kwargs: Any) -> _GlobalFitResult
Optimize one global parameter vector and estimate its joint covariance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p0
|
array_like or mapping
|
Vector in parameter_names order or complete mapping from global names to values. Defaults to ones for unbounded variables and feasible midpoints/interior points for bounded variables. |
None
|
bounds
|
tuple or mapping
|
Scalar/vector (lower, upper) or global-name-to-(lower, upper) map. Omitted names are unbounded. Equal limits denote exactly fixed parameters; they are removed from the optimizer vector. |
(-inf, inf)
|
absolute_sigma
|
bool
|
True uses known observation variances. False scales covariance by weighted SSE/(N-p), counting each estimated shared variable once. |
False
|
jac
|
('2-point', '3-point')
|
Finite differences obey optimization bounds. A callable returns the local model Jacobian, shape (n_dataset, n_model_parameters), from jac(x, *local_parameters). Shared/tied columns are assembled and whitened automatically. Complex-step differentiation is unsupported. |
'2-point'
|
rank_tolerance
|
float
|
Relative singular-value cutoff on column-normalized Jacobians. Default is max(N,p)*eps for analytic derivatives and at least 1e-7 for numerical derivatives. Supply an analytic jac to resolve very close directions; rank deficiency never produces a finite pseudoinverse. |
None
|
**kwargs
|
Any
|
Supported scipy.optimize.least_squares options. Only loss='linear' is allowed, preserving Gaussian least-squares covariance semantics. Array x_scale, diff_step, and jac_sparsity refer to non-fixed variables in global order. Solver args/kwargs overrides are not supported. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
result |
typed dataclass
|
popt, pcov, parameter_names, datasets, weighted_residuals, jacobian, active_mask, solver, and diagnostics. Each datasets[name] contains parameters, local popt, predictions, and raw/weighted residuals. result.success reflects solver convergence, not identifiability. |
Raises:
| Type | Description |
|---|---|
ValueError
|
Invalid guesses, bounds, solver options, uncertainties, or Jacobians. |
FloatingPointError
|
Weighted residuals or numerical Jacobian calculations are non-finite. |
Notes
For an interior full-rank global Jacobian J_r, covariance is inv(J_r.T @ J_r), multiplied by weighted SSE/(N-p) only for relative error scales. Equal bounds remove exactly fixed variables.
Optimization internally divides residuals/Jacobians by a common initial residual magnitude to avoid dependence on arbitrary common error units. Returned residuals, Jacobian, solver cost and optimality are restored to the original weighted units. SciPy gtol applies to the normalized objective; ftol and xtol retain their relative meanings. This improves common-scale invariance, not global-optimum guarantees.
Covariance comes from the actual global residual Jacobian. With active bounds it is conditional on active values: active rows/columns are NaN, and the free block uses N-p_free scaling. diagnostics.dof remains N-p for all optimized variables; covariance_dof explicitly reports N-p_free. Failed convergence or a rank-deficient optimized Jacobian gives all-NaN covariance. Full rank does not prove structural or global identifiability. When all parameters are fixed, success indicates model evaluation only: solver.status is None and nfev/njev are zero; SciPy options are not run. Results can still be inspected when success=False. Ordinary nonlinear Wald uncertainty is only a local approximation.
Examples:
>>> group = GlobalFitGroup(lambda x, a: a*x, {
... 'run': {'x': [1., 2., 3.], 'y': [2.1, 3.9, 6.0]},
... }, {'a'})
>>> result = group.fit({'a': 1.}, bounds={'a': (0., 5.)})
>>> abs(result.datasets['run'].parameters['a']-2) < 0.02
True
eiv_curve_fit ¶
eiv_curve_fit(func: _Model, xdata: ArrayLike, ydata: ArrayLike, p0: ArrayLike | None = None, *, sx: ArrayLike | None = None, sy: ArrayLike | None = None, absolute_sigma: bool = False, full_output: Literal[False] = False, **kwargs: Any) -> tuple[_Array, _Array]
eiv_curve_fit(func: _Model, xdata: ArrayLike, ydata: ArrayLike, p0: ArrayLike | None = None, *, sx: ArrayLike | None = None, sy: ArrayLike | None = None, absolute_sigma: bool = False, full_output: Literal[True], **kwargs: Any) -> tuple[_Array, _Array, _ODRDiagnostics]
eiv_curve_fit(func: _Model, xdata: ArrayLike, ydata: ArrayLike, p0: ArrayLike | None = None, *, sx: ArrayLike | None = None, sy: ArrayLike | None = None, absolute_sigma: bool = False, full_output: bool, **kwargs: Any) -> tuple[_Array, _Array] | tuple[_Array, _Array, _ODRDiagnostics]
eiv_curve_fit(func: _Model, xdata: ArrayLike, ydata: ArrayLike, p0: ArrayLike | None = None, *, sx: ArrayLike | None = None, sy: ArrayLike | None = None, absolute_sigma: bool = False, full_output: bool = False, **kwargs: Any) -> tuple[_Array, _Array] | tuple[_Array, _Array, _ODRDiagnostics]
Fit scalar errors-in-variables models through SciPy's ODRPACK backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
callable
|
Pointwise model written as func(x, *parameters). The adapter reverses arguments for ODR internally. Non-vectorized scalar callables and responses coupling observations are unsupported. |
required |
xdata
|
array_like
|
Finite, nonempty one-dimensional observations of identical length. Only one independent variable and one scalar response are supported. |
required |
ydata
|
array_like
|
Finite, nonempty one-dimensional observations of identical length. Only one independent variable and one scalar response are supported. |
required |
p0
|
array_like
|
Finite initial parameters. When omitted, explicit positional parameter names are inferred and initialized to ones, as in curve_fit. Ambiguous or variadic signatures require p0; keyword-only options are not fitted. |
None
|
sx
|
array_like
|
Positive scalar/vector independent-variable standard deviations. None treats x as exact using ODR's least-squares mode, not unit x error. Zero elements are rejected; fixing selected x observations is unsupported. |
None
|
sy
|
array_like
|
Positive scalar/vector dependent-variable standard deviations. None means unit y weighting, or known unit y variance with absolute_sigma=True. |
None
|
absolute_sigma
|
bool
|
True returns unscaled Output.cov_beta for known absolute error scales. False returns cov_beta*Output.res_var, matching ODR's sd_beta convention. One common unknown scale multiplies both axis covariance specifications. |
False
|
full_output
|
bool
|
False returns (popt, pcov). True additionally returns a typed diagnostics dataclass with termination, rank, residual variance, weighted objective, coordinate corrections, and scaled/unscaled uncertainty information. |
False
|
**kwargs
|
Any
|
ODR controls maxit (default 200), sstol, partol, ndigit, and taufac only. maxit may be zero for diagnostic evaluation. sigma, jac, bounds, method, maxfev, robust losses, and other curve_fit options are rejected. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
popt, pcov : ndarray
|
Parameter vector and covariance of shapes (p,) and (p, p). |
|
diagnostics |
typed dataclass, optional
|
Returned with full_output=True. adjusted_x=xdata+delta and fitted_y is func(adjusted_x, popt). eps is fitted_y-ydata, the ODR sign convention. standard_errors correspond to returned pcov; backend_standard_errors always follow cov_betares_var. dof=N-p only for identified solutions. |
Raises:
| Type | Description |
|---|---|
ValueError
|
Invalid data, uncertainties, parameter guesses, controls, or N <= p. |
RuntimeError
|
Missing/unsupported backend or nonconvergence with full_output=False. |
FloatingPointError
|
Unrepresentable weights or non-finite fitted parameters/results. |
Notes
Supports SciPy >=1.12,<1.19. scipy.odr is deprecated in 1.17 and removed in 1.19. Calls on deprecated versions emit a FutureWarning; the backend import deprecation is translated into that explicit compatibility warning. No replacement dependency is installed. This is not a full curve_fit substitute: bounds, correlated axis errors, multiple predictors, fixed parameters, and analytic ODR derivatives are outside this interface.
With full_output=True, nonconvergence warns and returns current estimates, all-NaN pcov, and success=False. Rank deficiency similarly warns and returns NaN covariance even when the optimizer converged. Full rank is a local numerical diagnostic, not proof of structural identifiability. A numerical relative rank cutoff of at least 1e-7 avoids finite uncertainties fabricated by finite-difference noise in dependent parameter columns.
ODR covariance is a local Gauss-Newton approximation. For independent errors the weighted objective is sum((delta/sx)2)+sum((eps/sy)2); the first term is zero in exact-x mode. For identified fits res_var=objective/(N-p). Zero residual variance makes scaled covariance degenerate and warns. At least one residual degree of freedom is required, including absolute-scale fits. Outputs are copies; inputs are not mutated.
Examples:
>>> import warnings
>>> with warnings.catch_warnings():
... warnings.simplefilter('ignore', FutureWarning)
... popt, pcov = eiv_curve_fit(lambda x, slope: slope*x,
... [1., 2., 3., 4.], [2.1, 3.9, 6.1, 7.9], [2.],
... sx=0.05, sy=0.1, absolute_sigma=True)
>>> abs(popt[0]-2) < 0.02 and pcov.shape == (1, 1)
True