scijit.optimize.curve_fit

scijit.optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False, check_finite=None, bounds=(-inf, inf), method=None, jac=None, *, full_output=False, nan_policy=None, args=array([0.]), tol=1.49012e-08, maxfev=0, ftol=None, xtol=None, gtol=0.0, epsfcn=None, factor=100.0, diag=None, col_deriv=False)

Nonlinear least-squares curve fit.

Fits a model f(x, p0, p1, ...) to data by nonlinear least squares and returns the best-fit parameters with a covariance estimate. Callable from Python and from inside @njit; both entries run the same compiled core.

Parameters:
fcallable

A MODEL f(x, p0, p1, ...) returning the predicted y, and the parameter count comes from its signature. A plain @njit model is reached from both entry points; a plain Python function is compiled here and so is reached from the Python entry.

xdata, ydataarray_like

Independent and dependent data, one dimension each. The residual count m is the longer of the two; an array holding a single value is repeated across the other, and any other disagreement raises.

p0array_like or None, optional

Initial parameters. None (default) is ones(n) with n read off the model’s signature. A p0 of any other length than the model takes raises TypeError.

sigmaarray_like or float or None, optional

Uncertainties on ydata. A scalar or a length-m array holds standard deviations and the residual becomes (model - ydata) / sigma; an (m, m) array is a covariance and the residual is transformed by its lower Cholesky factor. Under nan_policy='omit' the entries dropped from the data are dropped from sigma as well. See Notes.

absolute_sigmabool, optional

False (default) scales pcov by the reduced chi-square ssr / (m - n). True returns MINPACK’s covariance unscaled.

check_finitebool or None, optional

None (default) is True when nan_policy is None and False otherwise. True raises ValueError on a non-finite entry in either array.

bounds, method, jacoptional

Accepted only at their defaults. See Notes.

full_outputbool, keyword-only, optional

False (default) returns (popt, pcov). True returns (popt, pcov, infodict, mesg, ier). Compile-time constant inside @njit: it selects the return type.

nan_policy{None, ‘raise’, ‘omit’}, keyword-only, optional

Read only when the finiteness check did not run. 'raise' refuses a NaN, 'omit' drops the points where either array is NaN.

argsndarray, optional

BEYOND SCIPY. A flat buffer accepted for signature compatibility and not read: the model reads its data from xdata and ydata.

tolfloat, optional

BEYOND SCIPY. Sets both ftol and xtol when neither is given.

maxfev, ftol, xtol, gtol, epsfcn, factor, diag, col_derivoptional

Passed to the inner leastsq. ftol and xtol default to tol. maxfev at 0 means MINPACK’s 200 * (n + 1). col_deriv selects the layout of an analytic Jacobian, which this route does not pass, so it reaches nothing.

Returns:
poptndarray, shape (n,)

Best-fit parameters.

pcovndarray, shape (n, n)

Covariance estimate, MINPACK’s own, formed by inverting the QR factor lmdif produced and undoing the column pivoting. ALL-INF where the covariance is not estimable: MINPACK reached no solution, its triangular factor was singular, a NaN reached the covariance, or m <= n with absolute_sigma=False. That branch issues OptimizeWarning with the text “Covariance of the parameters could not be estimated”, through a numba.objmode block, so warnings.catch_warnings and -W see it from compiled and interpreted calls alike. All-zero on an exact fit.

infodictCurveFitInfo

With full_output. fvec, nfev, fjac, ipvt, qtf, in the order the fields are reached positionally.

mesgstr

With full_output. MINPACK’s termination message.

ierint

With full_output. 1..4 is success; anything else raises RuntimeError before returning.

Raises:
ValueError

If a non-finite entry survives the finiteness check, or a NaN survives nan_policy='raise'; if the model takes *params and p0 is None, names more than 15 parameters, or names a count the model body does not accept; if sigma has the wrong shape or is not positive definite; if method or jac is anything but None, or bounds anything but (-inf, inf); if f is not a plain @njit model; if xdata and ydata have lengths that do not broadcast; if p0 holds no parameters; or if ydata is empty.

TypeError

If the parameter count exceeds len(ydata), or p0 is not as long as the model’s parameter list.

IndexError

If nan_policy='omit' is given with a sigma that is not as long as the data.

RuntimeError

If the inner leastsq returns an ier outside 1..4.

Warns:
OptimizeWarning

pcov could not be estimated and is returned all-inf.

See also

scipy.optimize.curve_fit

The scipy routine this mirrors.

scijit.optimize.leastsq

The solver underneath.

scijit.optimize.lsq_linear

Bounded LINEAR least squares.

Notes

bounds, method and jac are accepted only at their defaults. bounds, and method='trf' or 'dogbox', select the nonlinear least_squares this package does not have. method='lm' and jac reach the leastsq path and are not wired through this front end.

sigma and nan_policy='omit' act on the residual: sigma folds the weights into it, and 'omit' shortens the data it reads. A sigma of shape (1, 1) is read as one standard deviation broadcast across the data, scipy’s own sigma.size == 1 rule.

The model is called once per iteration with the whole xdata array and must return one value per point. A model that returns a single value is broadcast across the data, as f(xdata, *p) - ydata in scipy. A multi-dimensional xdata is not accepted, and neither is a callable object rather than a function, because the parameter count is read from the model’s signature.

A model written as f(x, *params) is accepted, with p0 required. p0 omitted raises ValueError('Unable to determine number of fit parameters.'), and more than 15 parameters raises.

A p0 holding no parameters raises. scipy 1.18 reaches TypeError: object of type 'numpy.float64' has no len() on the same input.

A model written with numpy operations needs no change. Two spellings do not, and each has a one-token fix: math.sin(x) becomes np.sin(x), and a branch on x such as if x > 0.5 becomes np.where(x > 0.5, ...).

nfev is one higher than scipy’s on the same fit: one residual runs before MINPACK starts, and the count reports the callback’s own work rather than MINPACK’s counter.

infodict is a namedtuple rather than a dict, and the 5-tuple return is a tuple rather than an OptimizeResult.

full_output must be a compile-time literal inside @njit, and nan_policy must be a literal string.

tol sets both ftol and xtol when neither is given. args is accepted for signature compatibility and not read; scipy rejects the keyword with ValueError("'args' is not a supported keyword argument.").

Safe to call from a numba.prange loop: MINPACK holds the callback in a module variable carrying !$omp threadprivate, one slot per thread.

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html

Examples

Fit a * exp(-b * x) to noisy measurements. The model is scipy’s spelling, f(x, *params), and p0 defaults to ones(n) off its signature:

>>> import numpy as np
>>> from numba import njit
>>> from scijit.optimize import curve_fit
>>> @njit
... def model(x, a, b):
...     return a * np.exp(-b * x)
>>> x = np.linspace(0.0, 4.0, 20)
>>> rng = np.random.default_rng(0)
>>> y = model(x, 2.5, 0.4) + rng.normal(0.0, 0.05, x.size)   # noisy measurements
>>> @njit
... def run():
...     return curve_fit(model, x, y)
>>> popt, pcov = run()
>>> np.round(popt, 3)
array([2.521, 0.411])