Cumulative root-to-node S1 mutation count - #1223
Open
trvrb wants to merge 2 commits into
Open
Conversation
S1_mutations uses augur distance --compare-to root, which counts S1 sites (spike aa 14-685) that currently differ from the root. As S1 sites now mutate recurrently, a second hit at an already-changed site adds nothing and a reversion subtracts, so the metric saturates and looks like it is slowing down. Add scripts/root_to_node_distance.py, which sums the per-branch S1 distance along the path from the root to each node (reusing augur's read_distance_map, get_distance_between_nodes and load_alignments), so every substitution event accrues -- a molecular-clock-like tally rather than a net difference. Gaps and ambiguities are excluded via a new ignored_characters key in S1.json so artifactual gaps in submitted sequences cannot inflate divergence. Wire this in as a new rule cumulative_distances producing the attribute S1_cumulative_mutations, alongside the existing vs-root S1_mutations, with a new "S1 mutations (cumulative)" coloring, so the two can be compared head-to-head before S1_mutations itself is switched over. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Member
Author
Now that the cumulative metric can be compared head-to-head against the old net-vs-root count, promote it to be the canonical S1_mutations coloring. Remove the vs-root `rule distances` (augur distance --compare-to root); the existing `rule cumulative_distances` now emits the attribute S1_mutations directly. Drop the temporary "S1 mutations (cumulative)" coloring and the stale rules.distances node-data wiring in export. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
trvrb
marked this pull request as ready for review
August 2, 2026 09:55
Member
Author
|
@huddlej --- Tagging you here mostly as FYI. This form of counting is going to be relevant for longer timescale analyses, and may be relevant to 12y H3N2 for example. I do think this eventually deserves to live as something like a |
Contributor
|
Thanks, @trvrb! I added an issue to Augur describing this new feature. |
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.

Via Claude
Motivation
The
S1_mutationscoloring counts spike S1 amino-acid changes (sites 14–685). Today it's computed withaugur distance --compare-to root, which compares each node's reconstructed sequence directly against the root — i.e. the number of S1 sites that currently differ from the root.Six-plus years in, S1 sites now mutate recurrently (like flu). Under a net-vs-root count, a second hit at an already-changed site adds nothing and a reversion subtracts, so the metric saturates and looks like S1 evolution is slowing — when the underlying substitution process isn't.
Why not just use
augur distance?augur distancecan't express a path sum. Every--compare-tomode (root/ancestor/pairwise) makes a single node-pair comparison and never walks/sums along branches —rootmode compares each node to the root sequence once. So no combination of its flags yields "total changes accumulated from root to node." Hence a small new script.I'd propose that we add some sort of
--cumulativeoption toaugur distanceas often want this sort of cumulative counting rather than direct comparison to reference.What this does
New
scripts/root_to_node_distance.pysums the per-branch S1 distance along every edge from the root to each node, so each substitution event accrues. It doesn't reimplement the distance logic; it reuses augur's own machinery per branch:augur.distance.read_distance_map— loaddefaults/distance_maps/S1.jsonaugur.distance.get_distance_between_nodes(parent, child, map)— per-branch distance, identical semantics to the current metricaugur.reconstruct_sequences.load_alignments— the existingaligned.gene.S_withInternalNodes.fastaalready holds reconstructed sequences for every node (internal + tip)It walks the tree in iterative preorder (safe for deep trees) accumulating
cumulative[child] = cumulative[parent] + branch_distance.Gaps and ambiguities are excluded via a new
"ignored_characters": ["-", "X", "N"]inS1.json, so artifactual gaps in submitted sequences can't inflate divergence.