Repository navigation
v2.8.1: fiberhmm-extract single-pass multi-type
⚠️ Reverse-strand MM/ML parsing bug — UPGRADE TO v2.9.0
Versions 2.6 – 2.8.2 had a parser bug that shifted m6A/m5C modification positions on reverse-aligned reads (~24 bp median), causing ns/nl/as/al/MA/AQ tags to be wrong on reverse reads. Forward reads unaffected. DAF with IUPAC (R/Y) encoding unaffected.
Upgrade: pip install --upgrade fiberhmm (v2.9.0+). See v2.9.0 release notes for details.
fiberhmm-extract ~5× speedup for the default `--all` case
Two changes to `fiberhmm-extract` that together give N× speedup for N extract types plus a correctness fix.
Single-pass multi-type extraction
The old default (`--all`) ran the region-parallel pool 5 separate times, one per extract type. Every pass iterated the full BAM, rebuilt the query→ref `aligned_pairs` dict per read, and paid a fresh ProcessPool startup cost. That's 5× BAM I/O and 5× Python tuple allocations for data that could be shared.
The new worker takes a list of requested extract types and handles all of them in one BAM traversal:
- BAM iteration shared across types
- query→ref mapping computed once per read, passed to each extractor
- One ProcessPool startup
Benchmarks on test BAMs:
| Test | Reads | Types with data | New time |
|---|---|---|---|
| DddB | 22,913 | footprint, msp, tf | 6.1s |
| Hia5 | 1,190 | footprint, msp, tf, m6a, m5c | 3.0s |
For production BAMs on NAS (where I/O dominates), this is the biggest win — you go from 5× BAM reads to 1× BAM reads.
Correctness: empty-ML guard in m6a/m5c extractors
`_extract_m6a` and `_extract_m5c` call `read.modified_bases`, which segfaults pysam on reads where the MM tag has base-type header entries but the ML array is empty. Same bug we guarded against in the apply engine in 2.6.6.
Symptom before fix: on Hia5 PacBio BAMs with any empty-ML reads, extract workers silently terminated ("A process in the process pool was terminated abruptly") and produced 0-read output across all extract types.
Fix: check `len(read.get_tag('ML')) == 0` before calling `modified_bases`. O(1) on `array.array`, not materializing a PyInt list.
API compatibility
`extract_tags_parallel` signature extended: `output_bed` → `output_beds` (dict) and `extract_type` → `extract_types` (list). Old single-string calls still work for back-compat.
Install
```bash
pip install --upgrade fiberhmm
```
🤖 Generated with Claude Code