Methods

What each analysis computes, and how far to read it · model v1 · reference 1.0.0 (phase-2a)

One upload runs every analysis below, in this order, and the report fills in as each finishes. Each section says what is computed, mirroring the reference implementation function by function, what this implementation was checked against, and what has been measured about the model's behaviour. Where a real HyPhy method exists, the section says how to run it.

The model

surrogate for MEME

A ~1.9M-parameter axial transformer that reads a codon alignment and a metric tree as four tensors (codon tokens, amino-acid tokens, patristic distance matrix, 4-D classical-MDS coordinates) and emits a per-site MEME-style LRT through a 16-threshold ordinal head.

It is a surrogate for MEME: the training targets are MEME likelihood-ratio statistics, and it is evaluated against HyPhy MEME, not against known selection. The suite checkpoint has 2,455,128 parameters across the backbone and the head_meme, head_busted, head_absrel heads; the exported graphs take msa_codons, msa_aas, dist_matrix, mds_coords and return lrt, mean_root_attns, root_repr, which between them unlock every analysis on this page. The genetic code is universal only; the model accepts up to 512 taxa and this application subsamples to 256 by default. Random draws (the permutation nulls, the BUSTED head's missing parameters) come from xoshiro256** seeded with 42; MDS eigenvector signs follow the canonical convention. Model version v1, reference 1.0.0 (phase-2a).

Model variants. The two exported graphs, what each was trained on, and the prefix of the SHA-256 that every surface verifies before it scores.
VariantTrained onRegimeGraph
generalTOGA mammalian, 742 speciesdeep / cross-speciesaa10e8e0…+ head 2ad554e0…
viralbase + ~9,300 Datamonkey viralviral / shallowc3ea5795…

What the model is given instead of a tree

The four tensors above include a patristic distance matrix and its 4-D embedding, and those are the only way the phylogeny reaches the network: it never sees a topology. So a tree is an input to a distance calculation, not to the model, and the app treats it that way. A tree that carries branch lengths is used exactly as supplied. A tree without them, or no tree at all, puts the run in tree-free mode: pairwise Tamura–Nei 93 distances are computed from the alignment and feed the embedding directly. That is the reference's own --use-tn93 path, not a fallback invented here, and the manuscript reports Spearman ρ = 0.9997 between the site scores it produces and the tree-based ones. Nothing is fitted, nothing is inferred for the model, and every sequence is kept, in alignment order, because there is no tree to match names against.

The report still draws a tree — the site-specific tree modal and the phenotype foreground picker both need one — and in tree-free mode that is a neighbour-joining tree built from the same TN93 distances, labelled display only wherever it appears. Two consequences are worth stating: the gene-level phenotype permulations are withheld on such a run, because a Brownian null drawn from a topology inferred from the association's own distances would share its error; and the depth diagnostics now judge the regime on TN93 distances, so an alignment that used to get no depth advice at all may now be told it is deep or shallow.

Every surface verifies the full hash of the graph it loads and records it, the variant, the seed and the surface in the result's provenance. Source: HuggingFace datamonkey/hyphaeon model card and veg/HyphAeon models/manifest.json.

Measured behaviour, alignment-wide

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Rank is strong, scale is compressed.

    On HIV-1 RT the per-site LRT correlates with MEME at Spearman rho 0.53 with a regression slope of 0.16: a HyphAeon LRT of 4 is not a MEME LRT of 4. Across the literature datasets the aggregate is ROC-AUC 0.914, PPV 50.6% and Spearman rho 0.49. Sort by LRT; read rank and percentile; read p and q beside them, never alone.

    HIV-1 RT, Spearman rho vs MEME
    0.53
    HIV-1 RT, regression slope vs MEME
    0.16
    Literature aggregate, ROC-AUC
    0.914
    Literature aggregate, PPV
    50.6%
    Literature aggregate, Spearman rho
    0.49

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  3. Calibration depends on the tree regime.

    On neutral seq-gen simulations the false-positive rate at alpha = 0.05 is 5-7% for 20 taxa on a shallow tree and 50 taxa on a moderate one, and 36% for 100 taxa on a deep tree. The diagnostics step classifies the regime before the model runs; on deep trees with 100 or more taxa, treat p-values as an ordering.

    False-positive rate at alpha = 0.05 on neutral simulations (100 codons, seq-gen)
    RegimeTaxaTree depthFPRGateResult
    small_shallow200.1~5-7%<= 10%PASSED
    moderate500.2~5-7%<= 10%PASSED
    large_deep1000.5~36%<= 10%FAILED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  4. Nearly invariant to the tree's topology, sensitive to its branch-length scale.

    On a six-dataset grid (18-212 taxa, shallow to deep, 26-100% variable sites) the model fails the permutation, star-tree and zero-distance sensitivity gates on most datasets, fails the x0.1, x10 and x100 branch-scaling invariance gates, and passes duplicate-taxon invariance exactly through the default haplotype pruning. What matters is therefore what the checks look at: branch-length units, reading frame, U versus T, taxa missing from the tree (zeroed silently upstream, refused here), a maximum patristic distance above 10 (rescaled upstream, warned here), fewer than three taxa (refused).

    Invariance and sensitivity gates over six datasets (3 real, 3 simulated)
    GateResultDetail
    permutation sensitivityFAILEDinvariant on the majority of 6 datasets; sensitive only on sim_100_deep (r = 0.77)
    star-tree sensitivityFAILEDinvariant on the majority of 6 datasets
    zero-distance sensitivityFAILEDinvariant on the majority of 6 datasets
    scaling x0.1 invarianceFAILEDfails on sim_100_deep (r = 0.81)
    scaling x10 invarianceFAILEDfails on the majority of datasets
    scaling x100 invarianceFAILEDfails on the majority of datasets
    duplicate-taxon invariancePASSEDexact r = 1.0000 through default duplicate-haplotype and tree pruning

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  5. The general and viral variants differ by a factor of four on unseen viral families.

    Spearman rho against MEME is about 0.10 for the general (mammalian) variant and about 0.43 for the viral variant on viral families neither was trained on. Diagnostics suggest the variant from median patristic depth (shallow trees suggest viral); the choice is visible in the report's provenance and can be changed under 'Re-run with'.

    general variant, rho on unseen viral families
    0.10
    viral variant, rho on unseen viral families
    0.43

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  6. MDS eigenvector signs are a convention, fixed to 'canonical' on every surface.

    The model is not sign-invariant (mds_proj is a linear layer on the raw coordinates), and eigensolvers disagree on signs, so until phase-2a the same alignment scored differently on different machines. The canonical rule (largest-magnitude entry of each kept eigenvector positive) is now the default in the Python reference (--mds-sign canonical) and in the JavaScript port. Against the old LAPACK signs, every variable site on every bundled example moves by more than the 1e-5 parity class; rankings are essentially unchanged (Spearman rho >= 0.998) and two RHO sites cross p = 0.05. --mds-sign lapack reproduces pre-convention numbers exactly.

    hyphaeon meme, --mds-sign lapack against --mds-sign canonical, bundled weights, torch 2.10.0
    ExampleNSolverColumns flippedmax |dLRT| (site)Median rel. |dLRT|Spearman rhop <= 0.05 calls changed
    HIV1_RT475LAPACK eigh1, 23.90e-2 (219)9.06e-40.9999620 / 151 (35 -> 35)
    RHO655Lanczos1, 35.95e-1 (183)1.46e-20.9987922 / 145 (23 -> 25)
    Smc620LAPACK eigh1, 2, 31.85e-2 (628)3.52e-40.9999080 / 97 (1 -> 1)
    bat_oas118LAPACK eigh0, 15.40e-1 (332)1.71e-20.9984330 / 182 (5 -> 5)
    camelid212LAPACK eigh1, 22.25e-1 (18)1.03e-20.9991700 / 86 (15 -> 15)

    hyphaeon busted on Smc6: p_value_acat 0.11831563 -> 0.11797637, omnibus_lrt 3.2854052 -> 3.2988663, sig_sites_p05 5 -> 5.

    Source: veg/HyphAeon MDS_SIGN.md, 'Measured effect on the reference's own outputs' (scripts/mds_sign_effect.py)

  7. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  8. Real submissions are unpublished research.

    The browser path never transmits sequences. A server run (oversize inputs, the remote MCP connector) says what will be sent before sending, keeps nothing in logs, and expires the job after 7 days.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

Diagnostics and repairs

report step 1 · diagnose() from @veg/hyphaeon-js
Model outputs
none
In the browser
milliseconds; a second or two more when the pairwise TN93 distance matrix has to be computed

What is computed

One set of checks runs before the model on every surface (browser, MCP, server) and produces the same warning codes: format sniff and embedded tree, U read as T, the non-ACGT fraction, length modulo 3 with in-frame stops and a frameshift heuristic, the unknown-codon fraction, unequal lengths, identical sequences, taxa below three or above the cap, tree-to-alignment name matching in three tiers, missing or negative or saturated branch lengths, a maximum patristic distance above 10, the depth regime, and a cost estimate. Repairs are automatic and recorded: trailing codons trimmed, duplicate haplotypes collapsed with their tips, Faith’s-PD subsampling above the taxon cap, and the variant chosen from median patristic depth. The tree is not repaired at all: one with branch lengths is used as given, and one without — or none — puts the run in tree-free mode, where pairwise TN93 distances feed the embedding directly (the TREE_FREE_TN93 note carries the reason, and TN93_SATURATED_PAIRS counts the pairs too divergent to estimate). The only blocking outcomes are refuse-level: fewer than three taxa, a pervasive frameshift, an unparseable file, alignment taxa with no tip in a tree that IS being used, or a distance matrix that cannot be computed at all.

Result keys warnings[].codewarnings[].severityprovenance.preprocessingprovenance.model_variant

Validated against

The library’s diagnose() is the same code in the browser worker, the MCP’s hyphaeon_validate and the server’s /validate, so the codes cannot drift between surfaces. The tree-free distances are the reference’s own: the ported TN93 matrix is bit-identical to the Python package’s on every bundled example, and the MDS coordinates that follow agree to 7.8e-8 without any sign allowance. Everything applied to your data is shown in the strip at the top of the report and can be changed under “Re-run with”.

Measured behaviour

  1. Calibration depends on the tree regime.

    On neutral seq-gen simulations the false-positive rate at alpha = 0.05 is 5-7% for 20 taxa on a shallow tree and 50 taxa on a moderate one, and 36% for 100 taxa on a deep tree. The diagnostics step classifies the regime before the model runs; on deep trees with 100 or more taxa, treat p-values as an ordering.

    False-positive rate at alpha = 0.05 on neutral simulations (100 codons, seq-gen)
    RegimeTaxaTree depthFPRGateResult
    small_shallow200.1~5-7%<= 10%PASSED
    moderate500.2~5-7%<= 10%PASSED
    large_deep1000.5~36%<= 10%FAILED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  2. Nearly invariant to the tree's topology, sensitive to its branch-length scale.

    On a six-dataset grid (18-212 taxa, shallow to deep, 26-100% variable sites) the model fails the permutation, star-tree and zero-distance sensitivity gates on most datasets, fails the x0.1, x10 and x100 branch-scaling invariance gates, and passes duplicate-taxon invariance exactly through the default haplotype pruning. What matters is therefore what the checks look at: branch-length units, reading frame, U versus T, taxa missing from the tree (zeroed silently upstream, refused here), a maximum patristic distance above 10 (rescaled upstream, warned here), fewer than three taxa (refused).

    Invariance and sensitivity gates over six datasets (3 real, 3 simulated)
    GateResultDetail
    permutation sensitivityFAILEDinvariant on the majority of 6 datasets; sensitive only on sim_100_deep (r = 0.77)
    star-tree sensitivityFAILEDinvariant on the majority of 6 datasets
    zero-distance sensitivityFAILEDinvariant on the majority of 6 datasets
    scaling x0.1 invarianceFAILEDfails on sim_100_deep (r = 0.81)
    scaling x10 invarianceFAILEDfails on the majority of datasets
    scaling x100 invarianceFAILEDfails on the majority of datasets
    duplicate-taxon invariancePASSEDexact r = 1.0000 through default duplicate-haplotype and tree pruning

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  3. The general and viral variants differ by a factor of four on unseen viral families.

    Spearman rho against MEME is about 0.10 for the general (mammalian) variant and about 0.43 for the viral variant on viral families neither was trained on. Diagnostics suggest the variant from median patristic depth (shallow trees suggest viral); the choice is visible in the report's provenance and can be changed under 'Re-run with'.

    general variant, rho on unseen viral families
    0.10
    viral variant, rho on unseen viral families
    0.43

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  4. Shallow single-ancestor panels return nothing, silently.

    A star-like tree with one shared ancestor and short tips is outside the regime the model was trained on; the reference produces an empty-looking result without a warning (issue #33). The diagnostics step raises STAR_LIKE_TREE before the run.

    Source: GitHub issues veg/HyphAeon #7, #8, #9, #13, #33

  5. The app caps taxa at 256 by default; the CLI does not.

    Above the cap, Faith's-PD greedy subsampling keeps the reference sequence and the most phylogenetically diverse taxa (hard maximum 512, the model's trained limit). hyphaeon meme applies no cap, so a reproduction of an uncapped CLI run on a large alignment must set the cap to unlimited under 'Re-run with'. Which taxa were used is recorded in provenance.preprocessing.

    Source: hyphaeon-app PHASE1.md, parity table and known gaps

  6. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  7. Two identical sequences get the LARGEST distance in the matrix, not the smallest.

    compute_tn93_distance_matrix imputes max(1.0, max_d) for a pair of byte-identical sequences, while two DIFFERENT sequences whose estimated distance is zero get 1e-4. It is the reference's behaviour and it is reproduced here rather than corrected. Duplicate haplotypes are collapsed before the matrix is built, so the case is normally unreachable; it becomes reachable when duplicate pruning is turned off, and a pair of identical sequences would then sit as far apart as anything in the alignment.

    Imputed distance, identical sequences
    max(1.0, largest distance)
    Imputed distance, different sequences at zero
    1e-4

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  8. A saturated pair has no TN93 distance, and the diagnostics count them.

    The distance is a logarithm, so a pair of sequences too divergent to estimate reaches log of a non-positive number and a pair with no overlapping ungapped position divides by zero. The reference raises there and nothing catches it. Here the failure becomes the TN93_SATURATED_PAIRS diagnostic: at refuse level when the matrix cannot be computed at all, and otherwise a count of how many pairs came back at the saturation sentinel, shown on the report's strip and in the provenance block. A large count on a deep alignment means the distances - and therefore the embedding the model reads - are least reliable exactly where the sequences are most divergent.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

Site selection

hyphaeon meme
Model outputs
lrt
In the browser
one forward pass over the variable sites; seconds

What is computed

The alignment and tree become the four tensors (codon tokens, amino-acid tokens, the patristic distance matrix, 4-D classical MDS coordinates with canonical eigenvector signs) plus an invariable-site mask. Only variable sites go through the network; each receives a non-negative LRT from the 16-threshold ordinal head, and invariable sites keep LRT 0. The p-value is the MEME asymptotic mixture null, 1/3 δ₀ + 2/3 (0.45 χ²₁ + 0.55 χ²₂), so an LRT of 0 gives p = 2/3; q is Benjamini–Hochberg over all sites; both are stored as float32, as the CLI writes them. App-side, the report adds the columns DataMonkey’s AxoMEME shows beside them, computed from the same LRTs: a local z-score, the percentile among variable sites, and a tier call that toggles between “q ≤ 0.10” and “top 5% of variable sites”.

Result keys sitehyphaeon_lrtp_valueq_valueis_invariablecallpercentile

Validated against

Against hyphaeon meme on the five bundled examples at the parity class 1e-5 · max(1, |LRT|): Smc6 reproduces at a maximum |ΔLRT| of 5.7e-6 under Node and the browser agrees with Node at 5.3e-6; p and q are bit-equal given the LRT; taxa, site order and the invariable flag are exact. Against MEME itself, the calibration and concordance measurements below.

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Rank is strong, scale is compressed.

    On HIV-1 RT the per-site LRT correlates with MEME at Spearman rho 0.53 with a regression slope of 0.16: a HyphAeon LRT of 4 is not a MEME LRT of 4. Across the literature datasets the aggregate is ROC-AUC 0.914, PPV 50.6% and Spearman rho 0.49. Sort by LRT; read rank and percentile; read p and q beside them, never alone.

    HIV-1 RT, Spearman rho vs MEME
    0.53
    HIV-1 RT, regression slope vs MEME
    0.16
    Literature aggregate, ROC-AUC
    0.914
    Literature aggregate, PPV
    50.6%
    Literature aggregate, Spearman rho
    0.49

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  3. Calibration depends on the tree regime.

    On neutral seq-gen simulations the false-positive rate at alpha = 0.05 is 5-7% for 20 taxa on a shallow tree and 50 taxa on a moderate one, and 36% for 100 taxa on a deep tree. The diagnostics step classifies the regime before the model runs; on deep trees with 100 or more taxa, treat p-values as an ordering.

    False-positive rate at alpha = 0.05 on neutral simulations (100 codons, seq-gen)
    RegimeTaxaTree depthFPRGateResult
    small_shallow200.1~5-7%<= 10%PASSED
    moderate500.2~5-7%<= 10%PASSED
    large_deep1000.5~36%<= 10%FAILED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  4. Concordance with MEME on the bundled genes is a rank statement over a mostly neutral background.

    Spearman rho on variable sites is 0.27-0.37 on Smc6, bat_oas1 and camelid, with Cohen's kappa near zero and F1 between 0.00 and 0.30 at matched thresholds; all three pass the acceptance gates. In a long gene such as Smc6 (1,097 sites) more than 90% of sites sit at LRT ~ 0 under neutral or purifying evolution, so a whole-alignment correlation measures baseline noise; agreement on the top sites is what the gates check.

    Concordance with HyPhy MEME 2.5.101 on the bundled genes (variable sites)
    DatasetSpearman rhoCohen's kappaF1Result
    Smc60.37-0.030.00PASSED
    bat_oas10.270.090.14PASSED
    camelid0.310.050.30PASSED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  5. Nucleotide composition and alignment length do not move the calibration.

    AT-rich (80%), GC-rich (30%) and uniform simulations all give 5-9% FPR at alpha = 0.05; 30-, 100- and 500-codon alignments give 3.3-9% with a median LRT ratio of 1.15x across lengths (gate: 3x). p-values from alignments of different lengths are comparable.

    FPR at alpha = 0.05 across nucleotide composition and alignment length (moderate tree)
    ConditionSettingFPRMedian LRTResult
    compositionuniform, 50% AT7-9%PASSED
    compositionAT-rich, 80% AT5-8%PASSED
    compositionGC-rich, 30% AT5-9%PASSED
    lengthshort, 30 codons3.3%1.45PASSED
    lengthmedium, 100 codons7-9%1.35PASSED
    lengthlong, 500 codons4-5%1.27PASSED

    Cross-length median LRT ratio 1.15x against a 3x gate.

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  6. Nearly invariant to the tree's topology, sensitive to its branch-length scale.

    On a six-dataset grid (18-212 taxa, shallow to deep, 26-100% variable sites) the model fails the permutation, star-tree and zero-distance sensitivity gates on most datasets, fails the x0.1, x10 and x100 branch-scaling invariance gates, and passes duplicate-taxon invariance exactly through the default haplotype pruning. What matters is therefore what the checks look at: branch-length units, reading frame, U versus T, taxa missing from the tree (zeroed silently upstream, refused here), a maximum patristic distance above 10 (rescaled upstream, warned here), fewer than three taxa (refused).

    Invariance and sensitivity gates over six datasets (3 real, 3 simulated)
    GateResultDetail
    permutation sensitivityFAILEDinvariant on the majority of 6 datasets; sensitive only on sim_100_deep (r = 0.77)
    star-tree sensitivityFAILEDinvariant on the majority of 6 datasets
    zero-distance sensitivityFAILEDinvariant on the majority of 6 datasets
    scaling x0.1 invarianceFAILEDfails on sim_100_deep (r = 0.81)
    scaling x10 invarianceFAILEDfails on the majority of datasets
    scaling x100 invarianceFAILEDfails on the majority of datasets
    duplicate-taxon invariancePASSEDexact r = 1.0000 through default duplicate-haplotype and tree pruning

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  7. The general and viral variants differ by a factor of four on unseen viral families.

    Spearman rho against MEME is about 0.10 for the general (mammalian) variant and about 0.43 for the viral variant on viral families neither was trained on. Diagnostics suggest the variant from median patristic depth (shallow trees suggest viral); the choice is visible in the report's provenance and can be changed under 'Re-run with'.

    general variant, rho on unseen viral families
    0.10
    viral variant, rho on unseen viral families
    0.43

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  8. Shallow single-ancestor panels return nothing, silently.

    A star-like tree with one shared ancestor and short tips is outside the regime the model was trained on; the reference produces an empty-looking result without a warning (issue #33). The diagnostics step raises STAR_LIKE_TREE before the run.

    Source: GitHub issues veg/HyphAeon #7, #8, #9, #13, #33

  9. Invariable sites are not scored, not zero.

    The model runs on variable sites only; an invariable site gets LRT 0 and p = 2/3 by construction (the point mass of the MEME mixture null), and the report shows it as 'not scored'. Never rank or count these as zeros.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  10. The app caps taxa at 256 by default; the CLI does not.

    Above the cap, Faith's-PD greedy subsampling keeps the reference sequence and the most phylogenetically diverse taxa (hard maximum 512, the model's trained limit). hyphaeon meme applies no cap, so a reproduction of an uncapped CLI run on a large alignment must set the cap to unlimited under 'Re-run with'. Which taxa were used is recorded in provenance.preprocessing.

    Source: hyphaeon-app PHASE1.md, parity table and known gaps

  11. MDS eigenvector signs are a convention, fixed to 'canonical' on every surface.

    The model is not sign-invariant (mds_proj is a linear layer on the raw coordinates), and eigensolvers disagree on signs, so until phase-2a the same alignment scored differently on different machines. The canonical rule (largest-magnitude entry of each kept eigenvector positive) is now the default in the Python reference (--mds-sign canonical) and in the JavaScript port. Against the old LAPACK signs, every variable site on every bundled example moves by more than the 1e-5 parity class; rankings are essentially unchanged (Spearman rho >= 0.998) and two RHO sites cross p = 0.05. --mds-sign lapack reproduces pre-convention numbers exactly.

    hyphaeon meme, --mds-sign lapack against --mds-sign canonical, bundled weights, torch 2.10.0
    ExampleNSolverColumns flippedmax |dLRT| (site)Median rel. |dLRT|Spearman rhop <= 0.05 calls changed
    HIV1_RT475LAPACK eigh1, 23.90e-2 (219)9.06e-40.9999620 / 151 (35 -> 35)
    RHO655Lanczos1, 35.95e-1 (183)1.46e-20.9987922 / 145 (23 -> 25)
    Smc620LAPACK eigh1, 2, 31.85e-2 (628)3.52e-40.9999080 / 97 (1 -> 1)
    bat_oas118LAPACK eigh0, 15.40e-1 (332)1.71e-20.9984330 / 182 (5 -> 5)
    camelid212LAPACK eigh1, 22.25e-1 (18)1.03e-20.9991700 / 86 (15 -> 15)

    hyphaeon busted on Smc6: p_value_acat 0.11831563 -> 0.11797637, omnibus_lrt 3.2854052 -> 3.2988663, sig_sites_p05 5 -> 5.

    Source: veg/HyphAeon MDS_SIGN.md, 'Measured effect on the reference's own outputs' (scripts/mds_sign_effect.py)

  12. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  13. Two identical sequences get the LARGEST distance in the matrix, not the smallest.

    compute_tn93_distance_matrix imputes max(1.0, max_d) for a pair of byte-identical sequences, while two DIFFERENT sequences whose estimated distance is zero get 1e-4. It is the reference's behaviour and it is reproduced here rather than corrected. Duplicate haplotypes are collapsed before the matrix is built, so the case is normally unreachable; it becomes reachable when duplicate pruning is turned off, and a pair of identical sequences would then sit as far apart as anything in the alignment.

    Imputed distance, identical sequences
    max(1.0, largest distance)
    Imputed distance, different sequences at zero
    1e-4

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

Run MEME on Datamonkey Upload the same alignment and tree. MEME’s JSON can then be loaded on the Evaluate page against this run’s CSV.

Gene-level omnibus

hyphaeon busted
Model outputs
lrt + root_repr
In the browser
free from the same forward pass, plus one head pass; negligible

What is computed

The same forward pass keeps the pooled hidden state root_repr for each variable site in a [1, L, 384] tensor. Per-site p-values here use the Self and Liang (1987) mixture, 0.5 δ₀ + 0.5 χ²₁, not the MEME mixture. p_ACAT is the Cauchy combination of the variable sites’ p-values (the mean of tan((0.5 − p)π), back-transformed); p_Simes is the minimum over ranks of (L / rank) · p_sorted; omnibus_lrt = Σ max(0, LRT − 3.841); total_selection_energy = Σ LRT; sig_sites_p05 and sig_sites_p10 count sites below 0.05 and 0.10. The hidden states go through busted_head.onnx, which returns a selection probability, a predicted gene LRT, synonymous rate variation Var(α), ω₃, and the proportions of a three-class ω mixture with ω₁ = 0.10 and ω₂ = 1.00 fixed. positive_selection_detected is p_ACAT < 0.05 or selection probability > 0.5.

Result keys p_value_acatp_value_simesomnibus_lrttotal_selection_energysig_sites_p05selection_probabilitysynonymous_rate_variationrate_distributions

Validated against

The statistical fields against hyphaeon busted at the class: on Smc6 under the canonical MDS convention p_ACAT 0.1179765 against the reference’s 0.1179764, omnibus LRT 3.29886 against 3.29887, significant-site counts exact. The neural head cannot be validated against the reference because the reference is not reproducible there (below).

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Rank is strong, scale is compressed.

    On HIV-1 RT the per-site LRT correlates with MEME at Spearman rho 0.53 with a regression slope of 0.16: a HyphAeon LRT of 4 is not a MEME LRT of 4. Across the literature datasets the aggregate is ROC-AUC 0.914, PPV 50.6% and Spearman rho 0.49. Sort by LRT; read rank and percentile; read p and q beside them, never alone.

    HIV-1 RT, Spearman rho vs MEME
    0.53
    HIV-1 RT, regression slope vs MEME
    0.16
    Literature aggregate, ROC-AUC
    0.914
    Literature aggregate, PPV
    50.6%
    Literature aggregate, Spearman rho
    0.49

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  3. Calibration depends on the tree regime.

    On neutral seq-gen simulations the false-positive rate at alpha = 0.05 is 5-7% for 20 taxa on a shallow tree and 50 taxa on a moderate one, and 36% for 100 taxa on a deep tree. The diagnostics step classifies the regime before the model runs; on deep trees with 100 or more taxa, treat p-values as an ordering.

    False-positive rate at alpha = 0.05 on neutral simulations (100 codons, seq-gen)
    RegimeTaxaTree depthFPRGateResult
    small_shallow200.1~5-7%<= 10%PASSED
    moderate500.2~5-7%<= 10%PASSED
    large_deep1000.5~36%<= 10%FAILED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  4. The general and viral variants differ by a factor of four on unseen viral families.

    Spearman rho against MEME is about 0.10 for the general (mammalian) variant and about 0.43 for the viral variant on viral families neither was trained on. Diagnostics suggest the variant from median patristic depth (shallow trees suggest viral); the choice is visible in the report's provenance and can be changed under 'Re-run with'.

    general variant, rho on unseen viral families
    0.10
    viral variant, rho on unseen viral families
    0.43

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  5. The app caps taxa at 256 by default; the CLI does not.

    Above the cap, Faith's-PD greedy subsampling keeps the reference sequence and the most phylogenetically diverse taxa (hard maximum 512, the model's trained limit). hyphaeon meme applies no cap, so a reproduction of an uncapped CLI run on a large alignment must set the cap to unlimited under 'Re-run with'. Which taxa were used is recorded in provenance.preprocessing.

    Source: hyphaeon-app PHASE1.md, parity table and known gaps

  6. MDS eigenvector signs are a convention, fixed to 'canonical' on every surface.

    The model is not sign-invariant (mds_proj is a linear layer on the raw coordinates), and eigensolvers disagree on signs, so until phase-2a the same alignment scored differently on different machines. The canonical rule (largest-magnitude entry of each kept eigenvector positive) is now the default in the Python reference (--mds-sign canonical) and in the JavaScript port. Against the old LAPACK signs, every variable site on every bundled example moves by more than the 1e-5 parity class; rankings are essentially unchanged (Spearman rho >= 0.998) and two RHO sites cross p = 0.05. --mds-sign lapack reproduces pre-convention numbers exactly.

    hyphaeon meme, --mds-sign lapack against --mds-sign canonical, bundled weights, torch 2.10.0
    ExampleNSolverColumns flippedmax |dLRT| (site)Median rel. |dLRT|Spearman rhop <= 0.05 calls changed
    HIV1_RT475LAPACK eigh1, 23.90e-2 (219)9.06e-40.9999620 / 151 (35 -> 35)
    RHO655Lanczos1, 35.95e-1 (183)1.46e-20.9987922 / 145 (23 -> 25)
    Smc620LAPACK eigh1, 2, 31.85e-2 (628)3.52e-40.9999080 / 97 (1 -> 1)
    bat_oas118LAPACK eigh0, 15.40e-1 (332)1.71e-20.9984330 / 182 (5 -> 5)
    camelid212LAPACK eigh1, 22.25e-1 (18)1.03e-20.9991700 / 86 (15 -> 15)

    hyphaeon busted on Smc6: p_value_acat 0.11831563 -> 0.11797637, omnibus_lrt 3.2854052 -> 3.2988663, sig_sites_p05 5 -> 5.

    Source: veg/HyphAeon MDS_SIGN.md, 'Measured effect on the reference's own outputs' (scripts/mds_sign_effect.py)

  7. The neural BUSTED head is not reproducible upstream; the statistical fields are.

    The bundled model.safetensors lacks 11 BustedMultiTaskHead parameters, and hyphaeon busted loads the head unseeded, so selection_probability, predicted_gene_lrt, synonymous_rate_variation, omega_3 and the class proportions change from run to run of the reference (Smc6 selection_probability 0.995 in one run, 0.601 in the next). This app draws the missing parameters once from a fixed seed and marks the fields deterministic_upstream: false. p_ACAT, p_Simes, the omnibus LRT, total selection energy and the significant-site counts do not depend on the head and reproduce the reference at the parity class.

    Smc6 selection_probability, two reference runs
    0.995, then 0.601
    head parameters missing from model.safetensors
    11

    Source: hyphaeon-app PHASE1.md, parity table and known gaps

  8. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

