Skip to content

Commit 44e2c8b

Browse files
committed
Release v0.0.24
1 parent ff0ca0c commit 44e2c8b

9 files changed

Lines changed: 386 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ single version, bumped together via `make bump-{patch,minor,major}`.
88

99
## [Unreleased]
1010

11+
### Added
12+
- Three substitution models: `TajimaNei` (Tajima-Nei 1984, DNA — corrects
13+
Jukes-Cantor for unequal base frequencies), `Tamura` (Tamura 1992, DNA —
14+
Kimura two-parameter with a GC-content correction), and `KimuraProtein`
15+
(Kimura 1983, protein — empirical correction to the Poisson distance). All are
16+
closed-form and reduce to the model they extend under the appropriate
17+
conditions (Tajima-Nei → Jukes-Cantor at equal frequencies, Tamura →
18+
Kimura-2P at GC = 0.5). Exposed across the CLI, Python, and WASM bindings.
19+
1120
## [0.0.23] - 2026-06-04
1221

1322
### Fixed

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ FASTA input / SequenceObject list
8989

9090
### Substitution models (`models.rs`)
9191

92-
Models implement `ModelCalculation<A: AlphabetEncoding>`. DNA-only: `PDiff`, `JukesCantor`, `Kimura2P`. Protein-only: `Poisson`. `PDiff` works for both alphabets. Model–alphabet compatibility is enforced at runtime inside `nj()`.
92+
Models implement `ModelCalculation<A: AlphabetEncoding>`. DNA-only: `JukesCantor`, `Kimura2P`, `TajimaNei`, `Tamura`. Protein-only: `Poisson`, `KimuraProtein`. `PDiff` works for both alphabets. Model–alphabet compatibility is enforced at runtime inside `nj()` (the `dispatch_run!` macro in `lib.rs`).
9393

9494
### Bootstrap support
9595

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ opt-level = 3
77
lto = true
88

99
[workspace.package]
10-
version = "0.0.23"
10+
version = "0.0.24"
1111
edition = "2024"
1212
authors = ["Rens Holmer"]
1313
license = "MIT"

nj/src/lib.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@
4646
//! | `PDiff` | ✓ | ✓ |
4747
//! | `JukesCantor` | ✓ | — |
4848
//! | `Kimura2P` | ✓ | — |
49+
//! | `TajimaNei` | ✓ | — |
50+
//! | `Tamura` | ✓ | — |
4951
//! | `Poisson` | — | ✓ |
52+
//! | `KimuraProtein` | — | ✓ |
5053
//!
5154
//! Providing an incompatible model returns an `Err` from [`nj`].
5255
pub mod alphabet;
@@ -71,7 +74,9 @@ pub use crate::distance_matrix::DistanceResult;
7174
pub use crate::error::NJError;
7275
pub use crate::event::{LogLevel, NJEvent};
7376
pub use crate::fasta::parse_fasta;
74-
use crate::models::{JukesCantor, Kimura2P, ModelCalculation, PDiff, Poisson};
77+
use crate::models::{
78+
JukesCantor, Kimura2P, KimuraProtein, ModelCalculation, PDiff, Poisson, TajimaNei, Tamura,
79+
};
7580
use crate::tree::{NameOrSupport, TreeNode};
7681

7782
/// Fills `out` with the leaf indices of all taxa in the subtree rooted at `node`.
@@ -553,10 +558,18 @@ macro_rules! dispatch_run {
553558
SubstitutionModel::Kimura2P => {
554559
$run::<DNA, Kimura2P>(msa, $($arg),*).map_err(NJError::AlgorithmFailure)
555560
}
556-
SubstitutionModel::Poisson => Err(NJError::IncompatibleModel {
557-
model,
558-
alphabet: Alphabet::DNA,
559-
}),
561+
SubstitutionModel::TajimaNei => {
562+
$run::<DNA, TajimaNei>(msa, $($arg),*).map_err(NJError::AlgorithmFailure)
563+
}
564+
SubstitutionModel::Tamura => {
565+
$run::<DNA, Tamura>(msa, $($arg),*).map_err(NJError::AlgorithmFailure)
566+
}
567+
SubstitutionModel::Poisson | SubstitutionModel::KimuraProtein => {
568+
Err(NJError::IncompatibleModel {
569+
model,
570+
alphabet: Alphabet::DNA,
571+
})
572+
}
560573
}
561574
}
562575
Alphabet::Protein => {
@@ -566,15 +579,20 @@ macro_rules! dispatch_run {
566579
SubstitutionModel::Poisson => {
567580
$run::<Protein, Poisson>(msa, $($arg),*).map_err(NJError::AlgorithmFailure)
568581
}
582+
SubstitutionModel::KimuraProtein => {
583+
$run::<Protein, KimuraProtein>(msa, $($arg),*)
584+
.map_err(NJError::AlgorithmFailure)
585+
}
569586
SubstitutionModel::PDiff => {
570587
$run::<Protein, PDiff>(msa, $($arg),*).map_err(NJError::AlgorithmFailure)
571588
}
572-
SubstitutionModel::JukesCantor | SubstitutionModel::Kimura2P => {
573-
Err(NJError::IncompatibleModel {
574-
model,
575-
alphabet: Alphabet::Protein,
576-
})
577-
}
589+
SubstitutionModel::JukesCantor
590+
| SubstitutionModel::Kimura2P
591+
| SubstitutionModel::TajimaNei
592+
| SubstitutionModel::Tamura => Err(NJError::IncompatibleModel {
593+
model,
594+
alphabet: Alphabet::Protein,
595+
}),
578596
}
579597
}
580598
}

0 commit comments

Comments
 (0)