Skip to content

Commit 6288d81

Browse files
committed
docs: substantive CRG C annotation (EXPLAINME.adoc)
1 parent c758486 commit 6288d81

1 file changed

Lines changed: 138 additions & 22 deletions

File tree

EXPLAINME.adoc

Lines changed: 138 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,158 @@
11
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// Copyright (c) 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
23
= Cladistics.jl — Show Me The Receipts
34
:toc:
5+
:toclevels: 3
46
:icons: font
57

6-
The README makes claims. This file backs them up.
8+
The README makes claims. This file backs them up with specific code locations,
9+
honest caveats, and enough detail for an external reviewer to orient themselves.
710

8-
[quote, README]
9-
____
10-
See the link:README.adoc[README] for details.
11-
____
11+
== README Claims — Verified
1212

13-
== Technology Choices
13+
=== Claim 1: "Multiple distance metrics including Jukes-Cantor correction for multiple substitutions"
1414

15-
[cols="1,2"]
16-
|===
17-
| Technology | Learn More
15+
*True.* `src/Cladistics.jl` exports `distance_matrix/2` with a `method` keyword
16+
accepting `:hamming`, `:p_distance`, `:jc69` (Jukes-Cantor 1969), and `:k2p`
17+
(Kimura 2-parameter). The test suite verifies that the JC69 corrected distance
18+
is strictly greater than p-distance for sequences that differ, confirming the
19+
saturation correction is operative. Symmetry and zero-diagonal invariants are
20+
tested for all methods.
1821

19-
| **Zig** | https://ziglang.org
20-
| **Julia** | https://julialang.org
21-
| **Idris2 ABI** | https://www.idris-lang.org
22-
|===
22+
*Caveat:* The package is at 75% completion (TOPOLOGY.md). Maximum likelihood
23+
distance methods (e.g., GTR model) and amino acid alphabet support are not yet
24+
implemented.
25+
26+
=== Claim 2: "Bootstrap support — statistical confidence in tree topology with 1000+ replicates"
27+
28+
*True.* `bootstrap_support/2` takes a sequence matrix and `replicates` count,
29+
resamples alignment columns with replacement, reconstructs a tree per replicate,
30+
and returns proportional support values for each bipartition. The default
31+
`replicates=1000` is confirmed in the docstring and Quick Start.
32+
33+
*Caveat:* Bootstrap resampling is CPU-bound; at 1000 replicates over large
34+
alignments this is slow. The AcceleratorGate GPU hooks in `backends/abstract.jl`
35+
exist but are not yet operative for this function.
36+
37+
=== Claim 3: "Neighbor-Joining does not assume a molecular clock"
38+
39+
*True.* `neighbor_joining/1` accepts a raw distance matrix (output of
40+
`distance_matrix`) and returns a `PhylogeneticTree` with unequal branch lengths
41+
computed by the NJ algorithm. The UPGMA implementation assumes rate constancy;
42+
the test suite validates that NJ and UPGMA produce different topologies for the
43+
same input when rates are heterogeneous.
44+
45+
== How It Works
46+
47+
The package is centred on three data types: `TreeNode` (a mutable struct with
48+
`name`, `children`, `branch_length`, `support`, and `parent` fields),
49+
`PhylogeneticTree` (wrapper with a root `TreeNode`), and `DTCode` for
50+
Dowker-Thistlethwaite representations used in tree comparison.
51+
52+
The analysis pipeline follows:
53+
54+
. Build a distance matrix from raw sequence strings via `distance_matrix`.
55+
. Construct a tree using `upgma`, `neighbor_joining`, or `maximum_parsimony`.
56+
. Optionally assess reliability with `bootstrap_support`.
57+
. Export to Newick format via `tree_to_newick` or parse an existing Newick
58+
string with `parse_newick`.
59+
. Identify well-supported monophyletic groups with `identify_clades`.
60+
61+
`Graphs.jl` provides the underlying adjacency structure. `Clustering.jl` is
62+
used internally for UPGMA's agglomerative linkage step. `Distances.jl` provides
63+
validated distance functions as a computational substrate.
64+
65+
== Honest Caveats
66+
67+
* The package is at 75% completion. Bayesian phylogenetics (MrBayes-style MCMC)
68+
and maximum-likelihood tree search are in the roadmap but not implemented.
69+
* `character_state_matrix` and `parsimony_informative_sites` are implemented,
70+
but the full Fitch parsimony algorithm for tree scoring is only partially
71+
complete.
72+
* No I/O support for NEXUS or PHYLIP formats; only Newick is supported.
73+
* The AcceleratorGate GPU extensions (`src/backends/abstract.jl`,
74+
weak-deps CUDA/Metal/AMDGPU) are scaffolded but not operative.
2375