Run BUSTED[S] on Datamonkey The real omnibus test with synonymous rate variation, on the same alignment and tree.

Epistasis and sectors

hyphaeon epistasis
Model outputs
lrt + mean_root_attns
In the browser
graph math on the same forward pass; the permutation null runs in a worker; seconds

What is computed

The forward pass also returns the root-to-leaf attention mean_root_attns, one weight per taxon per site. Multiplied by the indicator of taxa whose amino acid differs from the site’s consensus, and by the site’s LRT, it gives each site an attribution vector over taxa, with a Self–Liang p per site. The co-selection network takes the float32 cosine between every pair of attribution rows, a Student-t p-value with N − 2 degrees of freedom, Benjamini–Hochberg over all pairs, and the composite epistatic selection index CESI; an edge is kept when cosine ≥ 0.30, shared mutated taxa ≥ 2, q ≤ 0.05, both LRTs ≥ 1.0 and CESI ≥ 2.0. Sector mining takes the sub-graph of connected sites, splits it into greedy-modularity communities (Clauset–Newman–Moore), scores each by spectral coherence C(S) = λ₁ / trace of the community’s attribution Gram matrix, prunes sites with |v_dom| < 0.10, keeps C(S) ≥ 0.50, and tests each sector against B random K-site subsets of active sites drawn with xoshiro256** from the seed: p_perm, the null mean, standard deviation and 95th percentile, and the isotropic baseline 1/K. Sectors are sorted by coherence, then size.

