Skip to content

Add a generic sigproc binner unit#157

Merged
cboulay merged 4 commits into
devfrom
generalize-binner
Jun 26, 2026
Merged

Add a generic sigproc binner unit#157
cboulay merged 4 commits into
devfrom
generalize-binner

Conversation

@kylmcgr

@kylmcgr kylmcgr commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Add a generic sigproc binner that other units can use to bin in the same way. Different binning was causing the root of the mismatch SBP vs SPK pathway timestamps.

@kylmcgr kylmcgr requested a review from cboulay June 25, 2026 23:34
@kylmcgr kylmcgr self-assigned this Jun 25, 2026
cboulay added 3 commits June 26, 2026 00:15
Hoist the bin-boundary arithmetic out of BinnedAggregateTransformer into a
reusable, backend-agnostic BinSchedule (ezmsg.sigproc.util.binning) so that
every consumer that needs fixed-duration binning lands on the same grid by
sharing one schedule rather than re-deriving the formula.

- BinSchedule owns fs, samples-per-bin, output gain/offset, the global bin
  index, and the carried sample count; it touches no array data. Consumers
  layer their own data carry (raw samples here; a scalar partial-sum for an
  event counter) on top of the shared boundaries.
- BinnedAggregateTransformer now delegates all boundary/gain/offset math to
  BinSchedule.advance() and only slices+aggregates at the returned cut points.
- Integer mode now truncates (int) instead of round() so the sample-locked
  grid matches Window's int(window_dur*fs) for any rate, not just when the
  fractional part is < 0.5.
- test_bin_schedule.py pins fractional=True against a faithful port of
  EventRate's accumulator algorithm and fractional=False against Window's
  grid, across chunkings and at fs in {30000, 30012, 30030}. The 30030 case
  (spb=600.6) is where truncation vs rounding diverges.

This converts the previous "agreement with EventRate by construction, untested"
into shared code with a regression test, and sets up EventRate (ezmsg-event) to
delegate to the same primitive.
test_concat_along_ch drove its coroutine via asyncio.get_event_loop()
.run_until_complete(), which raises "no current event loop" on Python 3.10+
once any earlier test in the suite has called asyncio.run() (which clears the
loop policy). It passed in isolation but failed after, e.g.,
test_binned_aggregate's asyncio.run()-based test. Use asyncio.run(), which is
self-contained and order-independent.
Extract BinSchedule: shared bin-boundary primitive
@cboulay cboulay merged commit 7268046 into dev Jun 26, 2026
14 checks passed
@cboulay cboulay deleted the generalize-binner branch June 26, 2026 04:57
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