From 7bd395c5a81555d9cbdee61021ace3c35e17797f Mon Sep 17 00:00:00 2001 From: "Mitchell R. Vollger" Date: Sat, 29 Aug 2026 10:01:52 -0600 Subject: [PATCH 1/2] fix: skip FIRE scoring when tag coordinates run past the sequence Hard-clipped supplementary alignments can keep nuc/msp tag coordinates from the full-length read. Their MSP coordinates run past the clipped SEQ, and reverse-strand records wrap the flipped index below zero. Both made ft fire panic with an out-of-range slice index. ft fire now checks the raw molecular coordinates before it scores a record. A record that fails the check gets a warning and is written to the output unchanged. Fixes #136 --- src/subcommands/fire.rs | 6 ++++ src/utils/fire.rs | 32 +++++++++++++++++++ tests/data/ont_hardclip_supplementary.bam | Bin 0 -> 43744 bytes tests/regression/fire.rs | 37 ++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 tests/data/ont_hardclip_supplementary.bam diff --git a/src/subcommands/fire.rs b/src/subcommands/fire.rs index d33cc87d8..5c95e5059 100644 --- a/src/subcommands/fire.rs +++ b/src/subcommands/fire.rs @@ -15,6 +15,11 @@ pub fn add_fire_to_rec( model: &GBDT, precision_table: &MapPrecisionValues, ) { + // Skip (and pass through unchanged) records whose annotations cannot be + // scored; fire_coords_fit_seq logs the reason (#136). + if !fire_coords_fit_seq(rec) { + return; + } let fire_feats = FireFeats::new(rec, fire_opts); let mut precisions = fire_feats.predict_with_xgb(model, precision_table); // FIRE produces precisions in MSP-iteration (BAM) order. Convert to @@ -82,6 +87,7 @@ pub fn add_fire_to_bam(fire_opts: &mut FireOptions) -> Result<(), anyhow::Error> let chunk: Vec = chunk.collect(); let feats: Vec = chunk .par_iter() + .filter(|r| fire_coords_fit_seq(r)) .map(|r| FireFeats::new(r, fire_opts)) .collect(); feats.iter().for_each(|f| { diff --git a/src/utils/fire.rs b/src/utils/fire.rs index ba9b13401..cd37ce9bd 100644 --- a/src/utils/fire.rs +++ b/src/utils/fire.rs @@ -61,6 +61,38 @@ fn get_mid_point(start: i64, end: i64) -> i64 { (start + end) / 2 } +/// Check that the annotations FIRE reads (msp, m6a, cpg) all fit inside the +/// stored sequence, warning and returning false if they do not. +/// +/// Hard-clipped supplementary alignments can keep nuc/msp tag coordinates +/// from the full-length read, so positions run past the clipped SEQ and +/// scoring the record indexes out of bounds (#136). The check uses the raw +/// molecular-orientation coordinates: building a BAM-oriented view flips +/// coordinates through `read_length - end`, which itself overflows on these +/// records. +pub fn fire_coords_fit_seq(rec: &FiberseqData) -> bool { + use crate::utils::basemods::{CPG_TYPE, M6A_TYPE}; + use crate::utils::ma_io::MSP_TYPE; + let seq_len = rec.record.seq_len() as u64; + for type_name in [MSP_TYPE, M6A_TYPE, CPG_TYPE] { + let Some(t) = rec.annotations.get_type(type_name) else { + continue; + }; + for a in &t.annotations { + if a.start as u64 + a.length as u64 > seq_len { + log::warn!( + "skipping FIRE for {}: {} coordinates extend past the {} bp sequence (hard-clipped supplementary alignment?)", + String::from_utf8_lossy(rec.record.qname()), + type_name, + seq_len + ); + return false; + } + } + } + true +} + /// ``` /// use fibertools_rs::utils::fire::get_bins; /// let bins = get_bins(50, 5, 20, 200); diff --git a/tests/data/ont_hardclip_supplementary.bam b/tests/data/ont_hardclip_supplementary.bam new file mode 100644 index 0000000000000000000000000000000000000000..edee745d01ccff129be326db9f60381a5c781069 GIT binary patch literal 43744 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 g03VA81ONa4009360763o02=@U00000000000Q9JRbpQYW literal 0 HcmV?d00001 diff --git a/tests/regression/fire.rs b/tests/regression/fire.rs index f2c490f75..8ff6fa712 100644 --- a/tests/regression/fire.rs +++ b/tests/regression/fire.rs @@ -27,6 +27,43 @@ fn fire_on_legacy_input_strips_consumed_legacy_tags() { } } +// Hard-clipped supplementary alignments can keep nuc/msp tag coordinates +// from the full-length read, so positions run past the clipped SEQ (and wrap +// below zero when flipped on reverse-strand records). `ft fire` must skip +// scoring these records instead of panicking, and still write them to the +// output unchanged (#136). The fixture holds two scorable primary reads plus +// a forward and a reverse hard-clipped supplementary read from TEnCATS ONT +// data. +#[test] +fn fire_skips_records_whose_coords_exceed_the_sequence() { + let scored = NamedTempFile::with_suffix(".bam").unwrap(); + run(&[ + "fire", + "--ont", + fixture("ont_hardclip_supplementary.bam").to_str().unwrap(), + scored.path().to_str().unwrap(), + ]); + let mut reader = bam::Reader::from_path(scored.path()).unwrap(); + let mut n_scored = 0; + let mut n_skipped = 0; + for rec in reader.records() { + let rec = rec.unwrap(); + if rec.is_supplementary() { + assert!(rec.aux(b"Ma").is_err(), "unscorable record got a Ma tag"); + assert!( + rec.aux(b"as").is_ok(), + "skipped record lost its original tags" + ); + n_skipped += 1; + } else { + assert!(rec.aux(b"Ma").is_ok(), "scorable record missing Ma tag"); + n_scored += 1; + } + } + assert_eq!(n_scored, 2); + assert_eq!(n_skipped, 2); +} + fn extract_fdrs(out: &str) -> Vec { out.lines() .map(|l| l.split('\t').nth(9).unwrap().parse().unwrap()) From 061e9c9dd75363d73de96eaa887ac58c6bebbca1 Mon Sep 17 00:00:00 2001 From: "Mitchell R. Vollger" Date: Sat, 29 Aug 2026 10:01:52 -0600 Subject: [PATCH 2/2] ci: support patch releases from release/** branches CI now runs on PRs that target release/** branches. The release-plz workflow copy on this branch triggers on pushes to release/**, so a merged fix opens a patch release PR against the branch, the same flow main has. cargo-dist is dispatched on the released tag instead of main, so binaries build from the patched 0.13.x source. --- .github/workflows/CI.yml | 4 ++-- .github/workflows/release-plz.yml | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 28eddc52d..f33309d02 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [main, master, dev, development] + branches: [main, master, dev, development, "release/**"] pull_request: - branches: [main, master] + branches: [main, master, "release/**"] jobs: Formatting: diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 36775e20a..66d6b8999 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -7,9 +7,14 @@ name: release-plz # GitHub releases. The only cross-workflow hop — firing cargo-dist to build the # fibertools-rs binaries — uses workflow_dispatch, which the default # GITHUB_TOKEN is allowed to trigger, so no PAT is required. +# This copy lives on the release/v0.13 maintenance branch: it runs on pushes +# to that branch (push-triggered workflows use the pushed branch's file), so +# merging a fix opens the patch release PR and merging that PR publishes it, +# the same flow main has. on: push: - branches: [main] + branches: ["release/**"] + workflow_dispatch: permissions: contents: write @@ -71,7 +76,9 @@ jobs: tag=$(echo "$RELEASES" | jq -r '.[] | select(.package_name=="fibertools-rs") | .tag') if [ -n "$tag" ] && [ "$tag" != "null" ]; then echo "Dispatching cargo-dist for $tag" - gh workflow run release.yml --ref main -f tag="$tag" + # Dispatch on the tag itself (not main) so the binaries are + # built from the patched 0.13.x source, not main's 0.14 code. + gh workflow run release.yml --ref "$tag" -f tag="$tag" else echo "fibertools-rs not in this release; skipping cargo-dist" fi