Expose sine-fit controls and diagnostics in AOUT analyses#56
Merged
Arcadia-1 merged 3 commits intoJun 30, 2026
Merged
Conversation
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.
Closes #54.
Summary
This PR exposes the sine-fit controls and diagnostics needed by the AOUT residual-analysis APIs while preserving the existing defaults.
The change follows the implementation order proposed in #54:
fit_sine_4paramnow returns convergence diagnostics:convergedn_iterationsinitial_frequencylast_delta_freqfit_sine_4paramnow exposemax_iterationsandtolerancewithout changing their default values.return_fit=Trueunderresult[fit].decompose_harmonic_errorand decomposition wrappers now acceptfrequency,max_iterations, andtolerance, so known fundamentals can bypass auto-detection.Modification Logic
The core issue is not that the sine fit is mathematically wrong. The problem is that higher-level analysis functions previously hid the fit controls and fit quality from users. When the initial FFT estimate is poor, or when a harmonic is stronger than the actual fundamental, the residual-analysis layer can produce misleading residuals while giving the caller no way to inspect or correct the fit.
This PR keeps the existing fit behavior as the default:
max_iterationsremains1toleranceremains1e-9fitkeyThe new controls are opt-in. Users who already know the input frequency can pass it directly, or increase
max_iterationsfor difficult captures. Users who want fit-quality visibility can passreturn_fit=Trueand inspect convergence diagnostics.For residual APIs,
result[fit]intentionally includes scalar metadata only, not the full fitted waveform arrays, to avoid duplicating large payloads that are already represented by each analyzer's existing residual/error outputs.For harmonic decomposition,
frequency=Nonepreserves the old auto-detection path. Passingfrequency=known_freq, max_iterations=0gives a fixed-frequency decomposition, which is important when a strong HD2 component would otherwise be detected as the fundamental.Experimental Evidence
Near-DC false residual
Synthetic signal:
For
analyze_error_spectrum:For
decompose_harmonic_error:This shows that the higher-level APIs can now expose and correct the false residual structure by allowing additional fit iterations.
Strong-HD2 fundamental mis-detection
Synthetic signal:
Auto-detection locks onto the larger HD2 tone:
Passing the known fundamental frequency restores the intended harmonic decomposition.
Tests
Targeted tests:
Full unit suite on Windows:
The single failure is the pre-existing Windows
test_matlab_test_runner.py::test_explicit_non_executable_matlab_path_is_rejectedissue, unrelated to this PR. It is caused by Windows executable permission semantics for a temporary file namedmatlab.Compatibility
return_fit=Trueis requested.decompose_harmonics(freq=...)wrapper now actually honors its existingfreqparameter; when provided, it uses fixed-frequency decomposition.