[us-commits] [ehb54/ultrascan3] a997ae: extrap_c0: fix unweighted GCV wiping out low q; re...
emre brookes
noreply at github.com
Mon Jul 20 07:14:36 MDT 2026
Branch: refs/heads/ehb54-issue-920
Home: https://github.com/ehb54/ultrascan3
Commit: a997aef8d438a5599240a6ef7cbefe853d9604ab
https://github.com/ehb54/ultrascan3/commit/a997aef8d438a5599240a6ef7cbefe853d9604ab
Author: ehb54 <brookes at uthscsa.edu>
Date: 2026-07-20 (Mon, 20 Jul 2026)
Changed paths:
M us_somo/develop/src/us_hydrodyn_saxs_iqq_extrap_c0.cpp
M us_somo/somo/doc/manual/somo/somo_saxs_extrap_c0.html
Log Message:
-----------
extrap_c0: fix unweighted GCV wiping out low q; report real skip causes
Reported: "non weighted seems to not work -- q-points could not be extrapolated
(fewer than 2 valid data points) and were skipped, regardless of merge etc."
Root cause. With unit weights the joint GCV objective on the reciprocal (c/I) axis is
dominated by the high-q points, whose values are orders of magnitude larger than the
low-q ones. GCV therefore selected lambda ~7.7e6 (effective slope dof 9.8, vs 259/19.7
for the same data weighted), over-smoothing alpha(q) into a near-constant until
Iex = (Q - B*alpha)/C went negative starting at the LOWEST q. Every such q was dropped,
so the Guinier region was destroyed and Rg blew up to 111 A. merge_ref cannot help
because it splices the reference at HIGH q while the damage is at low q.
This was previously recorded as "genuine algorithm behavior, validates why sd_weights
defaults ON". That was wrong: the same data unweighted with GCV OFF gives Rg 37.5 A with
1 skip, i.e. unweighted fitting is fine -- the regularization was the problem.
Fixes:
- (C, root cause) In the unweighted case, weight each q by 1/scale^2 where scale is that
q's mean |y|. The factor is CONSTANT WITHIN a q, so it leaves every per-q fit (slope
R/M and intercept Iex) algebraically unchanged -- it only rebalances the q against one
another in the joint penalized solve, restoring the conditioning the 1/sigma^2 path
gets for free. Equivalent to assuming constant relative error, the standard default
when error bars are absent or distrusted. The weighted path is untouched.
- (A) Report the ACTUAL skip cause(s) with per-cause counts. All four causes previously
reported as "fewer than 2 valid data points", which is wrong for three of them and hid
the real one (non-positive 1/I(0) intercept) -- that message is what sent the original
diagnosis down the wrong path.
- (B, safety net) If the GCV-smoothed intercept is still non-positive at some q, fall back
to the unregularized per-q intercept there instead of dropping the point, and tell the
user how many q that happened at (those points are not regularized).
Validated on the 7-curve alpha-syn set: recip_uw 506 skips / Rg 111 -> 0 skips / Rg 38.4
(in family with recip 38.1, additive 38.4, nogcv 38.3, unweighted-nogcv 37.5); same for
the merge variant. 8 of 9 regression baselines and all 5 SASBDB Table-1 outputs are
byte-identical, confirming the default weighted+GCV path is unchanged. Safety net (B) did
not need to fire in any test -- it is defensive only. Manual updated.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
To unsubscribe from these emails, change your notification settings at https://github.com/ehb54/ultrascan3/settings/notifications
More information about the us-commits
mailing list