Result keys edges[].similarityedges[].shared_taxaedges[].cesiedges[].fdr_qsectors[].sitessectors[].spectral_coherencesectors[].p_permsectors[].null_coherence_95

Validated against

Against hyphaeon epistasis --seed 42 on Smc6, on the model’s own attention: leaf attributions, LRTs and p-values bit-equal; the five edges bit-identical, key order included; both sectors exact in membership, coherence and strings; p_perm within 3√(p(1−p)/B) at B = 1,000 and at B = 100,000 with three seeds a side. Sector ids reproduce CPython’s set iteration order, which decides them in networkx.

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. MDS eigenvector signs are a convention, fixed to 'canonical' on every surface.

    The model is not sign-invariant (mds_proj is a linear layer on the raw coordinates), and eigensolvers disagree on signs, so until phase-2a the same alignment scored differently on different machines. The canonical rule (largest-magnitude entry of each kept eigenvector positive) is now the default in the Python reference (--mds-sign canonical) and in the JavaScript port. Against the old LAPACK signs, every variable site on every bundled example moves by more than the 1e-5 parity class; rankings are essentially unchanged (Spearman rho >= 0.998) and two RHO sites cross p = 0.05. --mds-sign lapack reproduces pre-convention numbers exactly.

    hyphaeon meme, --mds-sign lapack against --mds-sign canonical, bundled weights, torch 2.10.0
    ExampleNSolverColumns flippedmax |dLRT| (site)Median rel. |dLRT|Spearman rhop <= 0.05 calls changed
    HIV1_RT475LAPACK eigh1, 23.90e-2 (219)9.06e-40.9999620 / 151 (35 -> 35)
    RHO655Lanczos1, 35.95e-1 (183)1.46e-20.9987922 / 145 (23 -> 25)
    Smc620LAPACK eigh1, 2, 31.85e-2 (628)3.52e-40.9999080 / 97 (1 -> 1)
    bat_oas118LAPACK eigh0, 15.40e-1 (332)1.71e-20.9984330 / 182 (5 -> 5)
    camelid212LAPACK eigh1, 22.25e-1 (18)1.03e-20.9991700 / 86 (15 -> 15)

    hyphaeon busted on Smc6: p_value_acat 0.11831563 -> 0.11797637, omnibus_lrt 3.2854052 -> 3.2988663, sig_sites_p05 5 -> 5.

    Source: veg/HyphAeon MDS_SIGN.md, 'Measured effect on the reference's own outputs' (scripts/mds_sign_effect.py)

  3. p_perm is a Monte Carlo estimate; its resolution is 1/B.

    The sector null is B random K-site subsets. At the CLI's B = 1,000 the estimate carries roughly +/-0.03 absolute error and the null moments +/-5%, independently on each side of a parity comparison; the same two Smc6 sectors at B = 100,000 with three seeds a side agree to well inside the class (sector 1: p_perm 0.0011-0.0014; sector 2: 0.080-0.082). The report prints p_perm at the resolution B allows and shows the null band beside it; B = 10,000 is the function default and the setting the parity class was written for.

    Monte Carlo error on p_perm at B = 1,000
    about +/-0.03
    Monte Carlo error on null mean / std at B = 1,000
    about +/-5%
    Default B (function and parity harness)
    10,000

    Source: veg/HyphAeon PHASE2A.md, 'Epistasis end to end' and 'Python quirks replicated'

  4. Three reference quirks are reproduced on purpose.

    'Branches' means taxa: the co-selection network compares per-taxon attribution rows, with no branch projection and no APC correction. The CLI passes min_sim 0.30 where the function's default is 0.35; the report uses the CLI's value. max_overlap is declared and never read, so no Jaccard suppression between sectors happens. Thresholds are compared in float32, as numpy does, so a cosine of exactly 0.35 passes 0.35.

    Source: veg/HyphAeon PHASE2A.md, 'Epistasis end to end' and 'Python quirks replicated'

  5. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

