Repository navigation
Add Harun's redone aligner as opt-in engine with pymetagraph bindings - #672
Closed
adamant-pwn wants to merge 320 commits into
Closed
adamant-pwn wants to merge 320 commits into
adamant-pwn wants to merge 320 commits into
Conversation
The redone aligner's annotation buffer repeated the node-to-row mapping that AnnotationKeyMapper now provides. Use the mapper, and give it the SSHash shortcut through DBGSSHash::get_base_node, which this branch adds. The mapping is unchanged for basic, canonical, wrapped-primary and SSHash graphs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build_graph_batch returns primary graphs already wrapped in CanonicalDBG, so test the wrapper it returns, and the primary graph inside it for the rejection case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Building a primary graph for the protein alphabet crashes, as other canonical-graph tests already account for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep the swap_dir build directory and take master's v6 build option. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adamant-pwn
added a commit
that referenced
this pull request
Oct 28, 2026
* Map oriented nodes to annotation rows in one place Add AnnotationKeyMapper, which returns the node whose annotation row an oriented node uses: the node itself in basic graphs, the base node of a CanonicalDBG, and the canonical k-mer's node in canonical graphs. The aligner's annotation buffer now uses it instead of its own mapping. Unwrapped primary graphs are rejected, as the buffer already assumed. Taken from the annotation-supported traversal integration (#670), where the traversal and both aligners share it, without its SSHash fast path, which needs DBGSSHash::get_base_node from #672. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test primary graphs as the test helper builds them build_graph_batch returns primary graphs already wrapped in CanonicalDBG, so test the wrapper it returns, and the primary graph inside it for the rejection case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test primary graphs only for DNA Building a primary graph for the protein alphabet crashes, as other canonical-graph tests already account for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # metagraph/src/graph/annotation_key_mapper.cpp # metagraph/src/graph/annotation_key_mapper.hpp
Query::generate_rc reverse-complemented the member rc_ before it was constructed instead of the local copy. It only worked because the compiler elided the copy into rc_. The extender overload of align_query dropped connect_anchors_in_chain, so connect_anchors=false had no effect when chains were extended. Now that it reaches the extender, chains whose anchors were not connected keep placeholder nodes between anchors, which extension cannot start from; report such chains unextended instead of crashing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An exception from one read inside a pool task failed the whole batch from the first future, while the remaining tasks still wrote into the result vector. Catch it per read, log it and report the read as unmapped. Also correct the docs: neither `metagraph align` nor the server's /align endpoint uses the alignment_redone engine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch moved graph_index_to_sshash into DBGSSHash; the duplicate check from #682 still called the free function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a succinct graph with A = TTACGAAA and B = ACGTTGCA, k = 5 and minimum seed length 3, the redone engine labels ACGT and CGTTG as B and TACGA as A, in basic and canonical mode. The existing aligner finds no alignment for ACGT on the basic graph, as its only suffix match is the dummy source k-mer $ACGT, and for CGTTG also reports TTG as an alignment to A that spells ACG. Its test is disabled until that is fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sub-k seeding on a CanonicalDBG read nodes[i] for every seed start, while nodes holds one entry per full k-mer, so starts in the last k - min_seed positions and queries shorter than k read past the end. Treat those positions as unmatched, as the forward check above already does. Correct the sub-k label tests. The existing aligner's partial ACG match for CGTTG is on the reverse strand and A does contain ACG, so its labels are right; its only defect here is the missed ACGT on basic graphs. The redone engine misses TGCA, which ends B, on basic graphs, as sub-k seeds are only extended forward there; that case is a disabled test. Both tests also cover primary graphs, where the out-of-bounds read occurred. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- About 175 lines of commented-out code (debug output and abandoned variants) and two unreachable blocks after an unconditional return in the seeder, including an SSHash gap-scoring copy. - Unused members: chains_per_char, Cigar::extend_clipping and get_num_ref, LabeledSeeder::get_buffer, and Extender::extend's no_bwd/no_fwd parameters, which no caller set. - Commented-out tests: five copies of existing-aligner tests that use options this engine does not have (min_cell_score, the seed complexity filter, forward_and_reverse_complement) are deleted; they still run in test_aligner.cpp. align_long_gap_after_seed now runs and passes. align_low_similarity4 and its primary variant run for minutes, as the engine has no work budget, so they are skipped with that reason. Two commented-out variants are dropped: one expected an alignment that does not cover the query, and with seeds shorter than k the engine does not recover align_insert_long_offset's long insertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
The existing-aligner test now requires the full-length alignment to spell the query on either strand, not just to have its length. The redone test no longer requires ACGC to have no alignment: a partial alignment of ACG is legitimate, so any alignment must instead spell part of its label's sequence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The redone copy of spell_path matched align::spell_path with offset 0. Its documentation moves to the shared declaration. The std::hash specialisations for Match, Anchor and Alignment had no users. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
get_sequence_ids was a pure virtual on SequenceGraph for one caller that only uses DBGSSHash, and always returned a single id. It becomes the non-virtual DBGSSHash::get_sequence_id, and seq_index goes. The DBGSSHash::max_index override equalled num_nodes() in both modes a DBGSSHash can have, so it is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The --align-no-connect-anchors and --align-no-extend-chains flags only carried two binding keyword arguments through Config; no command used them. The binding now reads those keywords directly, and Config matches master again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
All reported issues were addressed across 17 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
A stretch of npos nodes does not throw: its characters come from overlapping neighbouring nodes, or are '$' where none covers them. Only an invalid edge throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
max_nodes_per_seq_char now bounds the wavefront search, as in the existing aligner: once max_nodes_per_seq_char times the query length nodes were explored, the search stops at the first entry behind the furthest query position reached, and the best alignment found so far is backtracked. A gap fill stopped this way no longer throws; its chain yields no alignment. align_low_similarity4 and its primary variant run again, port the existing aligner's checks, and finish in under a second. max_num_seeds_per_locus now drops all seeds shorter than k at a query position that has more than that many, as in the existing aligner. The binding no longer accepts max_alternative_alignments, which the engine never used, since it reports only the best alignment. The binding takes the CLI defaults (budget 5, 1000 seeds per locus). On the 350-read binding comparison (k = 31, seeds of 19), the seed cap changes nothing. With a budget of 5 or 10, 2 reads end 7-12 characters earlier, with the same labels; with 20 or more, the output is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Entries that extend the furthest query position by a deletion stay at that position, so the budget never stopped them. Once over budget, only entries that reach further into the query, or reach the front at the cost of the first entry there, continue. The binding comparison output is unchanged at budgets of 5 and 10. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The reverse-complement pass of sub-k seeding on a CanonicalDBG kept traversing mismatching branches and exact ones past length k. Neither yields an anchor there, and the latter trips the length assertion on primary graphs. It now only follows exact matches shorter than k. - Extension asserted that every backtracking start scores at most the best explored score. Entries the node budget leaves unexplored can score higher, so they are skipped instead. - align_low_similarity4 sets the minimum seed length to k, as the existing aligner's version does. The binding comparison output is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adamant-pwn
marked this pull request as draft
October 28, 2026 18:23
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add Harun's redone alignment engine (
graph/alignment_redone) as opt-in code, together with thepymetagraphPython binding that adaptive-sampling experiments use.metagraph align, the server andquery --alignkeep using the existing aligner, so default behaviour does not change.This replaces the previous contents of this branch. The branch now merges Harun's last
align_refactorcommit (2d1734717, Nov 2025) into current master, plus Sayan'sLabeledSeeder::get_anchorsfix. Sayan's experiments ran on exactly this engine. The October 2026 changes are preserved oncodex/align_refactor-oct2026and can come back one at a time where they are worth keeping.Changes relative to Harun's commit:
--separate-headerleft out. That annotation feature is ported separately onfeature/separate-header.initialize_redone_aligner_configserves the new engine.The Python extension builds only with
-DBUILD_PYTHON_BINDINGS=ON. That option compiles position-independent static libraries, uses shared Boost and drops jemalloc. The default static build is unchanged.Local checks (GCC 16, Release):
sg/readfish-bindingson the same k=31 graph, annotation and 350 simulated reads, per-read results are byte-identical in five of the six binding modes (align, query, align without annotation, without extension, full-k seeds).connect_anchors=Falsenow differs by design: before the fix below it was ignored when chains were extended. 278/350 rows are identical and 342/350 have the same label; the differing rows report shorter spans.Fixes from a review of this PR (all also present in Harun's commit):
connect_anchors=Falsewas ignored with extension.align_querynow passes it on. Chains whose anchors are not connected keep placeholder nodes between anchors; the extender reports those chains unextended instead of crashing on them.Query::generate_rcreverse-complemented the not-yet-constructed member instead of the local copy. It worked only because the compiler constructs the result in place; the tests now cover reverse-complement queries on BASIC graphs.query_batch: a read that throws (for example "Failed to connect anchors") is now logged and reported as unmapped instead of failing the batch while other tasks still write into it.metagraph alignor the server's/alignuse this engine.Known limitations:
exit(), which ends the Python process instead of raising.max_alternative_alignmentsandmax_num_nodes_per_seq_charwithout effect.Not yet tested: integration tests, Sayan's real data, and installing the binding with
pip.AnnotationKeyMappercame from #683, now merged into master. The new engine maps its annotation rows through it, and this PR only adds the mapper's SSHash shortcut (DBGSSHash::get_base_node).🤖 Generated with Claude Code