[Fix] Fix behaviour for rank deficient fits. Add test

This commit is contained in:
Fabian Joswig 2026-02-19 07:34:05 +01:00
commit 18a70fad53
2 changed files with 25 additions and 2 deletions

View file

@ -567,7 +567,7 @@ def total_least_squares(x, y, func, silent=False, **kwargs):
Notes
-----
Based on the orthogonal distance regression module of scipy.
Based on the odrpack orthogonal distance regression library.
Returns
-------
@ -670,7 +670,17 @@ def total_least_squares(x, y, func, silent=False, **kwargs):
print('Residual variance:', output.residual_variance)
if not out.success:
raise Exception('The minimization procedure did not converge.')
# info % 5 gives the convergence status: 1=sum-of-sq, 2=param, 3=both
# If odrpack reports rank deficiency (e.g. vanishing chi-squared when
# n_obs == n_parms), convergence was still achieved allow with a warning.
if out.info % 5 in [1, 2, 3]:
warnings.warn(
"ODR fit is rank deficient. This may indicate a vanishing "
"chi-squared (n_obs == n_parms). Results may be unreliable.",
RuntimeWarning
)
else:
raise Exception('The minimization procedure did not converge.')
m = x_f.size

View file

@ -468,6 +468,19 @@ def test_total_least_squares():
assert((outc.fit_parameters[1] - betac[1]).is_zero())
def test_total_least_squares_vanishing_chisquare():
"""Test that a saturated fit (n_obs == n_parms) works without exception."""
def func(a, x):
return a[0] + a[1] * x
x = [pe.pseudo_Obs(1.0, 0.1, 'x0'), pe.pseudo_Obs(2.0, 0.1, 'x1')]
y = [pe.pseudo_Obs(1.0, 0.1, 'y0'), pe.pseudo_Obs(2.0, 0.1, 'y1')]
with pytest.warns(RuntimeWarning, match="rank deficient"):
out = pe.total_least_squares(x, y, func, silent=True)
assert len(out.fit_parameters) == 2
def test_odr_derivatives():
x = []
y = []