|
1 | 1 | // SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | +// Copyright (c) 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
2 | 3 | = Cladistics.jl — Show Me The Receipts |
3 | 4 | :toc: |
| 5 | +:toclevels: 3 |
4 | 6 | :icons: font |
5 | 7 |
|
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. |
7 | 10 |
|
8 | | -[quote, README] |
9 | | -____ |
10 | | -See the link:README.adoc[README] for details. |
11 | | -____ |
| 11 | +== README Claims — Verified |
12 | 12 |
|
13 | | -== Technology Choices |
| 13 | +=== Claim 1: "Multiple distance metrics including Jukes-Cantor correction for multiple substitutions" |
14 | 14 |
|
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. |
18 | 21 |
|
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. |
23 | 75 |
|
24 | 76 | == Dogfooded Across The Account |
25 | 77 |
|
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 | +|=== |
30 | 101 |
|
31 | 102 | == File Map |
32 | 103 |
|
33 | | -[cols="1,2"] |
| 104 | +[cols="2,3"] |
34 | 105 | |=== |
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). |
36 | 153 |
|
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. |
40 | 156 | |=== |
41 | 157 |
|
42 | 158 | == Questions? |
|
0 commit comments