Skip to content

feat(group): accept query-grouped unaligned input with --allow-unmapped - #620

Merged
nh13 merged 1 commit into
mainfrom
nh/feat-group-allow-unmapped-queryname
Jul 23, 2026
Merged

nh13 merged 1 commit into
mainfrom
nh/feat-group-allow-unmapped-queryname

Conversation

@nh13

@nh13 nh13 commented Jul 21, 2026 •

Copy link
Copy Markdown
Member

group required template-coordinate sort unconditionally. So a user with an unaligned BAM who passed --allow-unmapped — whose entire purpose, per the command's own log line, is "All unmapped reads will form a single position group per library/cell" — was still told:

Input BAM must be template-coordinate sorted ...
  fgumi sort -i input.bam -o sorted.bam --order template-coordinate

on data that has no coordinates. That blocked the unaligned-only workflow (ribosome display, for instance) with advice the user cannot act on.

What changed

Template-coordinate sort exists to make position adjacency match the grouping key. Under --allow-unmapped every unmapped record lands in one group whatever the order, so that guarantee buys nothing — and the requirement is dropped.

Query grouping is still required, for a different reason. Templates are assembled by comparing each record's name to the previous one (group_by_name_and_build), so without adjacency an R1/R2 pair splits into two partial templates. That is corruption rather than a policy choice, so it stays enforced — and its error points at --order queryname, since the template-coordinate remediation is useless for a file with no coordinates.

Whether the header declares @SQ is deliberately not part of the decision. An earlier revision gated on their absence; that would reject an all-unmapped BAM that kept its header through something like samtools view -f 4, for no benefit. Mapped reads in query-grouped input are simply not position-adjacent, so each mapped template forms its own family — that under-groups rather than merging unrelated molecules, and --allow-unmapped already warns loudly that it groups by UMI alone. A further warning names the case explicitly when the header declares references.

Note there is no fgbio precedent to follow here: fgbio has no --allow-unmapped at all, so this is fgumi-specific semantics.

What did not change

Without --allow-unmapped, template-coordinate sort is still required — including for extract-style SO:unsorted GO:query headers with no SS. That case is the regression test for a real earlier bug where such headers were silently mistaken for template-coordinate, and it keeps failing without the flag. Accepting it under the flag routes it to the unmapped-only grouping path deliberately, which is a different thing from mistaking it for a sorted file.

The pre-existing rejection test previously asserted rejection under both flag settings; it is now scoped to the no-flag contract, with the flag contract covered by the new test. Both are explicit rather than one being weakened.

Verification

End-to-end with the real binary, not just unit tests:

  • fgumi extract output (SO:unsorted GO:query, no @SQ) → 12/12 records out, 2 MI groups matching the 2 distinct UMIs
  • all-unmapped BAM that does declare @SQ → same result, plus the warning
  • same input without --allow-unmapped → still rejected

cargo ci-test (5536 tests), cargo ci-fmt, cargo ci-lint, RUSTDOCFLAGS="-D warnings" cargo ci-doc pass.

Summary by CodeRabbit

  • New Features
    • --allow-unmapped can now handle query-grouped inputs even when reads are not adjacent by template-coordinate sorting.
    • Updated error/remediation guidance to point users to the appropriate --order setting for each input type.
  • Bug Fixes
    • Maintains strict template-coordinate sorting behavior when --allow-unmapped is not enabled.
    • Adds clearer warnings when reference sequences are present but inputs aren’t template-coordinate sorted.
  • Tests
    • Expanded integration coverage for accepted/rejected query-grouped unaligned cases, including with/without reference sequences.
  • Style / Chores
    • Minor formatting of public re-exports.

@nh13
nh13 temporarily deployed to github-actions July 21, 2026 02:00 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 79acdb03-b2a3-4893-99d7-a4541bfd046d

📥 Commits

Reviewing files that changed from the base of the PR and between 1b1ac60 and d570e94.

📒 Files selected for processing (2)
  • src/lib/commands/group.rs
  • src/lib/sam/mod.rs

Walkthrough

GroupReadsByUmi now accepts query-grouped unmapped inputs when --allow-unmapped is enabled, while retaining template-coordinate validation by default. Diagnostics distinguish accepted inputs, reference-sequence warnings, and rejected sort configurations.

Changes

Group input sort validation

Layer / File(s) Summary
Sort classification and execution diagnostics
src/lib/commands/group.rs, src/lib/sam/mod.rs
Input headers are classified as template-coordinate sorted, query-grouped unmapped, or unusable. Query-grouped inputs are accepted with --allow-unmapped; rejection messages provide order-specific remediation. The SAM re-export list is reformatted without changing exports.
Regression fixtures and tests
src/lib/commands/group.rs
Helpers and parameterized tests cover unaligned headers with and without @SQ, classification priority, accepted configurations, rejected configurations, and remediation text.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GroupReadsByUmi
  participant InputHeader
  participant Diagnostics
  GroupReadsByUmi->>InputHeader: classify sort order and grouping tags
  alt template-coordinate sorted
    InputHeader-->>GroupReadsByUmi: accept input
  else query-grouped with --allow-unmapped
    InputHeader-->>GroupReadsByUmi: accept query-grouped input
    GroupReadsByUmi->>Diagnostics: log acceptance and warn when `@SQ` is present
  else unusable or unauthorized ordering
    GroupReadsByUmi->>Diagnostics: report order-specific remediation
  end
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: accepting query-grouped unaligned input when --allow-unmapped is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nh/feat-group-allow-unmapped-queryname

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.51%. Comparing base (f3b0c78) to head (d570e94).
⚠️ Report is 20 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #620      +/-   ##
==========================================
+ Coverage   93.42%   93.51%   +0.08%     
==========================================
  Files         175      175              
  Lines      104807   105772     +965     
==========================================
+ Hits        97919    98913     +994     
+ Misses       6888     6859      -29     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nh13
nh13 force-pushed the nh/feat-group-allow-unmapped-queryname branch from 7a714d2 to 1b1ac60 Compare July 21, 2026 02:40
@nh13
nh13 temporarily deployed to github-actions July 21, 2026 02:40 — with GitHub Actions Inactive
@nh13

nh13 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/commands/group.rs`:
- Around line 982-1012: Update the query_grouped_unmapped classification in the
command’s header-validation flow so it is true only when --allow-unmapped is
enabled and the input is query-grouped but not template-coordinate sorted.
Preserve the existing rejection checks, and ensure genuinely
template-coordinate-sorted headers—including those with `@SQ` records—follow the
“Input is template-coordinate sorted” branch and do not emit the query-grouped
warning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b3e35d5a-ddee-4f5f-bb9a-ab0862642740

📥 Commits

Reviewing files that changed from the base of the PR and between 3da9945 and 1b1ac60.

📒 Files selected for processing (2)
  • src/lib/commands/group.rs
  • src/lib/sam/mod.rs

Comment thread src/lib/commands/group.rs Outdated
`group` required template-coordinate sort unconditionally, so a user with an
unaligned BAM who passed `--allow-unmapped` -- whose entire purpose is to place
all unmapped reads in a single position group -- was still told to run
`fgumi sort --order template-coordinate` on data that has no coordinates. That
blocked the unaligned-only workflow (ribosome display, for example) with advice
that could not be followed.

Template-coordinate sort exists to make position adjacency match the grouping
key. Under `--allow-unmapped` every unmapped record lands in one group whatever
the order, so that guarantee buys nothing.

Query grouping is still required, for a different reason: templates are
assembled by comparing each record's name to the previous one, so without
adjacency an R1/R2 pair splits into two partial templates. That is corruption
rather than a policy choice, so it stays enforced -- and the error for that case
points at `--order queryname` rather than the template-coordinate remediation,
which would not help a file with no coordinates.

Whether the header declares reference sequences is deliberately not part of the
decision. An all-unmapped BAM keeps its `@SQ` lines after something like
`samtools view -f 4`, and gating on their absence would reject it for no
benefit. Mapped reads in query-grouped input are simply not position-adjacent,
so each mapped template forms its own family -- that under-groups rather than
merging unrelated molecules, and a warning names the case when the header
declares references.

Without `--allow-unmapped` nothing changes: template-coordinate sort is still
required, including for extract-style `SO:unsorted GO:query` headers with no
`SS`, which the existing regression test continues to pin.

The accept/reject decision is a three-way classification, not two overlapping
booleans, so it lives in `classify_input_ordering`. Deciding it as booleans hid
a bug: template-coordinate headers advertise `GO:query`, so they also satisfy
`is_query_grouped`, and under `--allow-unmapped` a correctly-sorted BAM was
reported as merely query-grouped -- warning that its mapped templates "will not
be position-grouped" when they are, and making the template-coordinate log line
unreachable. Classifying template-coordinate first fixes it, and a case table
pins which ordering each header resolves to rather than only accept-vs-reject.

Verified end-to-end: `extract` output groups correctly through the new path, an
all-unmapped BAM that declares `@SQ` does too, and input without the flag is
still rejected.
@nh13
nh13 force-pushed the nh/feat-group-allow-unmapped-queryname branch from 1b1ac60 to d570e94 Compare July 22, 2026 18:48
@nh13
nh13 temporarily deployed to github-actions July 22, 2026 18:48 — with GitHub Actions Inactive
@nh13

nh13 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13

nh13 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13
nh13 merged commit 75628d4 into main Jul 23, 2026
14 checks passed
@nh13
nh13 deleted the nh/feat-group-allow-unmapped-queryname branch July 23, 2026 01:53
@nh13 nh13 mentioned this pull request Jul 23, 2026

This branch was previously deployed

1 inactive deployment
github-actions — d570e94f Deployed Jul 22, 2026 by nh13 via coverage #2904
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