Run BGM on Datamonkey A Bayesian graphical model of co-evolving sites on the same alignment. A different method, not the surrogate’s target, so agreement corroborates rather than reproduces.

Attribution

hyphaeon meme --attribute
Model outputs
lrt
In the browser
re-scoring loop over the non-consensus taxa at called sites; seconds

What is computed

At each site the report calls (LRT ≥ 3.84 by default, nominal p ≤ 0.05), the consensus codon is the most frequent one; each taxon that differs is mutated to it, alone, and the site is re-scored through the same tree cache. delta_lrt = LRT − LRT_mutated and pct_signal_explained = max(0, delta_lrt / LRT) per driver; drivers are sorted by delta_lrt, and top_driver and top_mutation name the largest. The delta_lrt-weighted mean of the positive drivers’ mean patristic depth to the other taxa, relative to the tree’s maximum, places the signal in an evolutionary epoch: a recent terminal sweep, an intermediate subclade burst, or a deep ancestral divergence.

Result keys top_drivertop_mutationevolutionary_epochattribution_details[].delta_lrtattribution_details[].pct_signal_explained

Validated against

The attribute_selection fixture replayed through ONNX: maximum |Δ delta_lrt| 1.10e-5 over the six attributed Smc6 sites; driver order, codons and epoch strings exact.

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Attribution explains the surrogate's signal, not MEME's.

    Each non-consensus taxon at a called site is mutated to the consensus codon and the site re-scored; delta LRT is the model's own sensitivity to that taxon's state. It answers 'which lineages move this prediction' and 'how deep in the tree they sit' with the same compressed scale as the LRT itself, and it is only computed at sites with LRT >= 3.84 by default.

    Source: hyphaeon-app PHASE1.md, parity table and known gaps

No HyPhy counterpart: this analysis is a property of the surrogate, not a prediction of another method.

Alignment-artifact filter

hyphaeon meme --filter
Model outputs
lrt
In the browser
two re-scoring passes; seconds

What is computed

Stage one scans the site p-values: a window of at most 35 codons holding at least 3 sites at p ≤ 0.05 is a candidate patch when the hypergeometric probability of that many hits in that span, given the alignment-wide count, is below 0.01. Stage two audits each patch per taxon: the longest run of consecutive radical mismatches against the column consensus and that taxon’s share of the patch’s mismatches, the outlier contamination index; a taxon is an artifact when run ≥ 3 and OCI ≥ 0.25, or run ≥ 4. Artifact codons are masked to gaps, the cleaned alignment is re-scored, and both sets of scores are kept. App-side, the report shows the number of masked patches and a masked/unmasked toggle; the mask is never applied silently and never offered as a pre-run option.

Result keys artifacts_masked[].taxonartifacts_masked[].startartifacts_masked[].endartifacts_masked[].outlier_contamination_indexcleaned_metrics

Validated against

The camelid end-to-end fixture: patches, artifact audit rows and cleaned metrics replayed exactly through the library’s runAlignmentFilter in CLI mode; the cleaned re-score at the LRT class. Two reference quirks pass through by design: --filter with an embedded tree and at least one masked artifact fails at the cleaned reload upstream, and the cleaned re-score reuses the baseline tree cache.

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Calibration depends on the tree regime.

    On neutral seq-gen simulations the false-positive rate at alpha = 0.05 is 5-7% for 20 taxa on a shallow tree and 50 taxa on a moderate one, and 36% for 100 taxa on a deep tree. The diagnostics step classifies the regime before the model runs; on deep trees with 100 or more taxa, treat p-values as an ordering.

    False-positive rate at alpha = 0.05 on neutral simulations (100 codons, seq-gen)
    RegimeTaxaTree depthFPRGateResult
    small_shallow200.1~5-7%<= 10%PASSED
    moderate500.2~5-7%<= 10%PASSED
    large_deep1000.5~36%<= 10%FAILED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

  3. The artifact filter reads the site p-values, so it inherits their calibration.

    A patch is flagged when nominally significant sites cluster (hypergeometric test at p < 0.01 over a window of at most 35 codons with at least 3 sites at p <= 0.05) and one taxon carries the mismatches (a run of at least 3 radical substitutions with an outlier contamination index >= 0.25, or a run of 4). On deep trees with many taxa the 36% FPR makes clusters of nominal hits more likely, and masked patches should be inspected. The report shows masked and unmasked scores side by side and never applies the mask silently.

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

