Identify nucleotide states that distinguish a clade and substitutions that reconstruct to a selected phylogenetic branch — without conflating the two.
BRANCHSNV is a dependency-free Python command-line tool for interrogating one selected branch of a rooted bacterial phylogeny using a nucleotide NEXUS SNV matrix. It reports strict clade-exclusive nucleotide markers separately from substitutions reconstructed on the focal edge, retains uncertainty across all globally optimal equal-cost parsimony solutions, validates exact taxon and branch membership, and records deterministic SHA-256 provenance.
NEXUS alignment ─┐
Newick tree + rooting choice ├──> BRANCHSNV ───> results.tsv
exact focal-clade tip list ──┘ members.txt
report.json
What BRANCHSNV reports
| Mode | Question answered | Reporting rule |
|---|---|---|
fixed-exclusive |
Which nucleotide states are strict markers of this clade in the supplied dataset? | Every descendant has the same unambiguous base; every outside taxon is callable; no outside taxon has that base. |
parsimony |
Which substitutions reconstruct to the selected branch? | Parent and child states are evaluated across all globally optimal equal-cost Sankoff reconstructions. |
both |
Which sites meet either definition? | Reports the union and records the reason for each row. This is the default. |
The definitions are deliberately separate. A strict clade marker can have ambiguous placement on the incoming branch, while a reconstructed branch change can recur elsewhere and therefore not be clade-exclusive.
Installation
BRANCHSNV requires Python 3.10 or later.
Install the stable release from Bioconda:
conda create -n branchsnv branchsnv=0.1.0 \
--channel conda-forge \
--channel bioconda \
--strict-channel-priority
conda activate branchsnv
branchsnv --version
Alternatively, install from PyPI:
python -m pip install branchsnv==0.1.0
branchsnv --version
Or install directly from the tagged source release:
git clone https://github.com/RhysWhite/branchsnv.git
cd branchsnv
git checkout v0.1.0
python -m pip install .
branchsnv --version
For development installation and contribution guidance, see
CONTRIBUTING.md.
Quick start
The bundled example contains five taxa, six sites, and a focal branch containing
isolates A and B.
branchsnv find \
--alignment examples/simple/alignment.nex \
--tree examples/simple/tree.nwk \
--outgroup Outgroup \
--clade-tips examples/simple/clade_tips.txt \
--mode both \
--output results.tsv \
--members-output members.txt \
--report report.json
BRANCHSNV reports:
Selected b_daee1cd25194ae95 (2 descendants); reported 2 of 6 sites.
The full TSV contains the original site identifier, inferred parent and child states, all optimal focal-edge state pairs, call counts, parsimony score, and selection reason. The example reduces to:
| Site | Reconstructed change | Parsimony status | Fixed-exclusive | Reported because |
|---|---|---|---|---|
ref_1 |
G>A |
unambiguous_change |
yes | both |
ref_6 |
ambiguous | placement_ambiguous |
yes | fixed-exclusive |
Committed expected outputs are available in
examples/simple/expected/.
Running BRANCHSNV on your data
1. Prepare three inputs
You need:
- a nucleotide NEXUS matrix in conventional taxon-by-character or transposed character-by-taxon orientation;
- a Newick tree containing exactly the same taxon names; and
- the exact tip names descending from the branch of interest.
The NEXUS taxon order does not need to match the visual tip order in the tree. BRANCHSNV matches taxa by exact name.
Example focal-clade file:
isolate_A
isolate_B
isolate_C
2. Validate the alignment, tree, and root
For a single outgroup tip:
branchsnv validate \
--alignment alignment.nex \
--tree tree.nwk \
--outgroup Outgroup_isolate
For an outgroup containing several genomes:
branchsnv validate \
--alignment alignment.nex \
--tree tree.nwk \
--outgroup outgroup_1 outgroup_2 outgroup_3 outgroup_4
A one-name-per-line outgroup file can instead be supplied with
--outgroup-file outgroup_tips.txt.
3. Find branch-associated SNVs
branchsnv find \
--alignment alignment.nex \
--tree tree.nwk \
--outgroup-file outgroup_tips.txt \
--clade-tips clade_tips.txt \
--mode both \
--output branch_snvs.tsv \
--members-output branch_members.txt \
--report branchsnv_report.json
BRANCHSNV stops if the requested tips do not form exactly one rooted clade, if tree and alignment taxa differ, or if unsupported input is encountered.
Selecting a branch
| Method | Option | Best use | Important detail |
|---|---|---|---|
| Exact descendants | --clade-tips clade_tips.txt |
Publication and permanent analyses | Recommended. The file must equal the complete descendant set of one branch. |
| MRCA anchors | --mrca isolate_A isolate_B |
Exploration | The selected MRCA may contain additional descendants. Inspect members.txt. |
| Deterministic branch ID | --branch-id b_daee1cd25194ae95 |
Repeating an inspected selection | Generate IDs first with branchsnv inspect. Full IDs or unique prefixes are accepted. |
To list every branch and its deterministic identifier:
branchsnv inspect \
--tree tree.nwk \
--outgroup-file outgroup_tips.txt \
--output branches.tsv
A branch ID is derived from the SHA-256 hash of its sorted exact descendant-tip names. It is unaffected by sibling order, branch lengths, or Newick formatting outside taxon labels, but exact taxon-name content is significant. It intentionally changes when rooting or descendant membership changes.
See docs/branch-selection.md for details.
Rooting is explicit
Every command that interprets branches requires one of:
--outgroup TIP [TIP ...]
--outgroup-file outgroup_tips.txt
--accept-existing-root
BRANCHSNV never silently assumes that the encoded Newick root is biologically appropriate. Branch direction and reconstructed parent-to-child changes depend on the chosen root.
Output files
| File | Purpose |
|---|---|
results.tsv |
Reported sites, ancestral-state results, call counts, parsimony scores, and selection reasons. |
members.txt |
Sorted, one-name-per-line record of every descendant on the selected branch. |
report.json |
Deterministic provenance: versions, input dimensions, rooting and selection methods, parameters, counts, and SHA-256 checksums. |
The JSON report omits timestamps and absolute paths so that identical input
files and parameters produce identical output bytes in different working
directories. Its schema is documented in
schemas/branchsnv-report.schema.json.
Parsimony classifications
BRANCHSNV uses unordered equal-cost Sankoff parsimony over A, C, G, and
T, retaining the complete set of parent-child state pairs attainable on the
focal edge among globally optimal reconstructions.
| Status | Interpretation |
|---|---|
unambiguous_change |
One parent-child pair is possible and the states differ. |
change_state_ambiguous |
Every optimum changes on the edge, but the exact transition is not unique. |
placement_ambiguous |
Some optima change on the edge and others do not. |
no_change |
No optimum changes on the selected edge. |
By default, parsimony mode reports only unambiguous_change. Add
--include-ambiguous to include the two ambiguous categories.
Input scope
BRANCHSNV accepts one nucleotide DATA or CHARACTERS NEXUS block in
conventional taxon-by-character or transposed character-by-taxon orientation,
together with one Newick tree with unique exact tip names. It supports quoted
labels, comments, branch lengths, multifurcations, standard IUPAC ambiguity
codes, and declared missing and gap symbols.
It deliberately does not support interleaved matrices, multiple data blocks, indel reconstruction, structural variants, fuzzy taxon matching, or general-purpose NEXUS dialects. Unsupported content is rejected rather than guessed.
See docs/input-formats.md for the complete accepted
subset.
Interpretation and limitations
Every result is conditional on the supplied alignment, upstream filters, tree topology, root, selected descendants, and state model.
“Branch-associated” does not mean causal, adaptive, free from recombination, or unique under future sampling. BRANCHSNV also does not use branch lengths, unequal substitution rates, or nucleotide frequencies in ancestral reconstruction.
See docs/interpretation.md for reporting language and
interpretive cautions.
Validation and reproducibility
Production tests and publication validation are deliberately separated.
The production repository contains the unit, regression, determinism, packaging, and bundled-example checks used during development. The current test suite contains 80 tests and is run across Python 3.10–3.14, with additional macOS and Windows jobs in GitHub Actions.
The independent publication-validation repository is maintained separately at RhysWhite/branchsnv-validation. The stable v0.1.0 validation release is archived at https://doi.org/10.5281/zenodo.21919067. It preserves two version-pinned records:
- the historical publication snapshot for BRANCHSNV v0.1.0a1; and
- a separate stable-release validation record for BRANCHSNV v0.1.0 under
release_validation/v0.1.0/.
Both records support the same deterministic analytical headline results:
| Validation layer | Result |
|---|---|
| Independent exhaustive oracle | 128,881/128,881 exact comparisons across seven topology–edge settings |
| Deliberately faulted implementations | 10/10 fault classes detected across 280,216 fault–challenge comparisons |
| SNPPar comparison | 877/877 BRANCHSNV-unambiguous substitutions matched SNPPar; 66 additional SNPPar events were retained as placement-ambiguous |
| Published focal branches | 46/46 published SNVs reproduced across MRSA AK3, MRSA ST97, and E. coli ST131/OXA-48 |
| Complete-phylogeny empirical analysis | 31,644 informative comparisons across five phylogenies; 827 (2.61%) fell outside the fixed-exclusive/unambiguous-substitution intersection |
| Scalability | 39/39 measured end-to-end command-line runs completed |
The stable v0.1.0 run was generated against production commit
71b055bdbd8e00ee63afda136b88892aee0062f8 using validation-framework commit
cfb07389191540ca57c9e822b254c279ab903f36. It verified the production
source identity for all 13 Python source files, the validation-script identity,
the Experiments 01–06 pass criteria, and exact reproduction of the deterministic
analytical outputs in the canonical scientific snapshot. Experiment 04
performance measurements are retained as environment-specific observations.
At validation-repository commit 35a0794ddd9782355e1e06dd95bd10e1cde4c735,
the stable record is checksum-gated and checked in CI. The historical snapshot
remains separately verifiable with verify_publication_snapshot.py.
The older validation/ak3/ directory in this repository is
retained as a checksum-gated working-data regression recipe. It is not the
authoritative independent validation record.
See VALIDATION_REPORT.md and
docs/validation.md for details.
Documentation
Hosted documentation is available at branchsnv.readthedocs.io.
BRANCHSNV is indexed in the ELIXIR bio.tools registry as
biotools:branchsnv. The archived software
release is available from Zenodo,
and installable releases are available from
Bioconda and
PyPI.
| Topic | Document |
|---|---|
| Accepted NEXUS and Newick syntax | docs/input-formats.md |
| Exact descendants, MRCA, and branch IDs | docs/branch-selection.md |
| Fixed-exclusive and Sankoff algorithms | docs/algorithm.md |
| Scientific interpretation | docs/interpretation.md |
| Validation design | docs/validation.md |
| Shell and Snakemake integration | docs/workflow-integration.md |
Annotated source-code walkthrough (v0.1.0a1) |
docs/code-walkthrough/v0.1.0a1/README.md |
| Contributing | CONTRIBUTING.md |
| Release history | CHANGELOG.md |
Funding and affiliation
Development of BRANCHSNV was supported by Genomics Aotearoa and undertaken at Public Health and Forensic Science (PHF Science), Aotearoa New Zealand.
BRANCHSNV was developed and is maintained by Rhys White.
Citation
Citation metadata are provided in CITATION.cff.
BRANCHSNV v0.1.0 is permanently archived at https://doi.org/10.5281/zenodo.21919038. The corresponding publication-validation release is archived separately at https://doi.org/10.5281/zenodo.21919067.
Licence
BRANCHSNV is released under the MIT License.
Metadata
Release files for branchsnv 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| branchsnv-0.2.0.tar.gz | 132.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| branchsnv-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 164.4 kB
Release files / branchsnv-0.2.0.tar.gz
| Download URL | branchsnv-0.2.0.tar.gz |
|---|---|
| Size | 132.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2000ae11e634cc2f7dc76936aee7247205c2f4e4f2a5aff2e546ce0996175cbd
|
|
BLAKE2b-256 checksum How to use checksums |
224ff888cab2a440d404f6f68cc675fee7b6bccc86574163a9154ae499a411c5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / branchsnv-0.2.0-py3-none-any.whl
| Download URL | branchsnv-0.2.0-py3-none-any.whl |
|---|---|
| Size | 31.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c62b81bd6bea76f39a965d954f368ce8ff9018c721c371c9fa492b079bd43683
|
|
BLAKE2b-256 checksum How to use checksums |
9a55b3287ead01fc3ae8d7a62facf84b2f92bf3b78f0b2e50d1677e964fb96b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency log