API reference#

Fitting#

fitwise.fit(model, x, y, *, yerr=None, xerr=None, p0=None, bounds=None, fixed=None, loss='linear', loss_scale=None, method='auto', scale_covar=None, nan_policy='raise')[source]#

Fit a model to data.

Parameters:
  • model (Model, callable or str) – A built-in model from fitwise.models, a composition such as gaussian + linear, a function f(x, p1, p2, ...), or an expression such as "a*exp(-x/tau) + c" (see fitwise.ExpressionModel).

  • x (array_like) – Independent variable, shape (n,) or (n, k); passed to the model unchanged.

  • y (array_like) – Measured values, shape (n,).

  • yerr (float or array_like, optional) – Absolute one-sigma uncertainties of y. Without yerr, uncertainties are estimated from the scatter of the residuals.

  • xerr (float or array_like, optional) – Absolute one-sigma uncertainties of x. The fit then uses orthogonal distance regression (odrpack, pip install 'fitwise[odr]'), which also needs yerr.

  • p0 (dict, optional) – Starting values {name: value}; override any heuristic per parameter.

  • bounds (dict, optional) – {name: (lo, hi)}; use None for an open side.

  • fixed (dict, optional) – {name: value} of parameters held constant.

  • loss ({"linear", "soft_l1", "huber", "cauchy", "arctan"}) – "linear" is ordinary least squares. The robust losses downweight outliers: the fit first runs ordinarily, then minimizes the robust loss from that solution. "soft_l1" and "huber" are mild, "cauchy" and "arctan" strong.

  • loss_scale (float, optional) – Residual size at which a robust loss starts to downweight points, in units of yerr. Default: 1.5 with yerr; without yerr, 1.5 times a robust estimate of the scatter (MAD) of an ordinary fit.

  • method ({"auto", "linear", "trf", "lm", "multistart"}) – Solver. "auto" solves models that are linear in their parameters directly (no starting values needed) and uses Trust Region Reflective otherwise; parameters without any starting value are then found by a multi-start. "lm" is Levenberg–Marquardt without bounds; "multistart" samples all free parameters.

  • scale_covar (bool, optional) – Multiply the covariance by χ²/ndf. Default: False with yerr (uncertainties are taken as absolute), True without.

  • nan_policy ({"raise", "omit"}) – What to do with non-finite data points.

Returns:

Parameters with uncertainties, goodness of fit, warnings and a printable report.

Return type:

FitResult

Examples

>>> import fitwise as fw
>>> x = np.linspace(-5, 5, 101)
>>> y = fw.models.gaussian(x, amp=2.0, cen=0.3, sigma=1.1)
>>> result = fw.fit(fw.models.gaussian, x, y + 0.01 * np.cos(7 * x))
>>> round(result.params["cen"].value, 2)
0.3

Results#

class fitwise.FitResult(model, params, data, method, method_reason, converged, nfev, message, free_names, covariance, scale_covar, chi2, ndf, redchi, pvalue, rss, residual_sd, r2, aic, bic, warnings, solver_log, raw, options=<factory>, loss='linear', robust_weights=None)[source]#

Outcome of fitwise.fit(). Identical in structure for every solver.

The most important attributes are params, ok and warnings; print(result) shows the full report.

Parameters:
aic: float#

Akaike information criterion n·ln(χ²/n) + 2k.

bic: float#

Bayesian information criterion n·ln(χ²/n) + k·ln(n).

bootstrap(n=1000, *, method='auto', seed=0)[source]#

Refit resampled data; see fitwise.intervals.bootstrap().

Parameters:
  • n (int)

  • method (Literal['auto', 'parametric', 'residuals', 'cases'])

  • seed (int)

Return type:

BootstrapResult

chi2: float#

Weighted sum of squared residuals Σ((y − f)/yerr)²; equals rss without yerr.

confidence_band(x, level=0.95)[source]#

Band containing the true curve with probability level; see fitwise.bands.

Parameters:
  • x (ArrayLike)

  • level (float)

Return type:

Band

converged: bool#

Whether the solver met its convergence criteria.

property correlation: NDArray[float64] | None#

Correlation matrix of the free parameters.

