Skip to content

fix: off-by-one in bigWig interval start collapsed wide annot tracks (#233)#234

Merged
d-laub merged 5 commits into
mainfrom
fix/annot-bigwig-offbyone-233
Jun 19, 2026
Merged

fix: off-by-one in bigWig interval start collapsed wide annot tracks (#233)#234
d-laub merged 5 commits into
mainfrom
fix/annot-bigwig-offbyone-233

Conversation

@d-laub

@d-laub d-laub commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #233. The Rust bigWig interval reader stored interval start - 1 instead of start. Since bigtools' get_interval already clips intervals to the query range, the -1 was a pure off-by-one. For intervals wider than the query region (e.g. binned/annotation bigWigs), the numba kernel intervals_to_tracks then computed a negative relative start and wrote an empty/truncated slice — collapsing wide intervals to value/span_length. Fine-grained tracks saw a one-base dilution. Also fixes a latent u32 underflow for contig-start (start = 0) intervals.

The fix is a single token in src/bigwig.rs: MaybeUninit::new(start - 1)MaybeUninit::new(start). The same reader backs both per-sample tracks and annot_tracks, so both paths are corrected.

Changes

  • src/bigwig.rs — store true interval start (the fix).
  • tests/integration/tracks/test_annot_tracks.py — new fail-first regression test test_annot_bigwig_wide_intervals_full_width: builds 1 kb-binned intervals wider than the query regions, reads back the annot track, and asserts full-width fill (count_nonzero == e - s) plus value correctness against an independent pyBigWig.values() oracle. Failed 5-vs-350 on the buggy reader; passes now.
  • tests/test_bigwig.rs — corrected two Rust unit-test expectations that had asserted the buggy start-1 coordinates ([0,5]→[1,5], [99,105]→[100,105]; the true clipped coordinates).
  • tests/dataset/_snapshots/ — regenerated exactly the 4 track-dependent characterization snapshots (tracks_ragged, tracks_fixed, haps_tracks_fixed, haps_tracks_ragged); the change is a one-base edge correction. All seq-only snapshots unchanged.

Scope / constraints

  • No public API signature/mode/default changes.
  • No kernel change (_dataset/_intervals.py untouched) — minimal, parity-preserving.
  • No SKILL.md change required (documents dataset-level reading, not the internal per-base coordinate).

Verification

  • Full Python tree: 764 passed, 25 skipped, 4 xfailed.
  • cargo test: 4/4 pass.
  • ruff check + ruff format + typecheck: clean.

🤖 Generated with Claude Code

d-laub and others added 5 commits June 19, 2026 01:28
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…233)

bigtools get_interval already clips to the query range; storing start-1
shifted every interval one base 5', which made intervals_to_tracks compute
a negative relative start and write an empty slice for wide intervals
(value/span_length collapse) and a one-base dilution for fine tracks. Also
fixes a latent u32 underflow for contig-start intervals.

Two Rust unit tests in tests/test_bigwig.rs were asserting the buggy
start-1 behavior; corrected to assert the right start coordinates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@d-laub d-laub merged commit cfa4fae into main Jun 19, 2026
8 checks passed
@d-laub d-laub deleted the fix/annot-bigwig-offbyone-233 branch June 19, 2026 16:13
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.

annot bigWig readback collapses wide intervals to value/span_length (realign_tracks=False)

1 participant