kinextract.fit_joint_auto_xlam_sigl0

kinextract.fit_joint_auto_xlam_sigl0(st: FitState, n_interior_knots: int = 10, degree: int = 3, sigl0_init: float = 100.0, n_sigl0_iter: int = 3, sigl0_tol: float = 2.0, 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]

Self-consistent fixed-point refinement of the wing-taper’s sigl0.

This is the default top-level joint-fit entry point (see run_spectral_fit() with cfg.fit_continuum=True).

Rationale: the sigma-recovery bias is a monotonic function of sigl0 crossing zero almost exactly at sigl0 == true sigma. That means the map sigl0 -> recovered sigma(sigl0) has a fixed point very close to the true sigma, and iterating – fit once, read off the recovered sigma, use it as the next sigl0, refit – converges toward that fixed point regardless of how wrong the starting guess is. This is more robust than a cross-correlation-based sigma pre-estimate: on a real, many-template library, individual templates’ own autocorrelation widths can span a wide range, so no single “reference template” construction generalizes across a whole library. Each iteration is a full fit_joint_auto_xlam() call (its own xlam grid search + wing-taper recentering), so this costs n_sigl0_iter times as much as a single auto-xlam fit.

Convergence is robust to the initial guess: a synthetic validation sweep (sigl0_init from 20 to 500 km/s against a true sigma of 140) shows the default 3-iteration schedule brings every tested starting point to within ~0.3 km/s of each other, and real-MUSE-bin tests converge to a consistent sigma within 2-3 iterations regardless of starting guess, matching the shipped ALS pipeline’s own recovered value on the same data.

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

  • sigl0_init (float, optional) – Starting sigl0 guess for iteration 1. Default 100 km/s, matching the legacy Fortran pipeline’s own fixed default (every bin uses the same hardcoded initial sigma guess regardless of radius or true dispersion).

  • n_sigl0_iter (int, optional) – Number of fit-then-update rounds. Default 3 (two corrections after the initial guess). Reduce to 2 (or 1, to disable correction entirely) if runtime on a full batch matters more than the small extra convergence margin the third fit buys.

  • sigl0_tol (float, optional) – Stop early (reuse the current iteration’s result) if |sigl0 - recovered_sigma| <= sigl0_tol km/s, i.e. the fixed point has already been reached to within this tolerance.

  • xlam_grid

  • xlam_chi2_tolerance

  • xlam_max_peaks

  • xlam_peak_min_prominence

:param : :param recenter_v: :param xlam_cont: :param cont_diff_order: :param maxiter: :param ftol: :param maxfun: :param use_jax: :param : :param xlam_criterion: Passed through to each fit_joint_auto_xlam() call. :param xlam_discrepancy_nsigma: Passed through to each fit_joint_auto_xlam() call. :param fit_continuum: Passed through to each fit_joint_auto_xlam() call – see its

docstring. Set False for pre-normalized input (no continuum to co-fit); sigl0 fixed-point convergence still applies exactly the same way.

Returns:

  • result (scipy.optimize.OptimizeResult) – The best round’s fit (physical units) – see the divergence-guard note below, not necessarily the final round’s.

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

  • best_xlam (float) – The returned fit’s selected xlam.

  • sigl0_trace (list of float) – [sigl0_init, sigl0_after_iter_1, sigl0_after_iter_2, ...] – the sequence of sigl0 values used/produced, for diagnosing convergence.

Notes

Divergence guard. This iteration is not guaranteed to converge monotonically on every chi2(xlam) curve: on an unusually flat one (confirmed on a clean, oversimplified synthetic mock – an under-constrained problem for regularization selection in general, see examples/notebooks/01_basic_mock_fit.ipynb and kinextract.fitting._fit_map_sigl0_recenter(), the shipped-path analogue of this function), each round’s recovered sigma can land farther from that round’s sigl0 input than the previous round did – a positive feedback loop, not a fixed point. This function tracks the smallest |sigl0 - recovered_sigma| gap seen across all rounds and returns that round’s fit instead of the final round’s if the final round’s gap is worse.