Skip to content

Add ndoptimize.models.gaussian_binned, a Gaussian averaged over each bin. - #6

Merged
roytsmart merged 1 commit into
mainfrom
feature/gaussian-binned
Oct 19, 2026
Merged

roytsmart merged 1 commit into
mainfrom
feature/gaussian-binned

Conversation

@roytsmart

Copy link
Copy Markdown
Contributor

Adds ndoptimize.models.gaussian_binned, a Gaussian averaged over each bin:

$$f(x_0, x_1) = \frac{1}{x_1 - x_0} \int_{x_0}^{x_1} A \exp\left(-\frac{(x - \mu)^2}{2\sigma^2}\right) dx.$$

It has the same parameters as gaussian (amplitude, center and width), and its two inputs are the lower and upper edges of each bin, x[:, 0] and x[:, 1].

Why

Averaging matters when the bins are about as wide as the line, which is the usual case for a CTIS reconstruction. sun-data/ctis#23 integrates its line profile over each velocity bin for this reason. Averaging over bins of width Δ broadens the line by about Δ²/12 in variance, and a fit of gaussian at the bin centers takes that broadening as part of the line. For bins as wide as the line, the sampled fit comes out 4.2% too wide and 4% too low in amplitude, while gaussian_binned recovers the line exactly.

It's also the model that bin-edge inputs to na.ModelFitFunctionArray will feed (sun-data/named-arrays#271): when a fit axis of a function array holds bin edges, the model gets each bin's lower and upper edge.

Numerics

  • The average is a difference of two error functions. In the tails, where both are close to 1 or to -1, it's computed from their complements, erfc, so it stays accurate where the plain difference would cancel to zero. A bin 15σ from the center comes out within 1e-11 of numerical integration, at about 1e-47 of the peak.
  • A bin of zero width gives the Gaussian at that point, and its Jacobian.

Tests

  • The model against scipy.integrate.quad over bins in both far tails, on either side of the center, and across it, to a relative 1e-11, with its Jacobian against finite differences.
  • Zero-width and 1e-6-wide bins against gaussian.
  • A fit to bins as wide as the line recovers the truth to 1e-6, while a fit of gaussian at the bin centers comes out more than 2% too wide.

50 tests pass with and without JIT, with models.py 100% covered. ruff, black and pyright 1.1.411 are clean, and the docstring example (the Gaussian next to its bin averages) builds.

Follow-up

The README and documentation list the models in #5. Once both merge, that list should add the binned Gaussian. I left it out here to avoid a conflict.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PZRXiFhGzzrF87vsFg73B9

…h bin.

It has the same parameters as `gaussian`, the amplitude, center and
width, and takes the edges of each bin as its two inputs. Averaging
matters when the bins are about as wide as the line: a fit of `gaussian`
at the bin centers takes the broadening from the bins as part of the
width of the line, about 4% too wide for bins as wide as the line.

The average is the difference of two error functions. In the tails, where
both are close to 1 or to -1, it is computed from their complements, so
it stays accurate where the plain difference would cancel to zero. A bin
of zero width gives the Gaussian at that point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PZRXiFhGzzrF87vsFg73B9
@codecov

codecov Bot commented Oct 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.65%. Comparing base (61296fd) to head (ef3d9f9).

Additional details and impacted files
@@            Coverage Diff             @@
##             main       #6      +/-   ##
==========================================
+ Coverage   99.61%   99.65%   +0.03%     
==========================================
  Files           8        8              
  Lines         782      861      +79     
==========================================
+ Hits          779      858      +79     
  Misses          3        3              
Flag Coverage Δ
unittests 99.65% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@roytsmart
roytsmart merged commit b62d586 into main Oct 19, 2026
18 checks passed
@roytsmart
roytsmart deleted the feature/gaussian-binned branch October 19, 2026 21:15
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.

1 participant