Disease similarity profiles¶
A profile is a declarative description of a published, group-level
disease-associated microbiome pattern. It says which features were reported,
which way each moved, how the finding was measured, and how far the evidence
has come. It contains no scoring logic — that lives in openbiota/scoring.py,
which has no knowledge of which condition it is scoring.
Thirty-three profiles ship. List them with openbiota profiles, inspect one
with openbiota profiles --show crohns. Every profile in the library is scored
on every sample, and the result is read as a shape across the library rather
than as thirty-three independent verdicts.
What a percentile means¶
The sample is more concordant with this profile's prespecified pattern than that fraction of the matched reference set.
It is not a probability of having the condition. Every design decision below follows from holding that distinction.
The library¶
| Profile | Family | Maturity | Study modules (fused) | Features | Evidence | Challenge for |
|---|---|---|---|---|---|---|
crc |
colorectal | P3 | 5 (2) | 22 | taxa · genes · carriers | adenoma, crohns, cirrhosis |
adenoma |
colorectal | P3 | 3 (2) | 11 | taxa · genes | crc |
crohns |
ibd | P3 | 7 (5) | 41 | taxa · genes · carriers · ecology | crc, uc |
uc |
ibd | P3 | 6 (4) | 19 | taxa · genes · carriers · ecology | crohns, crc |
ibd |
ibd | P3 | 6 (4) | 27 | taxa · genes · carriers · ecology | — |
ibs, ibs_c, ibs_d, ibs_m |
ibs | P2 / P1 | 5 (4) / 3 (2) / 3 (2) / 2 (1) | 19 / 4 / 11 / 6 | taxa · genes (· ecology) | — |
t2d |
cardiometabolic | P3 | 5 (3) | 23 | taxa · genes · carriers | — |
acvd |
cardiometabolic | P3 | 4 (2) | 22 | taxa · genes · carriers | cirrhosis, t2d |
hypertension |
cardiometabolic | P2 | 3 (2) | 13 | taxa · genes · ecology | acvd, obesity, t2d |
ckd |
cardiometabolic | P2 | 4 (2) | 21 | taxa · genes · carriers | t2d, hypertension, cirrhosis |
obesity |
cardiometabolic | P3 | 6 (3) | 9 | taxa · genes · carriers · ecology | — |
cirrhosis |
liver | P3 | 5 (3) | 23 | taxa · genes · carriers · ecology | crc, crohns |
masld |
liver | P2 | 6 (4) | 16 | taxa · genes · carriers · ecology | cirrhosis, obesity, t2d |
parkinsons |
neurodegeneration | P3 | 5 (3) | 30 | taxa · genes · carriers | — |
ad_clinical, ad_mci, ad_preclinical_amyloid |
alzheimers_continuum | P2 | 4 (1) / 3 (1) / 2 (1) | 20 / 10 / 5 | taxa · genes (· pathways, unbound) | — |
ms |
autoimmune | P3 | 5 (3) | 16 | taxa · genes · carriers | — |
ra |
autoimmune | P3 | 4 (2) | 11 | taxa · genes (· strain, unbound) | — |
t1d |
autoimmune | P2 | 5 (3) | 13 | taxa · genes · carriers · ecology | — |
celiac |
autoimmune | P2 | 4 (2) | 14 | taxa · genes (· CAZy, unbound) | — |
ankylosing_spondylitis |
autoimmune | P2 | 4 (2) | 16 | taxa · genes · carriers | — |
mdd |
psychiatric | P2 | 4 (3) | 16 | taxa · genes | — |
alopecia_areata |
alopecia_areata | P1 | 9 (5) | 29 | taxa · genes (· pathways, unbound) | — |
androgenetic_alopecia |
androgenetic_alopecia | P1 | 4 (3) | 11 | taxa · genes | — (sex-stratified) |
mecfs |
post_infectious | P2 | 3 (3) | 7 | taxa · genes · ecology | longcovid, ibs |
longcovid |
post_infectious | P1 | 4 (3) | 15 | taxa · genes · ecology | mecfs, ibs |
"Study modules" counts every module in the profile; "fused" is how many enter the combined score (the rest are sensitivity panels, phenotype panels, or modules whose evidence type has no engine yet). Measured accuracy where a labelled cohort exists: VALIDATION.md.
The contract (spec 3)¶
Every profile declares what kind of claim it is making, and the loader refuses one that does not.
Evidence type — what was measured. Bound types have an engine in this pipeline; unbound types load, are shown, and say what would bind them.
| Type | Claim level | Engine | Status |
|---|---|---|---|
TAX_REL, TAX_PRES |
observed | MetaPhlAn 3 species relative abundance / presence | bound |
GENE_ABUND |
genomic_capacity | DIAMOND gene panels, rpoB-normalised | bound |
CARRIER_ABUNDANCE |
carrier_proxy | sum of a curated carrier set (panel organisms or a taxon group) |
bound |
ECO |
observed | Shannon, richness, evenness | bound |
STRAIN, PANCNV |
observed | StrainPhlAn / MIDAS2 / PanPhlAn | unbound |
SEQ_HMM, PATH_ABUND, PATH_COMPL, CAZY, AMR |
genomic_capacity | HMMER / HUMAnN 3 / assembly + dbCAN3 / CARD | unbound |
FLUX, METAB, MODEL |
flux_predicted / external_measured / model_output | AGORA2 / metabolomics file / frozen container | unbound |
Evidence maturity — how far the research has come, P0 to P5:
| P0 | animal, case report, or mechanistic hypothesis only |
| P1 | one small human cohort, amplicon-only, or inaccessible individual data |
| P2 | usable human shotgun cohort, or multiple compatible human association cohorts |
| P3 | independent human replication with coherent task and assay |
| P4 | external population validation with a frozen model and proper participant split |
| P5 | prospective intended-use validation with calibrated clinical performance |
Nothing in the library is above P3. The report prints the grade beside every score.
Assay transport — whether the source study measured what this pipeline
measures. native means shotgun species or genes. amplicon_taxon_to_shotgun
means a 16S genus-level finding carried onto shotgun species, and is the only
way a genus-level feature is accepted (below). predicted_to_measured means a
PICRUSt inference tested against genes actually counted.
Study modules and fusion. A v3 profile is a set of modules, one per
independent published cohort, each carrying a study_group. Modules that share
participants share one group. Fusion is study_average: independent groups are
averaged with equal weight, so a study contributing twenty correlated taxa
cannot outweigh a study contributing one replicated feature. sensitivity_panel
and phenotype_panel modules are scored and shown but never fused. The three
legacy profiles (crc, mecfs, longcovid) keep their taxonomic /
functional / ecological split with the documented 50/35/15 weights.
Scoring¶
1 — Per-feature robust value, against the matched reference only:
d_i is +1 for a reported increase and −1 for a decrease, so v_i runs from
−1 (opposite) to +1 (strongly concordant). Zero-inflated features (carried by
under 80% of the reference) use a prevalence-aware rank instead: absence is a
category, not a small number, because the CLR of an absent taxon carries only
the denominator's noise. Median and MAD, not mean and SD, because abundance
distributions are skewed enough that one outlier otherwise sets the scale.
Centred log-ratio, because relative abundances are compositional.
Genus-level and carrier features are the log-ratio of a sum of species against the same prevalent-core frame, computed identically for the sample and for every reference sample.
2 — Module aggregation.
w is the evidence weight. The three other factors every feature carries —
q cohort independence, s disease specificity, c cross-study direction
agreement — are recorded for audit and printed in the decomposition table,
not multiplied into the score. Multiplying them made every profile's number
depend on four curator judgements at once; the v3 contract keeps them visible
and keeps the score simple.
3 — Percentile. Every reference sample is scored through the identical path and the sample is ranked against that null. Never by rescaling the raw value. A bootstrap over the reference gives a likely range (the report's "likely 71–100").
4 — Fusion, as declared by the profile (study_average or the legacy
weighted split).
Two rules the loader enforces¶
Genus level is conditional. Aggregating a genus reverses direction in
practice: genus Faecalibacterium has been reported higher in a cohort where
F. prausnitzii was lower. So a genus feature is accepted only when the
module declares assay_transport: amplicon_taxon_to_shotgun — the source could
not have named the species — and, for the conflicted genera
(Faecalibacterium, Streptococcus, Veillonella, Prevotella, Blautia,
Lachnospiraceae, Alistipes, Bacteroides, Dorea), only when it also
declares direction_conflict: material. Shotgun-derived genus evidence is
never accepted: the study could have named the species and did not.
Every feature carries all four factors and a source. A feature without them cannot be audited, so it is not accepted.
Confidence is a vector, not a multiplier¶
Beside every score the report prints, and never folds into the number:
| Dimension | Answers |
|---|---|
| technical reliability | depth, host fraction, reference match, profiler-version agreement |
| independent feature coverage | share of the pattern's independent evidence clusters this sample could measure |
| evidence maturity | the P-grade |
| assay transportability | native / transported |
| population match | how well the matched reference resembles the subject |
| specificity | empirical (challenge-cohort AUROC, where measured) or the literature-uniqueness prior |
| out-of-distribution | whether the sample sits outside the reference for the features used |
| direction conflict | none / documented / material |
| interval width | the bootstrap range |
A weak row means "less certain", not "lower".
Shape of the result (spec 7.8)¶
Thirty percentiles are not thirty findings. After every profile is scored the library is read as a whole:
- quiet — nothing above the 75th percentile (the report's typical band)
- specific — one or two profiles above it, with distinctive features
- diffuse — a large fraction above it, resting on shared features (butyrate-producer loss, oral-taxa gain); the general dysbiosis index is the headline, not any disease
- mixed — several above it with partial specificity
Each scored profile also lists its competing profiles (the next-highest from other families) and the top-two margin, so a 90th-percentile result two points ahead of its neighbour reads as what it is.
Specificity is empirical where the challenge-cohort matrix in
docs/profile_validation.json covers the profile (worst off-target AUROC
against its own), and otherwise the labelled literature-uniqueness prior:
the mean over the profile's features of 1 / (number of profiles sharing that
feature). The report always says which one it used.
The dysbiosis anchor¶
GMWI2 runs on every sample and is reported beside every profile score. If the
anchor is strongly negative the community is generally disturbed and a high
score on any profile probably reflects that. The 95 published coefficients are
stored verbatim in openbiota/data/gmwi2_model.json; tests/test_dysbiosis.py
reproduces the authors' worked example to four decimal places.
Abstention and the confounder ledger (spec 12)¶
A refused score is more useful than a confident wrong one. Profiles abstain when:
- broad-spectrum antibiotics fall inside the declared window (90 days)
- usable non-host pairs fall below 500,000
- required metadata is missing —
t2dneeds metformin status,celiacneeds gluten-free-diet status,androgenetic_alopecianeeds sex - a
mandatory_matchfield (age band, sex) cannot be matched in the reference
An abstaining profile renders the reasons and what would change them. Beside the library the report prints a confounder ledger: what was known about the subject when scoring (antibiotics, metformin, PPI, gluten-free diet, country, age, sex, stool form, hospitalisation, kidney function, medications, sequencing batch from the FASTQ headers), what was missing and what it would have changed, and which profiles abstained because of it.
Opt-in profiles. The mechanism exists — a profile marked opt_in: true
is scored only with --include-opt-in — but no profile in the shipped library
uses it. mdd did until the transfer evidence was reviewed: patient stool has
induced depression-like behaviour in germ-free mice and in microbiota-depleted
rats, so the pattern is measured and reported like every other one, under the
same caveat that a percentile is resemblance and not a diagnosis.
Reference contrasts¶
Profiles need two contrasts: people with the same exposure who did not
develop the syndrome (primary), and general healthy adults matched on the
non-exposure variables (secondary). For ME/CFS and Long COVID the primary
contrast does not exist in the published cohorts; both profiles declare
primary: source: null, say so in the report, and take a confidence penalty.
Adding a profile¶
Drop a YAML file in profiles/. The loader checks:
disease,task,body_site,population,evidence_maturity- semantic
version— changing any weight bumps it - every module has an
evidence_type, astudy_group, anassay_transportand amodule_type - every feature has
direction,w q s cin [0, 1], alevel, asource - genus features obey the transport rule above
stratify_onnames a subject field;mandatory_matchfields existchallenge_fornames profiles that exist- cross-engine checks name features that exist
profiles/crohns.yaml is the fullest v3 example (seven study modules,
carrier features, an amplicon-transported module, challenge declarations);
profiles/mecfs.yaml the fullest legacy one (duration strata, cross-engine
check, absent primary contrast).
Sources¶
Every profile carries its citations inline, per feature and at the profile
level; openbiota profiles --show <name> --json prints them all. Method sources:
- Compositional data: Gloor et al., Front Microbiol 2017;8:2224, doi:10.3389/fmicb.2017.02224
- GMWI2: Chang & Gupta et al., Nat Commun 2024;15:7447, doi:10.1038/s41467-024-51651-9
- MetaPhlAn: Blanco-Míguez et al., Nat Biotechnol 2023, doi:10.1038/s41587-023-01688-w
- curatedMetagenomicData: Pasolli et al., Nat Methods 2017;14:1023–1024, doi:10.1038/nmeth.4468
- Colorectal cancer: Wirbel et al., Nat Med 2019;25:679–689; Thomas et al., Nat Med 2019;25:667–678
- ME/CFS: Guo et al. and Xiong et al., Cell Host Microbe 2023;31
- Long COVID: Liu et al., Gut 2022;71:544–552; Su et al., Cell Host Microbe 2024;32:651–660
Measured performance and limitations: VALIDATION.md.