No HyPhy counterpart: this analysis is a property of the surrogate, not a prediction of another method.

Digital deep mutational scan

hyphaeon dms
Model outputs
lrt (19 · L passes)
In the browser
the expensive one: 19 · L forward passes, tens of seconds to minutes; runs last, fills in progressively, cancellable, capped by work

What is computed

One focal taxon (the first, or --focal-taxon). At each site its amino acid is replaced by each of the other 19 through the canonical codon for that residue (GCC for A, TGC for C, and so on), giving 19 mutant alignments per site that go through the network in chunks. delta = LRT_mutant − LRT_baseline; intrinsic_plasticity Φ is the mean |delta| over the 19; the mean, maximum and minimum delta and the full mutant_deltas map are kept with the baseline LRT and its Self–Liang p. App-side, the report draws the 19 × L heatmap and the plasticity track as sites finish, and stops at the work cap 19 · L · N² with an offer to finish on the server.

Result keys plasticity[].siteplasticity[].wt_aaplasticity[].baseline_lrtplasticity[].intrinsic_plasticityplasticity[].max_delta_lrtplasticity[].mutant_deltastotal_mutations

Validated against

The run_insilico_selection_dms fixture: every delta, baseline and reduction bit-equal via playback of the recorded model outputs; p-values at 1e-9. The ONNX replay at the LRT class is the runtime’s.

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Invariable sites are not scored, not zero.

    The model runs on variable sites only; an invariable site gets LRT 0 and p = 2/3 by construction (the point mass of the MEME mixture null), and the report shows it as 'not scored'. Never rank or count these as zeros.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  3. MDS eigenvector signs are a convention, fixed to 'canonical' on every surface.

    The model is not sign-invariant (mds_proj is a linear layer on the raw coordinates), and eigensolvers disagree on signs, so until phase-2a the same alignment scored differently on different machines. The canonical rule (largest-magnitude entry of each kept eigenvector positive) is now the default in the Python reference (--mds-sign canonical) and in the JavaScript port. Against the old LAPACK signs, every variable site on every bundled example moves by more than the 1e-5 parity class; rankings are essentially unchanged (Spearman rho >= 0.998) and two RHO sites cross p = 0.05. --mds-sign lapack reproduces pre-convention numbers exactly.

    hyphaeon meme, --mds-sign lapack against --mds-sign canonical, bundled weights, torch 2.10.0
    ExampleNSolverColumns flippedmax |dLRT| (site)Median rel. |dLRT|Spearman rhop <= 0.05 calls changed
    HIV1_RT475LAPACK eigh1, 23.90e-2 (219)9.06e-40.9999620 / 151 (35 -> 35)
    RHO655Lanczos1, 35.95e-1 (183)1.46e-20.9987922 / 145 (23 -> 25)
    Smc620LAPACK eigh1, 2, 31.85e-2 (628)3.52e-40.9999080 / 97 (1 -> 1)
    bat_oas118LAPACK eigh0, 15.40e-1 (332)1.71e-20.9984330 / 182 (5 -> 5)
    camelid212LAPACK eigh1, 22.25e-1 (18)1.03e-20.9991700 / 86 (15 -> 15)

    hyphaeon busted on Smc6: p_value_acat 0.11831563 -> 0.11797637, omnibus_lrt 3.2854052 -> 3.2988663, sig_sites_p05 5 -> 5.

    Source: veg/HyphAeon MDS_SIGN.md, 'Measured effect on the reference's own outputs' (scripts/mds_sign_effect.py)

  4. The scan mutates one focal taxon, and total_mutations counts 19 per codon regardless.

    Each of the 19 alternative residues replaces the focal taxon's amino acid (first taxon unless --focal-taxon; the column majority when the focal residue is a gap or unknown) through its canonical codon, so the result is a property of that lineage's context. total_mutations is 19 x codon_count even when only a subset of sites was swept, and the per-site p_value is the Self-Liang p of the unmutated baseline LRT, not a test of the deltas. In the browser the scan runs last, fills in progressively, can be cancelled, and is capped by the work term 19 x L x N^2; above the cap the report says so and offers a server run.

    Source: veg/HyphAeon PHASE2A.md, 'Epistasis end to end' and 'Python quirks replicated'

  5. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

