Skip to content

Add log-binned histogram arithmetic (M3) - #3

Merged
remislp merged 1 commit into
masterfrom
histogram
Sep 1, 2026
Merged

Add log-binned histogram arithmetic (M3)#3
remislp merged 1 commit into
masterfrom
histogram

Conversation

@remislp

@remislp remislp commented Sep 1, 2026

Copy link
Copy Markdown
Member

M3 of the record-layer plan: the binning maths moves down, the figures stay
where they are.

The premise held, but not for the reason stated

The proposal called this "roughly thirty lines copied". Reading both
implementations side by side, the bin edges agree exactly — same start,
same ratio, same bins-per-decade rule — but the upper limit does not:

upper limit for max = 5.0 s for max = 30 s
EKDIST exp(ceil(log(max))) 7.389 54.598
HJCFIT 10 ** ceil(log10(max)) 10 100

The whole scheme is bins per decade. exp(ceil(log(x))) rounds up to the
next power of e, which is what you get from writing the decade round-up
with a natural log by mistake. It can land below the longest interval, and
numpy.histogram then drops those intervals with no warning.

Across 400 randomly drawn exponential samples the top edge fell below max(X)
in 119 of them. On glyr_experimental.scn it happens not to bite — open
and shut periods both clear it — which is presumably why it survived.

This implements the decade-aligned version and pins it with a regression test
over 200 random samples.

What is not shared

The two "scale factor" helpers looked like a third duplicate and are not.
EKDIST's __exponential_scale_factor normalises a fitted exponential mixture
against the data; HJCFIT's ideal_pdf_scale_factor renormalises an ideal pdf
onto the resolved intervals via the Q-matrix survival
φ_A exp(Q_AA t_res) u_A. Different quantities. Both stay where they are.

API

bins_per_decade, log_bin_edges, log_bin_histogram, staircase — counts,
edges and step coordinates. No matplotlib anywhere in the module.

Tests

29 new. 262 passing overall.

Next

Repointing EKDIST and HJCFIT at this is the other half of M3 and follows in
their own PRs. Worth flagging that EKDIST hard-depending on dcio needs dcio to
be installable — it is not on PyPI, so that dependency has to be a git URL
until it is.

🤖 Generated with Claude Code

M3 of the record-layer plan: the binning maths moves down, the figures stay
where they are. EKDIST draws for a person, HJCFIT draws inside a notebook and
SCALCS feeds a Qt canvas; those are legitimately different figures over the
same bins, and only the bins were ever duplicated.

Comparing the two existing copies turned up a defect rather than a duplicate.
The bin edges agree exactly -- same start, same ratio -- but the upper limit
does not. EKDIST computes it as exp(ceil(log(max))), which rounds up to the
next power of e, while the whole scheme is bins per decade. That limit can
land below the longest interval, and numpy.histogram then drops the tail of
the distribution silently: across 400 randomly drawn exponential samples it
happened in 119 of them. HJCFIT's 10 ** ceil(log10(max)) is right, and is
what this implements.

Also splits out what was tangled together. The two "scale factor" helpers are
not copies of each other: EKDIST's normalises a fitted exponential mixture,
HJCFIT's renormalises an ideal pdf onto resolved intervals from the Q matrix
survival. Different quantities, both staying put.

Exports bins_per_decade, log_bin_edges, log_bin_histogram and staircase --
counts, edges and step coordinates, no matplotlib anywhere.

29 new tests, including the truncation regression over 200 random samples.
262 passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@remislp
remislp merged commit a2cdb36 into master Sep 1, 2026
7 checks passed
@remislp
remislp deleted the histogram branch September 1, 2026 16:53
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