correlations(threshold=0.0)[source]#

Parameter pairs whose absolute correlation exceeds threshold, strongest first.

Parameters:

threshold (float)

Return type:

dict[tuple[str, str], float]

covariance: NDArray[float64] | None#

Covariance of the free parameters (scaled per scale_covar), or None.

data: FitData#

The data used in the fit (after nan_policy).

property downweighted: NDArray[float64]#

Boolean mask of points a robust fit treated as outliers (weight below 0.5).

property effective_yerr: NDArray[float64] | None#

yerr, or √(yerr² + (f′(x)·xerr)²) if x has uncertainties too.

eval(x=None)[source]#

Evaluate the fitted model at x (default: the data’s x).

Parameters:

x (ArrayLike | None)

Return type:

NDArray[float64]

free_names: tuple[str, ...]#

Names of the varied parameters; the order of covariance.

property guess_strategy: dict[str, str]#

How each starting value was obtained.

property initial_guess: dict[str, float]#

Starting value of every parameter.

loss: str = 'linear'#

"linear" for ordinary least squares, otherwise the robust loss used.

message: str#

The solver’s status message.

method: str#

Solver that ran.

method_reason: str#

Why this solver was chosen.

model: Model#

The fitted model.

ndf: int#

points minus free parameters.

Type:

Degrees of freedom

nfev: int#

Number of model evaluations.

property normalized_residuals: NDArray[float64]#

(y − f(x)) / σ; equals residuals without yerr.

σ is yerr, or with xerr the effective uncertainty √(yerr² + (f′(x)·xerr)²).

property ok: bool#

True if the solver converged and parameter uncertainties are available.

options: Mapping[str, Any]#

The fit options as given by the user.

params: Parameters#

Fitted parameters with uncertainties, including fixed ones.

plot(*, residuals=True, band='confidence', level=0.95, ax=None, show_params=False)[source]#

Plot data, fit, band and residuals; see fitwise.plotting.plot_result().

Parameters:
  • residuals (bool)

  • band (Literal['confidence', 'prediction'] | None)

  • level (float)

  • ax (Axes | None)

  • show_params (bool)

Return type:

tuple[Figure, list[Axes]]

prediction_band(x, level=0.95, *, yerr_new=None)[source]#

Band containing a new measurement with probability level.

Parameters:
  • x (ArrayLike)

  • level (float)

  • yerr_new (ArrayLike | None)

Return type:

Band

profile(names=None, *, level=0.6827)[source]#

Profile-likelihood intervals; see fitwise.intervals.profile().

Parameters:
Return type:

ProfileResult

pvalue: float | None#

Probability of a χ² at least this large if model and yerr are right (needs yerr).

r2: float#

Coefficient of determination, weighted with 1/yerr² if yerr is given.

raw: object#

The backend’s native result object.

redchi: float | None#

χ²/ndf, or None if ndf == 0.

residual_sd: float | None#

Residual standard deviation √(rss/ndf).

property residuals: NDArray[float64]#

y − f(x).

robust_weights: NDArray[float64] | None = None#

Robust weights at the solution (1 = normal point, ≪ 1 = outlier); None if not robust.

rss: float#

Unweighted residual sum of squares.

scale_covar: bool#

Whether the covariance was multiplied by χ²/ndf.

solver_log: tuple[str, ...]#

What the solver did, step by step.

to_dict(*, include_data=False)[source]#

JSON-serializable record of the fit; see fitwise.serialize.to_dict().

Parameters:

include_data (bool)

Return type:

dict[str, Any]

warnings: tuple[FitWarning, ...]#

Everything that makes the result questionable.

property x: NDArray[float64]#

Independent variable.

property y: NDArray[float64]#

Dependent variable.

property yerr: NDArray[float64] | None#

Uncertainties of y, if given.

class fitwise.Parameter(name, value, stderr, init_value, guess_strategy, bounds=(-inf, inf), fixed=False)[source]#

A single fitted parameter.

Parameters:
name#

Parameter name as used by the model.

Type:

str

value#

Best-fit value (or the fixed value).

Type:

float

stderr#

One-sigma standard error; None if fixed or if the covariance is unavailable.

Type:

float or None

init_value#

Starting value of the fit.

Type:

float

guess_strategy#

How the starting value was obtained, e.g. "p0" or "peak heuristic".

Type:

str

bounds#

Lower and upper bound; ±inf means unbounded.

Type:

tuple of float

fixed#

Whether the parameter was held fixed.

Type:

bool

property is_bounded: bool#

Whether at least one bound is finite.

property relative_error: float | None#

stderr / |value|, or None if undefined.

class fitwise.Parameters(params, *, covariance=None, free_names=())[source]#

Ordered, read-only collection of Parameter objects.

Supports item access (params["sigma"]) and attribute access (params.sigma).

Parameters:
as_array()[source]#

Return the best-fit values as an array in model order.

Return type:

NDArray[float64]

as_ufloat()[source]#

Return the parameters as correlated uncertainties.ufloat values.

Calculations with the returned values propagate errors including the correlations between parameters. Fixed parameters are returned as plain floats. Requires the uncertainties package (pip install 'fitwise[units]').

Examples

>>> import fitwise as fw
>>> x = np.linspace(0, 1, 20)
>>> r = fw.fit(fw.models.linear, x, 2 * x + 1 + 0.01 * np.sin(17 * x))
>>> u = r.params.as_ufloat()
>>> round((u["slope"] + u["intercept"]).nominal_value, 2)
3.0
Return type:

dict[str, Any]

errors_dict()[source]#

Return the standard errors as {name: stderr}.

Return type:

dict[str, float | None]

values_dict()[source]#

Return the best-fit values as {name: value}.

Return type:

dict[str, float]

Models#

class fitwise.Model(func, *, name=None, param_names=None, guess=None, guess_label=None, linear=None, shape='other', symmetric=(), abbrev=None, formula=None, param_docs=None)[source]#

A fit model built from a Python function.

Parameters:
  • func (callable) – func(x, p1, p2, ...) returning an array shaped like y. The first argument is the independent variable; all further positional arguments are fit parameters. Numeric default values are used as starting values.

  • name (str, optional) – Name shown in the report. Defaults to func.__name__.

  • param_names (sequence of str, optional) – Parameter names, required if they cannot be read from the signature (func(x, *p)).

  • guess (callable, optional) – guess(x, y) -> {name: value} with starting values estimated from the data.

  • guess_label (str, optional) – Short description of the guess heuristic for the report.

  • linear (bool, optional) – Whether the model is linear in its parameters; None if unknown.

  • shape ({"peak", "monotone", "oscillation", "baseline", "other"}) – Qualitative shape; used to guess starting values of composite models.

  • symmetric (sequence of str) – Parameters the model depends on only through their absolute value, such as a Gaussian width. Their sign is normalized to positive after the fit.

  • abbrev (str, optional) – Short name for automatic prefixes in composite models (g1_amp).

  • formula (str, optional) – The model equation in LaTeX, for documentation and export.

  • param_docs (mapping, optional) – {name: description} for documentation.

Examples

>>> def decay(t, amp, tau=1.0):
...     return amp * np.exp(-t / tau)
>>> model = Model(decay)
>>> model.param_names
('amp', 'tau')
>>> model + Model(lambda t, c: c + 0 * t)
CompositeModel(decay(x; amp, tau) + model(x; c))
canonicalize(values)[source]#

Map equivalent solutions to a canonical one.

Returns the new values and the sign (±1) applied to each parameter, so that the covariance can be transformed consistently.

Parameters:

values (Mapping[str, float])

Return type:

tuple[dict[str, float], dict[str, float]]

property defaults: dict[str, float]#

Starting values from the function signature.

eval(x, params)[source]#

Evaluate the model at x for the parameter values in params.

Parameters:
Return type:

NDArray[float64]

guess(x, y)[source]#

Estimate starting values from data; may return only some parameters.

Parameters:
  • x (ArrayLike)

  • y (ArrayLike)

Return type:

dict[str, float]

property leaves: tuple[Model, ...]#

The elementary models this model is composed of.

property param_names: tuple[str, ...]#

Parameter names including the prefix.

signature()[source]#

Human-readable signature, e.g. gaussian(x; amp, cen, sigma).

Return type:

str

with_prefix(prefix)[source]#

Return a copy whose parameter names start with prefix.

Examples

>>> from fitwise.models import gaussian
>>> gaussian.with_prefix("peak_").param_names
('peak_amp', 'peak_cen', 'peak_sigma')
Parameters:

prefix (str)

Return type:

Model

class fitwise.ExpressionModel(expression, *, independent='x', name=None)[source]#

A Model defined by a text expression.

Parameters:
  • expression (str) – For example "a*exp(-x/tau) + c". Parameters are all names other than the independent variable, the functions in FUNCTIONS and pi, in order of first appearance.

  • independent (str) – Name of the independent variable.

  • name (str, optional) – Name for the report; defaults to "expression".

Examples

>>> m = ExpressionModel("a*exp(-t/tau) + c", independent="t")
>>> m.param_names
('a', 'tau', 'c')
>>> float(m(0.0, a=2.0, tau=1.0, c=0.5))
2.5
signature()[source]#

Return the expression as signature, e.g. y = a*exp(-x/tau) + c.

Return type:

str

fitwise.expression.FUNCTIONS: dict[str, Callable[[...], Any]]#

Functions available in expressions.

class fitwise.CompositeModel(left, right, op)[source]#

Sum or product of two models; created with model_a + model_b or model_a * model_b.

Parameter names that occur in more than one component get automatic prefixes, for example gaussian + gaussian has parameters g1_amp, g1_cen, g1_sigma, g2_amp, .... Components with an explicit prefix (Model.with_prefix()) keep it.

Parameters:
property defaults: dict[str, float]#

Starting values from the component signatures.

eval(x, params)[source]#

Evaluate both components and combine them.

Parameters:
Return type:

NDArray[float64]

property leaves: tuple[Model, ...]#

The elementary models in evaluation order.

property param_names: tuple[str, ...]#

Parameter names of all components.

signature()[source]#

Signatures of the components joined by the operator.

Return type:

str

with_prefix(prefix)[source]#

Not supported; prefix the components instead.

Parameters:

prefix (str)

Return type:

Model

Built-in models#

Constant, linear and polynomial models (linear in their parameters).

fitwise.models.basic.constant = Model(constant(x; c))#

Constant offset \(c\).

Parameters:
Return type:

FloatArray

fitwise.models.basic.linear = Model(linear(x; slope, intercept))#

Straight line \(\mathrm{slope}\,x + \mathrm{intercept}\).

Parameters:
Return type:

FloatArray

fitwise.models.basic.polynomial(degree)[source]#

Polynomial \(c_0 + c_1 x + \dots + c_n x^n\) of the given degree.

Parameters:

degree (int) – Polynomial degree n >= 0; the parameters are c0 to cn.

Return type:

Model

Examples

>>> polynomial(2).param_names
('c0', 'c1', 'c2')

Peak shapes. amp is always the peak height, cen the position.

fitwise.models.peaks.gaussian = Model(gaussian(x; amp, cen, sigma))#

Gaussian peak of height amp at cen with standard deviation sigma.

Parameters:
Return type:

FloatArray

fitwise.models.peaks.lorentzian = Model(lorentzian(x; amp, cen, gamma))#

Lorentzian peak of height amp at cen with half width gamma.

Parameters:
Return type:

FloatArray

fitwise.models.peaks.voigt = Model(voigt(x; amp, cen, sigma, gamma))#

Voigt peak (Gaussian ⊗ Lorentzian) of height amp at cen.

Parameters:
Return type:

FloatArray

Exponential, sigmoid, power-law and oscillating models.

fitwise.models.curves.damped_sine = Model(damped_sine(x; amp, freq, phase, tau))#

Exponentially damped sine oscillation.

Parameters:
Return type:

FloatArray

fitwise.models.curves.exponential = Model(exponential(x; amp, tau))#

Exponential decay amp * exp(-x/tau); add constant for an offset.

Parameters:
Return type:

FloatArray

fitwise.models.curves.powerlaw = Model(powerlaw(x; amp, exponent))#

Power law amp * x**exponent.

Parameters:
Return type:

FloatArray

fitwise.models.curves.sigmoid = Model(sigmoid(x; amp, cen, width))#