No HyPhy counterpart: this analysis is a property of the surrogate, not a prediction of another method.

Phenotype association

hyphaeon phenotype
Model outputs
lrt + mean_root_attns
In the browser
seconds; on demand, because it needs a trait, and it runs on the model the report already loaded

Runs in the browser. Describe the trait on the report — a curated preset that matches these taxa, tips clicked on the tree, a pasted list or pattern, or a trait table — and the pillar runs beside the other sections. There is no Python behind it on any surface.

What is computed

The trait vector comes from one of three sources, in the reference’s own priority order: a table (CSV or TSV, a species column and a trait column, binary or continuous), a curated preset (echolocation, marine, fossorial, hibernation, longevity, high altitude, cardenolide resistance, dim light), or an inline foreground list — where each entry is tried as a regular expression first and only then as a glob. Attribution vectors over taxa are computed exactly as for epistasis, from the same attention and the same non-consensus indicator, and each site’s attribution row is correlated with the trait vector: ρ on the unit hypersphere, a Student-t p on N−2 degrees of freedom, and a combined p that is the Cauchy combination of that and the site’s own LRT p, with Benjamini–Hochberg q over the combined column. score = √max(0, LRT) × max(0, ρ) orders the table, and the first fifteen sites clearing ρ ≥ 0.40 and score ≥ 0.50 become the PARS signature of reference and derived residues with their foreground and background frequencies. Gene-level: spectral energy ‖A·ŷ‖, its ratio to the Frobenius norm, and a length-adjusted extreme-value p for the largest association against a null of standard error 1/√max(10, N). The called sites (q ≤ α with ρ > 0) go through the same sector miner as the epistasis pillar, at its looser trait gates. With permulations > 0 and a tree with branch lengths, Brownian-motion permulations of the trait give a second, empirical gene p and replace the parametric association p; without such a tree they are skipped and said to be skipped.

Result keys sites[].association_rhosites[].scoresites[].p_valuesites[].q_valuecompact_pars_signaturep_evd_length_adjustednorm_spectral_ratiotrait_sectorsgene_p_value_perm

Validated against

Against run_phenotype_association on RHO with the README marine foreground, on the model’s own captured attention: the 21 record keys identical and in order, 145 site rows in the same score order, every string, count, frequency column and both attention means bit-identical, and the model-dependent columns (attribution norm, ρ, its p-values, score and q) within 1e-6 — the residuals all trace to one float32 BLAS reduction that no JavaScript summation reproduces. The one trait sector matches in membership, coherence, null moments and PARS string. resolve_phenotype_vector (15 cases), compute_phylogenetic_covariance (3) and generate_permulations (3) have their own fixtures; the permulation draws are checked statistically, as the plan’s classes require.

Measured behaviour

  1. HyphAeon is a surrogate for MEME, evaluated against MEME, not against truth.

    The training targets are MEME LRTs. Every result carries is_surrogate: true and surrogate_for as data. A site you intend to publish should be confirmed with the real method.

    Run MEME on Datamonkey for the alignment; the report links to it.

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. MDS eigenvector signs are a convention, fixed to 'canonical' on every surface.

    The model is not sign-invariant (mds_proj is a linear layer on the raw coordinates), and eigensolvers disagree on signs, so until phase-2a the same alignment scored differently on different machines. The canonical rule (largest-magnitude entry of each kept eigenvector positive) is now the default in the Python reference (--mds-sign canonical) and in the JavaScript port. Against the old LAPACK signs, every variable site on every bundled example moves by more than the 1e-5 parity class; rankings are essentially unchanged (Spearman rho >= 0.998) and two RHO sites cross p = 0.05. --mds-sign lapack reproduces pre-convention numbers exactly.

    hyphaeon meme, --mds-sign lapack against --mds-sign canonical, bundled weights, torch 2.10.0
    ExampleNSolverColumns flippedmax |dLRT| (site)Median rel. |dLRT|Spearman rhop <= 0.05 calls changed
    HIV1_RT475LAPACK eigh1, 23.90e-2 (219)9.06e-40.9999620 / 151 (35 -> 35)
    RHO655Lanczos1, 35.95e-1 (183)1.46e-20.9987922 / 145 (23 -> 25)
    Smc620LAPACK eigh1, 2, 31.85e-2 (628)3.52e-40.9999080 / 97 (1 -> 1)
    bat_oas118LAPACK eigh0, 15.40e-1 (332)1.71e-20.9984330 / 182 (5 -> 5)
    camelid212LAPACK eigh1, 22.25e-1 (18)1.03e-20.9991700 / 86 (15 -> 15)

    hyphaeon busted on Smc6: p_value_acat 0.11831563 -> 0.11797637, omnibus_lrt 3.2854052 -> 3.2988663, sig_sites_p05 5 -> 5.

    Source: veg/HyphAeon MDS_SIGN.md, 'Measured effect on the reference's own outputs' (scripts/mds_sign_effect.py)

  3. p_perm is a Monte Carlo estimate; its resolution is 1/B.

    The sector null is B random K-site subsets. At the CLI's B = 1,000 the estimate carries roughly +/-0.03 absolute error and the null moments +/-5%, independently on each side of a parity comparison; the same two Smc6 sectors at B = 100,000 with three seeds a side agree to well inside the class (sector 1: p_perm 0.0011-0.0014; sector 2: 0.080-0.082). The report prints p_perm at the resolution B allows and shows the null band beside it; B = 10,000 is the function default and the setting the parity class was written for.

    Monte Carlo error on p_perm at B = 1,000
    about +/-0.03
    Monte Carlo error on null mean / std at B = 1,000
    about +/-5%
    Default B (function and parity harness)
    10,000

    Source: veg/HyphAeon PHASE2A.md, 'Epistasis end to end' and 'Python quirks replicated'

  4. No tree, or no branch lengths, means TN93 distances rather than an estimated tree.

    The model reads a distance matrix, not a topology. When the upload carries a tree with branch lengths it is used as given; when it does not, pairwise Tamura-Nei 93 distances go into the MDS directly, which is the reference's own --use-tn93 path (dataset.py:493-571 and 598-636) and not a fallback invented here. The manuscript reports Spearman rho = 0.9997 between tree-free and tree-based site scores. Nothing is fitted and no phylogeny is inferred for the model: the tree drawn beside a tree-free report is a neighbour-joining tree on those same distances, for display only. The Python reference and this port compute the same distance matrix bit for bit on the bundled examples, so camelid and HIV-1 RT - whose numbers used to differ between surfaces because two builds of an external engine fitted their branch lengths differently - now agree by construction.

    Tree-free vs tree-based site scores, Spearman rho
    0.9997
    TN93 distance matrix, Python vs JavaScript
    bit-identical (max |delta| 0.0)
    MDS coordinates, worst residual (bat_oas1, camelid)
    7.8e-8

    Supply a tree with branch lengths when you have one; the report's strip says which path your dataset took.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  5. A foreground pattern is a regular expression before it is a glob.

    resolve_phenotype_vector runs re.search on each pattern first and only falls back to fnmatch if that neither matched nor raised (phenotype.py:249-256), so a pattern typed as a shell glob is silently a regular expression: pan* is 'pa followed by zero or more n' and matches papAnu. The panel says so as soon as a glob character is typed and lists the taxa the pattern actually matched, because the failure is silent and the count is the only way to see it. Presets are unaffected: their branch uses fnmatch, plus a substring test for the patterns that are bare names.

    Read the matched taxa under the box before running; a prefix without the star matches by substring anyway.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  6. Permulations need a tree with branch lengths, so a tree-free report has no empirical gene p.

    The gene-level empirical p comes from Brownian-motion permulations of the trait on the phylogeny (phenotype.py:275-346): a root-to-tip covariance, a Cholesky factor, Gaussian draws rank-matched to the trait. A tree-free run has no such tree, and the neighbour-joining tree drawn beside it is inferred from the very distances the association is computed on, so a null drawn from it would share the alternative's error. The permulation control is therefore disabled with that sentence and the association p-values stay the parametric t-test ones - which is exactly what hyphaeon phenotype --use-tn93 reports. The length-adjusted extreme-value p is computed either way.

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

  7. Phenotype association needs a trait, so it runs on demand, and it is not covered by model_eval.

    model_eval covers hyphaeon meme only; the trait association, PARS signatures and permulations have exact fixtures from the reference but no calibration suite against a simulated neutral trait. The pillar runs in the browser on the model this report already loaded, and its site statistics were checked against the reference on RHO with the README marine foreground: the 21 record keys in order, 145 site rows, every string, count, sort order and both attention columns bit-identical, and the model-dependent columns within 1e-6. Permulations use numpy's legacy global generator upstream, so that parity is statistical from the start.

    RHO marine probe, failing assertions
    0
    Worst residual on a model-dependent column
    4.4e-7

    Source: veg/HyphAeon PHASE3A.md, 'Tree-free parity, the D22 probe', 'The phenotype pillar end to end' and 'Python quirks replicated in this phase'

Run Contrast-FEL on Datamonkey Tests whether selection differs between foreground and background branches at each site: the closest real method to a trait association.

Evaluate against MEME

hyphaeon evaluate
Model outputs
none
In the browser
instant; no model runs

What is computed

A prediction CSV from meme and a MEME JSON are paired by gene name (.csv and .MEME.json stripped); MEME’s global site ids are recovered from its partition coverage; sites are pooled across genes. Pearson r and Spearman ρ on the LRTs. At α = 0.05 and 0.10, MEME’s p ≤ α is the reference label and hyphaeon_lrt the score for ROC-AUC, and both methods’ p ≤ α calls fill a confusion matrix for PPV = TP / (TP + FP) and FPR = FP / (FP + TN); per-gene site counts are listed; a metric that is undefined (one class) is reported as null with a warning.

Result keys pearson_rspearman_rhothresholds[].roc_aucthresholds[].ppvthresholds[].fprthresholds[].confusionper_gene

Validated against

evaluateFiles against the Python on the end-to-end fixtures at 1e-9 for every metric; confusion matrices exact. This is the tool behind the concordance numbers quoted on this page, run on the bundled genes against HyPhy 2.5.101.

Measured behaviour

  1. Rank is strong, scale is compressed.

    On HIV-1 RT the per-site LRT correlates with MEME at Spearman rho 0.53 with a regression slope of 0.16: a HyphAeon LRT of 4 is not a MEME LRT of 4. Across the literature datasets the aggregate is ROC-AUC 0.914, PPV 50.6% and Spearman rho 0.49. Sort by LRT; read rank and percentile; read p and q beside them, never alone.

    HIV-1 RT, Spearman rho vs MEME
    0.53
    HIV-1 RT, regression slope vs MEME
    0.16
    Literature aggregate, ROC-AUC
    0.914
    Literature aggregate, PPV
    50.6%
    Literature aggregate, Spearman rho
    0.49

    Source: hyphaeon-manuscript main.tex, figures as quoted in hyphaeon-app PLAN.md section 2

  2. Concordance with MEME on the bundled genes is a rank statement over a mostly neutral background.

    Spearman rho on variable sites is 0.27-0.37 on Smc6, bat_oas1 and camelid, with Cohen's kappa near zero and F1 between 0.00 and 0.30 at matched thresholds; all three pass the acceptance gates. In a long gene such as Smc6 (1,097 sites) more than 90% of sites sit at LRT ~ 0 under neutral or purifying evolution, so a whole-alignment correlation measures baseline noise; agreement on the top sites is what the gates check.

    Concordance with HyPhy MEME 2.5.101 on the bundled genes (variable sites)
    DatasetSpearman rhoCohen's kappaF1Result
    Smc60.37-0.030.00PASSED
    bat_oas10.270.090.14PASSED
    camelid0.310.050.30PASSED

    Source: veg/HyphAeon model_eval/README.md, the 'Current state (hyphaeon_v1)' tables (HyPhy 2.5.101 for the cached MEME runs, seq-gen 1.3.5 for the neutral simulations)

Run MEME on Datamonkey Run MEME, download its JSON, and load it on the Evaluate page beside the CSV from your report.

Reproducing a report

provenance.reference_command

Every report carries a provenance block with the surface that computed it, the model version, variant and graph hash, the seed, the options as submitted, everything the diagnostics step did to the data, and the hyphaeon command line that reproduces the run with the Python reference. The same run is one tool call away in Claude through MCP, and the report's "Reproduce" panel prints that call.