kinextract.fit_joint_auto_xlam

kinextract.fit_joint_auto_xlam(st: FitState, n_interior_knots: int = 10, degree: int = 3, xlam_grid: tuple = (10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0), xlam_chi2_tolerance: float = 0.02, xlam_max_peaks: int = 1, xlam_peak_min_prominence: float = 0.1, recenter_v: bool = True, xlam_cont: float = 3.0, cont_diff_order: int = 2, maxiter: int = 50000, ftol: float = 1e-12, maxfun: int = 500000, use_jax: bool = True, fit_continuum: bool = True, xlam_criterion: str = 'discrepancy', xlam_discrepancy_nsigma: float = 0.3, w_bounds: tuple = (1e-05, 1.0))[source]

Automatically select the joint model’s LOSVD regularization strength.

Two criteria are supported (xlam_criterion):

"discrepancy" (the default – see below) and "chi2"/"roughness" (legacy, kept for backward compatibility).

"chi2"/"roughness"

Mirrors kinextract.fitting._auto_select_xlam’s chi2 criterion exactly (same selection rule, reusing its compute_losvd_roughness/ compute_losvd_n_peaks helpers directly): run a full fit at every grid point, then among the unimodal candidates (n_peaks <= xlam_max_peaks) pick the largest xlam whose reduced chi2 is within xlam_chi2_tolerance of the grid minimum – “use as much smoothing as possible without visibly hurting the fit.”

"discrepancy"

Delegates to kinextract.fitting._discrepancy_principle_search() (the same shared root-finder the shipped MAP path’s kinextract.fitting._auto_select_xlam_discrepancy() uses), replacing the grid scan with a 1-D root-find over log(xlam) targeting a known chi2 rise rather than a tolerance-from-minimum rule. Only xlam_grid’s min/max are used, as the search’s initial bracket. If xlam_grid has only one element (cfg.xlam_auto=False convention – see run_joint_fit()), falls back to the "chi2" path’s trivial single-candidate behavior instead of attempting a degenerate 1-D search.

Difference from the shipped selector, and why it matters: this always recenters the wing-taper’s v_center on kinextract.numerics.estimate_velocity_xcorr(st) before running the grid search (see recenter_v), rather than treating recentering as a separate, optional step layered on afterward. The “prefer the largest xlam that doesn’t hurt chi2” rule systematically walks toward high xlam whenever the data is clean enough not to visibly penalize it there – and high xlam is exactly the regime where the wing-taper’s fixed v_center=0 convention biases recovered V the most. Recentering first removes the asymmetry regardless of which xlam the search lands on.

Parameters:
  • st (FitState) – Fit state to optimize (not modified).

  • n_interior_knots

  • degree

  • xlam_cont

  • cont_diff_order

  • maxiter

  • ftol

:param : :param maxfun: Passed through to each grid-point fit_joint() call. :type maxfun: optional :param use_jax: Passed through to each grid-point fit_joint() call. :type use_jax: optional :param xlam_grid: Candidate xlam values, matching the shipped pipeline’s typical

grid span.

Parameters:
  • xlam_chi2_tolerance (float, optional) – Fractional chi2 tolerance for the “largest xlam within tolerance of the minimum” rule.

  • xlam_max_peaks (int, optional) – Maximum number of prominent LOSVD peaks (via compute_losvd_n_peaks) for a candidate to count as unimodal.

  • xlam_peak_min_prominence (float, optional) – Prominence threshold passed to compute_losvd_n_peaks.

  • recenter_v (bool, optional) – If True (default), recenter v_center on estimate_velocity_xcorr(st) once before the grid search.

  • fit_continuum (bool, optional) – Passed through to each fit_joint() call – see its docstring. Set False for pre-normalized input (no continuum to co-fit).

Returns:

  • result (scipy.optimize.OptimizeResult) – The final fit at the selected xlam (physical units).

  • design (ndarray) – Continuum B-spline design matrix for the final fit.

  • best_xlam (float) – The selected xlam value.

  • records (list of tuple) – (xlam, chi2_red, roughness, n_peaks) for every grid point, for diagnostics.