Logistic step from 0 to amp centred at cen; add constant for an offset.

Parameters:
Return type:

FloatArray

Bands#

Confidence and prediction bands of a fitted model (delta method).

class fitwise.bands.Band(x, center, lower, upper, level, kind)[source]#

A band around the fitted curve.

x is where the band is evaluated, center the fitted model there, lower and upper the band limits, level the coverage probability (e.g. 0.95), and kind says what the band covers: "confidence" (the true curve) or "prediction" (a new measurement).

Parameters:
  • x (NDArray[float64])

  • center (NDArray[float64])

  • lower (NDArray[float64])

  • upper (NDArray[float64])

  • level (float)

  • kind (Literal['confidence', 'prediction'])

center: NDArray[float64]#

Alias for field number 1

kind: Literal['confidence', 'prediction']#

Alias for field number 5

level: float#

Alias for field number 4

lower: NDArray[float64]#

Alias for field number 2

upper: NDArray[float64]#

Alias for field number 3

x: NDArray[float64]#

Alias for field number 0

fitwise.bands.confidence_band(result, x, level=0.95)[source]#

Band that contains the true curve with probability level at each x.

Parameters:
Return type:

Band

fitwise.bands.model_jacobian(result, x)[source]#

Differentiate the fitted model at x with respect to the free parameters.

Central differences with a step relative to each parameter’s magnitude, so that parameters of any scale (for example 1e-12) are differentiated accurately.

Parameters:
Return type:

FloatArray

fitwise.bands.prediction_band(result, x, level=0.95, *, yerr_new=None)[source]#

Band that contains a new measurement with probability level at each x.

The measurement scatter is yerr_new if given; otherwise yerr of the fit if it is the same for all points, or the residual scatter if the fit had no yerr. With scale_covar, the scatter is scaled by χ²/ndf like the covariance.

Parameters:
  • result (FitResult)

  • x (ArrayLike)

  • level (float)

  • yerr_new (ArrayLike | None)

Return type:

Band

Bootstrap and profile likelihood#

Uncertainties beyond the covariance matrix: bootstrap and profile likelihood.

Both refit the model many times with the options of the original fit, starting from its solution. They are slower than the covariance but do not assume that the model is linear near the solution, so they reveal asymmetric uncertainties.

class fitwise.intervals.BootstrapResult(result, samples, method, n_failed)[source]#

Parameter distributions from refitting resampled data.

Parameters:
result#

The original fit.

Type:

FitResult

samples#

Shape (n_ok, k): refitted values of the free parameters, in result.free_names order, for every resample that converged.

Type:

ndarray

method#

How the data were resampled.

Type:

{“parametric”, “residuals”, “cases”}

n_failed#

Resamples whose refit did not converge; they are excluded.

Type:

int

property covariance: NDArray[float64]#

Covariance of the free parameters over the resamples.

interval(name, level=0.6826894921370859)[source]#

Percentile interval of one parameter (default: central 68.3 %).

Parameters:
Return type:

Interval

property std: dict[str, float]#

Standard deviation of each parameter over the resamples.

class fitwise.intervals.Interval(value, lower, upper, level)[source]#

A confidence interval [lower, upper] around value; ±inf if open.

Parameters:
level: float#

Alias for field number 3

lower: float#

Alias for field number 1

property minus: float#

Distance from the value down to the lower limit.

property plus: float#

Distance from the value up to the upper limit.

upper: float#

Alias for field number 2

value: float#

Alias for field number 0

class fitwise.intervals.ProfileResult(result, intervals, delta_chi2)[source]#

Profile-likelihood intervals of the free parameters.

Parameters:
result#

The original fit.

Type:

FitResult

intervals#

{name: Interval}.

Type:

dict

delta_chi2#

The χ² increase that defines the interval edges.

Type:

float

fitwise.intervals.bootstrap(result, n=1000, *, method='auto', seed=0)[source]#

Refit n resampled data sets.

