derivkit.adaptive.polyfit_utils module

Utilities for polynomial fitting and evaluation.

derivkit.adaptive.polyfit_utils.assess_polyfit_quality(u: ndarray, y: ndarray, coeffs: ndarray, deg: int, ridge: float = 0.0, factor: float = 1.0, order: int = 0) tuple[dict[str, float | dict[str, float]], list[str]]

Assess numerical quality of a power-basis polynomial fit.

Computes several diagnostics for a polynomial fit evaluated on scaled offsets u:

  • Relative RMS residual (rrms_rel)

  • Leave-one-out (LOO) relative RMSE via the ridge hat matrix (loo_rel)

  • Condition number of the Vandermonde design matrix (cond_vdm)

  • Relative change of the target derivative compared to a degree-1 refit (deriv_rel), when feasible

It also returns human-readable suggestions to improve a poor fit. The thresholds are heuristic and may be tuned for your application. The LOO estimate is derived from the ridge hat-matrix diagonal, which is a fast approximation and works well for spotting overfit/outliers.

Parameters:
  • u (ndarray) – Scaled offsets, shape (n,).

  • y (ndarray) – Function values at the sample points, shape (n, m).

  • coeffs (ndarray) – Power-basis coefficients of the fit with columns per component, shape (deg+1, m). Column k corresponds to the coefficient of u**k.

  • deg (int) – Polynomial degree used in the fit (>= 0).

  • ridge (float) – Ridge regularization used in the fit (>= 0).

  • factor (float) – Scaling factor such that original offsets t = u * factor. Used only when extracting derivatives in the refit comparison.

  • order (int) – Derivative order of interest (>= 0).

Returns:

A tuple (metrics, suggestions) where:

  • metrics is a dict with keys:
    • "rrms_rel" (float)

    • "loo_rel" (float)

    • "cond_vdm" (float)

    • "deriv_rel" (float)

    • "thresholds" (dict): contains the threshold values used for each metric (same keys as above)

  • suggestions is a list of textual recommendations to improve the fit.

Return type:

tuple[dict, list[str]]

Notes

Large values of any metric indicate potential instability. Consider widening the sampling window (spacing), modestly increasing the number of points, or adding light ridge regularization.

derivkit.adaptive.polyfit_utils.choose_degree(order: int, n_pts: int, extra: int = 5) int

Choose a polynomial degree given derivative order and sample size.

Selects min(order + extra, n_pts - 1) to avoid underdetermined fits while allowing some flexibility beyond the target derivative order.

Parameters:
  • order – Derivative order (>= 0).

  • n_pts – Number of available points (>= 1).

  • extra – Extra degrees beyond order (>= 0). Default is 5.

Returns:

Chosen polynomial degree.

Return type:

int

Raises:

ValueError – If order < 0, n_pts < 1, or extra < 0.

derivkit.adaptive.polyfit_utils.extract_derivative(coeffs: ndarray, order: int, scale: float) ndarray

Extract the derivative of given order from power-basis coefficients.

Parameters:
  • coeffs – array of shape (deg+1, n_comp) with power-basis coefficients

  • order – derivative order (>= 0)

  • scale – scaling factor used in offsets (s > 0)

Returns:

array of shape (n_comp,) with the estimated derivative values

Return type:

deriv

Raises:

ValueError – if order < 0 or scale <= 0 or C has invalid shape

derivkit.adaptive.polyfit_utils.fit_multi_power(u: ndarray, y: ndarray, deg: int, ridge: float = 0.0) tuple[ndarray, ndarray]

Perform a least-squares polynomial fit in the power basis for multiple components.

This is a vectorized version of fit_and_rel_rms_multi using the Vandermonde matrix.

Parameters:
  • u – 1D array of scaled independent variable values (n_pts,).

  • y – 2D array of dependent variable values (n_pts, n_comp).

  • deg – Degree of polynomial to fit (integer, >= 0).

  • ridge – Optional ridge regularization parameter (default 0.0).

Returns:

Array of shape (deg+1, n_comp) with power-basis coefficients. rrms: Array of shape (n_comp,) with relative RMS errors.