2476
== Dogfooded Across The Account
2577

26-
Uses the hyperpolymath ABI/FFI standard (Idris2 + Zig). Same pattern used across
27-
https://github.com/hyperpolymath/proven[proven],
28-
https://github.com/hyperpolymath/burble[burble], and
29-
https://github.com/hyperpolymath/gossamer[gossamer].
78+
[cols="2,3"]
79+
|===
80+
| Where | How Cladistics is relevant
81+
82+
| https://github.com/hyperpolymath/developer-ecosystem[developer-ecosystem]
83+
`julia-ecosystem/`
84+
| Cladistics follows the standard Julia RSR package layout enforced by the
85+
Julia ecosystem tooling: Project.toml, test/, benches/, contractiles/.
86+
87+
| https://github.com/hyperpolymath/statistease[statistease]
88+
| Statistease's distance and clustering primitives are conceptually
89+
complementary; Cladistics provides domain-specific biological distance
90+
models (JC69, K2P) beyond generic metrics.
91+
92+
| https://github.com/hyperpolymath/Cliodynamics.jl[Cliodynamics.jl]
93+
| The phylogenetic distance methods in Cladistics can be repurposed for
94+
cultural trait evolution analysis, a use case noted in Turchin's
95+
cliodynamics programme.
96+
97+
| https://github.com/hyperpolymath/hypatia[hypatia]
98+
| Hypatia CI scans Cladistics.jl for SPDX compliance and RSR antipatterns
99+
on every push.
100+
|===
30101

31102
== File Map
32103

33-
[cols="1,2"]
104+
[cols="2,3"]
34105
|===
35-
| Path | What's There
106+
| Path | What is There
107+
108+
| `src/Cladistics.jl`
109+
| Entire package implementation. Data types (`TreeNode`, `PhylogeneticTree`,
110+
`DTCode`), distance computation (`distance_matrix` with 4 methods),
111+
tree-building algorithms (`upgma`, `neighbor_joining`, `maximum_parsimony`),
112+
bootstrap analysis, clade identification, Newick I/O, and parsimony scoring.
113+
114+
| `src/backends/abstract.jl`
115+
| AcceleratorGate coprocessor-dispatch hook (GPU backend stub for bootstrap
116+
resampling and distance matrix computation).
117+
118+
| `src/abi/`
119+
| Idris2 ABI definitions directory — currently scaffolded, not yet populated.
120+
121+
| `test/runtests.jl`
122+
| Tests covering: Hamming/p-distance/JC69/K2P distance matrices (symmetry,
123+
zero diagonal, value correctness); UPGMA and NJ tree construction; parsimony
124+
score computation; bootstrap support; Newick round-trip; clade identification
125+
with confidence threshold.
126+
127+
| `test/e2e_test.jl`
128+
| End-to-end test: distance matrix → NJ tree → bootstrap → clade extraction
129+
pipeline on a synthetic 8-taxon dataset.
130+
131+
| `test/property_test.jl`
132+
| Property invariants: distance matrix symmetry always holds; bootstrap support
133+
values are in [0, 1]; parsimony score is non-negative.
134+
135+
| `benches/benchmarks.jl`
136+
| BenchmarkTools suite for distance matrix computation (varying sequence length
137+
and taxon count), UPGMA, and 100-replicate bootstrap.
138+
139+
| `ffi/`
140+
| Zig FFI directory — structural stub, no operative bindings yet.
141+
142+
| `Project.toml`
143+
| Name `Cladistics`, v0.1.0, MPL-2.0; deps include `AcceleratorGate`,
144+
`LinearAlgebra`, `Statistics`, `Clustering`, `Distances`, `DataFrames`,
145+
`Graphs`.
146+
147+
| `examples/`
148+
| Worked phylogenetic examples on synthetic DNA sequences, including
149+
UPGMA vs NJ comparison and bootstrap support visualisation.
150+
151+
| `contractiles/`
152+
| Contractile interface definitions (RSR interoperability standard).
36153

37-
| `src/` | Source code
38-
| `ffi/` | Foreign function interface
39-
| `test(s)/` | Test suite
154+
| `stapeln.toml`
155+
| Stapeln container configuration for reproducible build environment.
40156
|===
41157

42158
== Questions?

0 commit comments

Comments
 (0)