Parameters:
  • result (FitResult) – The fit to examine.

  • n (int) – Number of resamples.

  • method ({"auto", "parametric", "residuals", "cases"}) – "parametric" adds Gaussian noise of size yerr to the fitted curve, consistent with absolute uncertainties. "residuals" adds resampled residuals instead, so the observed scatter counts. "cases" resamples data points with replacement, which also captures model misspecification but needs enough points. "auto" chooses "parametric" if yerr is taken as absolute and "residuals" otherwise, like the covariance (ADR 3).

  • seed (int) – Seed of the random resampling.

Return type:

BootstrapResult

fitwise.intervals.profile(result, names=None, *, level=0.6826894921370859, max_steps=30)[source]#

Profile-likelihood confidence intervals.

For each parameter, the interval contains all values for which χ², minimized over the other parameters, rises by at most Δχ² = χ²₁⁻¹(level) (1 for 68.3 %). Without yerr, Δχ² is scaled by χ²/ndf. For a model that is linear in its parameters this reproduces value ± σ; for nonlinear models the interval can be asymmetric. Interval edges that are never reached within max_steps widening steps are reported as ±inf.

Parameters:
Return type:

ProfileResult

Warnings#

Warnings that flag fit results which should not be trusted blindly.

Every warning is stored in fitwise.FitResult.warnings, printed in the report and emitted through Python’s warnings machinery. Silence them with the standard filters, for example warnings.simplefilter("ignore", fitwise.warnings.StrongCorrelationWarning).

exception fitwise.warnings.FitWarning[source]#

Base class of all fitwise warnings.

exception fitwise.warnings.LargeUncertaintyWarning[source]#

A parameter’s standard error exceeds its absolute value.

exception fitwise.warnings.NotConvergedWarning[source]#

The solver stopped without meeting its convergence criteria.

exception fitwise.warnings.ParameterAtBoundWarning[source]#

A parameter ended at one of its bounds; its uncertainty is unreliable.

exception fitwise.warnings.PoorChiSquareWarning[source]#

χ²/ndf is implausible for the given yerr: wrong model or wrong uncertainties.

exception fitwise.warnings.SingularCovarianceWarning[source]#

The covariance matrix could not be estimated; parameters may be unidentifiable.

exception fitwise.warnings.StrongCorrelationWarning[source]#

Two parameters are almost fully correlated (absolute correlation above 0.999).

The data then determine only a combination of the two. Their individual uncertainties are correct but large; combine them using the covariance, or reparametrize the model.

Output#

fitwise.report.format_measurement(value, error)[source]#

Round a value and its uncertainty consistently.

The uncertainty is rounded to two significant digits and the value to the same decimal place. Very large or small numbers use a shared power of ten.

Examples

>>> format_measurement(1.51234, 0.01937)
('1.512', '0.019')
>>> format_measurement(56789.0, 1234.0)
('56800', '1200')
>>> format_measurement(-1.42626e-6, 5.567e-8)
('-1.426e-06', '0.056e-06')
>>> format_measurement(2.5, None)
('2.5', '–')
Parameters:
Return type:

tuple[str, str]

fitwise.plotting.plot_result(result, *, residuals=True, band='confidence', level=0.95, ax=None, show_params=False, n_points=500)[source]#

Plot data with error bars, the fitted curve and the residuals.

Parameters:
  • result (FitResult) – The fit to show.

  • residuals (bool) – Add a residual panel below the main plot (normalized by yerr if given). Ignored if ax is given.

  • band ({"confidence", "prediction"} or None) – Shade the confidence band (where the true curve lies) or the prediction band (where new measurements fall). Skipped if the covariance is not available.

  • level (float) – Coverage probability of the band.

  • ax (matplotlib.axes.Axes, optional) – Draw into existing axes instead of creating a new figure.

  • show_params (bool) – Put the fitted parameters into the legend.

  • n_points (int) – Number of points of the smooth fit curve.

Returns:

The figure and the list of axes (main plot first).

Return type:

figure, axes

fitwise.serialize.to_dict(result, *, include_data=False)[source]#

Describe a fit completely in JSON-compatible types.

Parameters:
  • result (FitResult) – The fit to serialize.

  • include_data (bool) – Also store x, y and yerr. Otherwise only their hash is stored.

Returns:

With keys schema_version, versions, model, data, options, method, converged, parameters, covariance, statistics and warnings.

Return type:

dict