Return type:

C

Raises:
  • ValueError – If inputs have wrong shapes/lengths or degree is invalid.

  • TypeError – If deg is not an integer.

derivkit.adaptive.polyfit_utils.fit_with_headroom_and_maybe_minimize(u: ndarray, y: ndarray, *, order: int, mode: str, ridge: float, factor: float, deg_cap: int = 8) tuple[ndarray, ndarray, int]

Perform a polynomial fit with headroom and optionally prefer minimal degree.

Fits a polynomial of degree deg_hi = deg_req + headroom to the data and, if the lower-degree fit (deg_req) yields effectively identical derivatives, switches to the minimal degree for stability and exactness. The method ensures that exact polynomials or smooth functions yield consistent derivatives without overfitting.

Parameters:
  • u – Scaled independent variable values (offsets), shape (n_points,).

  • y – Function values evaluated at the grid points, shape (n_points, n_components).

  • order – Derivative order to compute (>= 1).

  • mode – Sampling mode — one of "x", "signed_log", or "sqrt". Determines whether additional pullback corrections are applied when comparing fits.

  • ridge – Ridge regularization parameter applied in the least-squares fit.

  • factor – Scaling factor relating physical offsets to scaled ones (t = u * factor).

  • deg_cap – Maximum allowed polynomial degree (default 8).

Returns:

A 3-tuple (coeffs, rrms, deg_used) where:
  • coeffs: Power-basis polynomial coefficients, shape (deg+1, n_components).

  • rrms: Relative RMS residuals per component, shape (n_components,).

  • deg_used: Polynomial degree actually adopted (either deg_req or deg_hi).

Return type:

Tuple[np.ndarray, np.ndarray, int]

Raises:

ValueError – If the fit fails due to invalid input dimensions or degree constraints.

Notes

  • deg_req equals 2 * order for "sqrt" mode, else order.

  • Headroom is set to +4 for second-order sqrt mode, otherwise +2.

  • The switch to minimal degree occurs only if both:
    1. the lower-degree fit has negligible residuals (rrms < 5e-15), and

    2. its derivatives match the higher-degree fit within absolute tolerance 1e-9.

derivkit.adaptive.polyfit_utils.pullback_derivative_from_fit(*, mode: str, order: int, coeffs: ndarray, factor: float, x0: float, sign_used: float | None) ndarray

Extract the derivative at x0 with mode-specific pullbacks.

Interprets the power-basis polynomial coefficients in the internal coordinate and converts the requested derivative to the physical x domain. In "x" mode, the derivative is read directly from the power basis. In transformed modes, an analytic pullback is applied: the signed-log chain rule or the boundary-centered square-root mapping. Note that in "sqrt" mode, the first derivative in x uses the internal 2nd coefficient, and the second derivative uses the internal 4th coefficient.

Parameters:
  • mode – Sampling/transform mode ("x", "signed_log", or "sqrt").

  • order – Derivative order to return (>= 1). For transformed modes, only orders 1 and 2 are supported.

  • coeffs – Power-basis coefficients with columns per component, shape (deg+1, n_components).

  • factor – Positive scaling factor such that physical offsets satisfy t = u * factor.

  • x0 – Physical expansion point where the derivative is evaluated.

  • sign_used – For "sqrt" mode, the branch sign (+1 or -1). Ignored for other modes.

Returns:

The requested derivative at x0 with shape (n_components,).

Return type:

np.ndarray

Raises:

NotImplementedError – If mode is "signed_log" or "sqrt" and order is not 1 or 2.

derivkit.adaptive.polyfit_utils.scale_offsets(t: ndarray) tuple[ndarray, float]

Rescale offsets to improve numerical stability.

Converts offsets t to u = t/s, where s = max(|t|) (or 1 if t is empty or all zeros). This mitigates instability in polynomial fitting and differentiation, where powers of t can become very large or very small.

Parameters:

t – 1D array of offsets (can be empty).

Returns:

Scaled offsets, same shape as t. s: Positive scaling factor.

Return type:

u

Raises:

ValueError – If t is not 1D.