fix(profile): fade each peak to zero at its support edge - #18
Merged
Merged
Conversation
synthesizePattern summed each peak inside a hard ±20·FWHM window, and leBailExtract inside ±12·FWHM. The edge moves with every width and position parameter, so y jumped by the pseudo-Voigt Lorentzian tail whenever a data point crossed it, and a central difference divided that jump by 2h. On the Mn3Ga 30 K example (Example 3), the profW column at the engine's step gave JtJ = 218 (91 % from one point) instead of 8.7, and profW's esd came out 0.071 instead of 1.16. A C² quintic now fades each peak to exactly 0 over the outer 20 % of its support (supportTaper). The binary-search window is unchanged, and points in the flat 80 % are bit-identical. The fade removes 0.18 % of a Lorentzian's area. Gaussian and TOF tails are already below 1e-7 of the peak there, so those patterns move only at roundoff. Tests: FD width columns across an edge crossing (profile level vs the analytic dpV/dΓ; powder level for profW), Le Bail continuity in the width, and grid-order invariance. nextParameters' "converged" case now converges scale + background on noisy data first. Its seeds had left wR at 18 %, and the profile group's predicted gain there (0.0053) depended on the tails. Golden shifts (all GaNb4Se8 synchrotron, TCH pseudo-Voigt): Rietveld wR 10.3484 → 10.3475 %; staged wR 5.718 → 5.721 % (W 5.040 → 4.997); GSAS-II benchmark fixed-atom wR 18.31 → 18.33 % (single pV) and 23.44 → 23.33 % (TCH+FCJ). TOF goldens: roundoff only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
synthesizePatternsummed each peak inside a hard ±20·FWHM window, andleBailExtractinside ±12·FWHM. The edge moves with every width and position parameter. When a data point crossed it, y jumped by the pseudo-Voigt's Lorentzian tail. A central difference divided that jump by 2h, so the column spiked ∝ 1/h at one point.On the Mn₃Ga 30 K example (Example 3,
claude/example-magnetic), the profW column at the engine's step gave JᵀJ = 218, 91 % of it from one data point, instead of 8.7.Fix
supportTaperfades each peak to exactly 0 over the outer 20 % of its support with a C² quintic. It depends only on dist/half, so it moves smoothly with Γ and the centre.Example 3 replay (old → fixed)
The last row is a separate issue this PR does not fix. The final fit stops early on a flat U/V/W–moment valley, with or without the spike.
Tests
All four new tests fail on the old code.
peakWindow.test.tsputs a data point exactly on the strongest peak's edge. The profW JᵀJ must agree across h = 1e-3…1e-7·|W|. With the hard cutoff it was up to 7·10⁶× too large.profile.test.tsrequires the finite-difference width derivative to match the analytic ∂pV/∂Γ at every step. It also checks that a peak is exactly 0 at its edge, and that ascending, descending and unordered grids agree.leBail.test.tsrequires Le Bail to stay continuous in the width across an edge crossing.nextParameters.test.tschanged its "converged model promises no real wR gain" case. It now converges scale + background on noisy data first. Its starting values alone left wR at 18 %, and the profile group's predicted gain there (0.0053 vs a 0.005 limit) depended on the tails. Converged: wR 0.8 %, largest predicted gain 2e-5, limit tightened to 1e-3.Golden shifts
All are GaNb₄Se₈ synchrotron data with a TCH pseudo-Voigt. Every other golden moved only at roundoff.
Verification
vitest runwithdata/present: 1495 passed, 46 skipped (the same env-gated skips asmain).tsc -b --noEmitandeslint .are clean.🤖 Generated with Claude Code