Skip to content

Follow-up to #167 — fixes a numerical issue in the merged implementation, addresses the review comment on readthedocs/sphinx math formatting, and adds a worked multi-clock example. - #169

Open
kimonito98 wants to merge 2 commits into
aewallin:masterfrom
kimonito98:fix/adev2psd-analytic-tail-docs

Conversation

@kimonito98

Copy link
Copy Markdown
Contributor

Modifications:

  • adev2psd_piecewise_approx: the kernel integral J(μ) was evaluated with a plain quad(0, ∞), which silently truncates its oscillatory tail as μ → −2. The tail is now integrated analytically; single-slope inputs recover their analytic coefficients to machine precision
  • Convergence guards are now strict open intervals (−2 < μ < 2 ADEV, −2 < μ < 4 HDEV), with error messages pointing to MDEV or drift removal / vartype='hdev'.
  • psd_piecewise_to_adev and noise.timmer_koenig_from_psd accept the two-endpoint f_nodes form returned for single-segment inputs.
  • Docstrings reworked with sphinx-compatible math

Additions

  • examples/multi-color-noise-demo.py: worked end-to-end example for three clocks — ADEV spec → piecewise PSD → exact round trip → Timmer–Koenig noise → OADEV, in one figure
  • tests/functional_tests/test_adev2psd.py: single-slope analytic checks

kimonito98 and others added 2 commits August 27, 2026 19:19
…ingle-segment f_nodes

The kernel integral J(mu) = int q(z) sin^4(z)/z^(3+mu) dz has a slowly
decaying oscillatory tail that naive quad() silently truncates as
mu -> -2: the returned value plateaus near 3.3 while the true integral
diverges as 3/(8(2+mu)), so the fitted PSD intensity h was wrong by up
to ~100x at mu = -1.99 with no warning (and the ADEV round trip still
closed, since both directions evaluate the same truncated integral).
The tail is now evaluated analytically: the divergent constant term of
the cosine expansion of q(z) sin^4(z) in closed form, the bounded
oscillatory terms via cosine-weighted QAWF quadrature. Single-slope
inputs now recover their analytic coefficients (white FM h0 = 2A^2,
flicker FM h = sigma^2/(2 ln 2)) to machine precision; mid-range
results are unchanged.

Also:
- convergence guards are now strict (-2 < mu < 2 ADEV, -2 < mu < 4
  HDEV; the boundaries themselves are divergent) and the error messages
  say what to do instead (MDEV for tau^-1 white/flicker-PM regions,
  drift removal or vartype='hdev' for tau-linear drift);
- psd_piecewise_to_adev() and noise.timmer_koenig_from_psd() accept the
  two-endpoint f_nodes form that adev2psd_piecewise_approx() returns
  for single-segment inputs;
- docstrings reworked with readthedocs/sphinx-compatible math
  (follow-up to the review comment on aewallin#167); docs build verified clean;
- regression tests, including the single-slope analytic checks that a
  round trip alone cannot provide.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the single-clock demo with a worked example (OCXO, AccuBeat
USO, Orolia RAFS): ADEV spec -> piecewise PSD -> exact round trip ->
Timmer-Koenig noise -> OADEV of the realisations, all overlaid in one
figure. The timestep (Nyquist above the highest PSD node) and duration
(f1 = 1/T below the lowest node, tau <~ T/10 usable) choices are
explained in the module docstring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 89.064% (+3.0%) from 86.055% — kimonito98:fix/adev2psd-analytic-tail-docs into aewallin:master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants