Skip to content

Add a mapping-only mode to the labeled aligner - #692

Merged
adamant-pwn merged 1 commit into
masterfrom
feat/align-map-only
Oct 28, 2026
Merged

adamant-pwn merged 1 commit into
masterfrom
feat/align-map-only

Conversation

@adamant-pwn

@adamant-pwn adamant-pwn commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Stacked on #690. Review only the top commit, "Add a mapping-only mode to the labeled aligner"; this PR will be retargeted to master after #690 merges.

What

LabeledAligner::map_batch:

  • finds and label-filters seeds exactly as alignment does (build_seeders / filter_seeds, including min_exact_match), but does not extend them;
  • reports, per query, the labels whose seeds cover the most query characters on the better strand, plus the number of covered characters and the query range they span (on the forward query).

This supports read accept/reject decisions (e.g. adaptive sampling) that need the label, not a base-level alignment.

The CLI option metagraph align --align-map-only is opt-in and off by default. It requires -a and supports TSV output only, one line per query:

header  strand  labels  covered_chars  query_begin  query_end      (unmapped: header * * 0 * *)

Nothing changes in the default align path.

Test

LabeledAlignerTest.MapWithoutExtension, typed over all 7 graph/annotation pairs, covers:

  • full coverage by one label;
  • a query split between two labels, where the larger coverage wins;
  • an unmapped query.

7/7 pass locally (assertion-enabled build, filtered run only).

Numbers (benchmark harness bench/align-harness, mode map; 24 bacterial genomes, k = 31, CANONICAL, labeled, seed 19)

Single-threaded, per read, alignment vs. map_batch on the same reads. The aligned and negative-accepted fractions are identical by construction (same seed filter).

reads top-1 label correct (align / map) p50 ms (align / map) p99 ms (align / map)
Illumina-like 150 bp .922 / .921 3.0 / 1.9 5.8 / 2.7
ONT 400 bp, 3% .952 / .945 8.0 / 3.5 20.0 / 5.5
ONT 400 bp, 5% .679 / .675 6.0 / 2.6 17.4 / 4.7
ONT 1–5 kb, 3% .993 / .993 69.2 / 27.8 295 / 54.5
ONT 1–5 kb, 5% .827 / .830 55.5 / 21.3 563 / 47.4
ONT 1–5 kb, 10%, min_exact_match 0 1.000 / .997 66.2 / 13.3 397 / 29.5
ONT 400 bp, 10%, min_exact_match 0 .967 / .935 6.7 / 1.5 21.3 / 2.8

Multi-threaded CLI, -p 8, 945 long reads (median wall, peak RSS):

run wall peak RSS
align, seed 19 45.2 s 0.95 GB
align --align-map-only, seed 19 14.4 s 0.67 GB

No regression in align, this PR vs its base, interleaved repeats; output checksums are identical in all three configurations:

config base this PR
labeled, seed 19 (6 repeats) 45.2 s 46.0 s
labeled, full k 26.7 s 27.8 s
unlabeled, seed 19 38.0 s 39.6 s

The seed-19 spread is 42–49 s on both sides, plus one 68 s outlier on this PR's first repeat.

🤖 Generated with Claude Code


Summary by cubic

Adds a mapping-only mode to the labeled aligner that reports the best-supported label per query without extending seeds into alignments. This supports read accept/reject decisions (e.g., adaptive sampling) that need a label rather than a base-level alignment.

LabeledAligner::map_batch finds and label-filters seeds exactly as alignment does — including min_exact_match — but does not extend them. For each query it reports the labels whose seeds cover the most query characters on the better strand, the number of covered characters, and the query range they span on the forward query. The new metagraph align --align-map-only flag is off by default, requires -a, and rejects --json output; it emits one TSV line per query (header, strand, labels, covered_chars, query_begin, query_end), with unmapped queries reported as header * * 0 * *. The default align path is unchanged.

Tests

  • LabeledAlignerTest.MapWithoutExtension covers full coverage by one label, a split query where the larger coverage wins, and an unmapped query, across all graph/annotation pairs.

Benchmarks

  • On simulated Illumina and ONT reads, map_batch cuts per-read p50 latency by ~1.5–5× with top-1 label accuracy within ~1–3 percentage points of alignment.

Written for commit 2fc28b6. Summary will update on new commits.

View guided diff Turn on auto-fix

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread metagraph/src/cli/config/config.cpp Resolved
Comment thread metagraph/src/cli/align.cpp Resolved
Base automatically changed from fix/annotation-buffer-dangling-refs to master October 28, 2026 21:46
LabeledAligner::map_batch finds and label-filters seeds exactly as for
alignment (including min_exact_match), but does not extend them. For each
query it reports the labels whose seeds cover the most query characters on
the better strand, with the number of covered characters and the query
range they span. This is enough for accept/reject decisions on reads at a
fraction of the cost of alignment.

metagraph align --align-map-only (requires -a, TSV only) prints one line per
query: header, strand, labels, covered characters, query begin and end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adamant-pwn
adamant-pwn merged commit d70c25d into master Oct 28, 2026
25 checks passed
@adamant-pwn
adamant-pwn deleted the feat/align-map-only branch October 28, 2026 21:50
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