|
| 1 | +# Host species fill — alternatives + chosen strategy |
| 2 | + |
| 3 | +## Problem |
| 4 | + |
| 5 | +`annotated_hits.tsv` carries no host info. BFVD reference tables |
| 6 | +(`bfvd/`) carry virus taxonomy but no host either. Need |
| 7 | +`taxid → host_group` mapping for UMAP-by-host plot. |
| 8 | + |
| 9 | +## Definition of `host_group` |
| 10 | + |
| 11 | +Coarse buckets that compress 23,614 viral taxids into ~10 categories |
| 12 | +useful for visual stratification: |
| 13 | + |
| 14 | +| host_group | examples | |
| 15 | +|---|---| |
| 16 | +| `human` | HIV, HSV, HPV, SARS-CoV-2, common-cold coronaviruses | |
| 17 | +| `vertebrate_nonhuman` | bat coronaviruses, avian influenza, fish iridoviruses | |
| 18 | +| `arthropod` | insect baculoviruses, mosquito-vectored viruses (vector not host of replication) | |
| 19 | +| `plant` | TMV, plant geminiviruses | |
| 20 | +| `fungus` | mycoviruses | |
| 21 | +| `protist` | algal viruses, mimivirus host *Acanthamoeba* | |
| 22 | +| `bacteria` | bacteriophages (Caudoviricetes, Microviridae, etc.) | |
| 23 | +| `archaea` | archaeal viruses | |
| 24 | +| `metazoan_other` | nematodes, molluscs (abalone herpesvirus) | |
| 25 | +| `unknown` | uncharacterized environmental virus | |
| 26 | + |
| 27 | +`host_organism` retained as free-text alongside (e.g. "Homo sapiens", |
| 28 | +"Gordonia bronchialis") for hover-text in interactive plots. |
| 29 | + |
| 30 | +## Source ranking — best-first |
| 31 | + |
| 32 | +Use a layered fill: each layer fills any taxid the previous left |
| 33 | +unknown, with `host_source` recording which layer landed each value. |
| 34 | + |
| 35 | +### 1. ICTV Virus Metadata Resource (VMR) — primary |
| 36 | + |
| 37 | +- Single authoritative table per ICTV release (MSL40 current as of 2026). |
| 38 | +- Columns include `Host source` (human-curated) at species / genus / family granularity. |
| 39 | +- Pull URL: `https://ictv.global/vmr/current` → CSV → ~17k rows mapping ICTV taxon → host source. |
| 40 | +- **Limit:** ICTV taxonomy ≠ NCBI taxid. Need ICTV name → NCBI taxid bridge. |
| 41 | + Two paths: |
| 42 | + - Use ICTV's `Genome composition` + `Virus name(s)` to fuzzy-match to NCBI taxonomy names (provided in BFVD lineage already). |
| 43 | + - Use `ictv-taxonomy-id` field in VMR (if released after MSL38, which carries NCBI taxid for ~80% of entries). |
| 44 | +- Expected coverage: 60-75% of BFVD taxids hit ICTV exactly at species or genus level. |
| 45 | + |
| 46 | +### 2. UniProt REST `organism_host` — secondary |
| 47 | + |
| 48 | +- Each viral UniProt entry has an `Organism host` cross-reference (when |
| 49 | + characterized). Query API at |
| 50 | + `https://rest.uniprot.org/uniprotkb/{accession}.json?fields=organism_host`. |
| 51 | +- Coverage on BFVD: estimated 30-50% (many BFVD entries are uncharacterized |
| 52 | + metagenome predictions where UniProt has no host annotation). |
| 53 | +- For the unique 347k uniprots in BFVD, this is ~70k REST calls if |
| 54 | + batched (UniProt allows 500 ids per stream/search query → ~700 calls |
| 55 | + with rate-limit pause). Cacheable as `refs/uniprot_host.parquet`. |
| 56 | + |
| 57 | +### 3. NCBI Taxonomy host field — tertiary |
| 58 | + |
| 59 | +- NCBI taxonomy entries carry `host` in the dataset (efetch from |
| 60 | + `taxonomy` db). Coverage similar to UniProt but for the taxid (not |
| 61 | + uniprot) — fills viruses where the species is known but the UniProt |
| 62 | + entry is bare. |
| 63 | +- ~24k taxids → 24k efetch calls (cacheable; batched in groups of 200). |
| 64 | + |
| 65 | +### 4. Rule-based by lineage — quaternary |
| 66 | + |
| 67 | +- Sweep remaining unknowns using BFVD lineage we already have. |
| 68 | + Mapping rules from clade → host_group: |
| 69 | + |
| 70 | + ``` |
| 71 | + class Caudoviricetes → bacteria |
| 72 | + family Microviridae → bacteria |
| 73 | + family Inoviridae → bacteria |
| 74 | + family Tectiviridae → bacteria |
| 75 | + family Plasmaviridae → bacteria |
| 76 | + family Corticoviridae → bacteria |
| 77 | + family Sphaerolipoviridae → bacteria / archaea (mostly bacteria; flag dual) |
| 78 | + family Fuselloviridae → archaea |
| 79 | + family Rudiviridae → archaea |
| 80 | + family Lipothrixviridae → archaea |
| 81 | + family Globuloviridae → archaea |
| 82 | + family Ampullaviridae → archaea |
| 83 | + family Bicaudaviridae → archaea |
| 84 | + family Salterprovirus → archaea |
| 85 | + order Geplafuvirales → plant |
| 86 | + family Geminiviridae → plant |
| 87 | + family Caulimoviridae → plant |
| 88 | + family Bromoviridae → plant |
| 89 | + family Closteroviridae → plant |
| 90 | + family Tymoviridae → plant |
| 91 | + family Tobamoviridae → plant |
| 92 | + family Virgaviridae → plant |
| 93 | + family Mimiviridae → protist (Acanthamoeba) |
| 94 | + family Marseilleviridae → protist |
| 95 | + family Phycodnaviridae → protist (algae) |
| 96 | + family Pithoviridae → protist |
| 97 | + family Asfarviridae → vertebrate_nonhuman (mostly suid) |
| 98 | + family Iridoviridae → vertebrate_nonhuman + arthropod (flag mixed) |
| 99 | + family Baculoviridae → arthropod |
| 100 | + family Polydnaviridae → arthropod |
| 101 | + family Nudiviridae → arthropod |
| 102 | + family Hytrosaviridae → arthropod |
| 103 | + family Hytrosaviridae → arthropod |
| 104 | + family Partitiviridae → fungus / plant (flag mixed) |
| 105 | + family Totiviridae → fungus / protist (flag mixed) |
| 106 | + family Hypoviridae → fungus |
| 107 | + family Polyomaviridae → vertebrate_nonhuman (mostly mammals; human via taxid override) |
| 108 | + family Papillomaviridae → vertebrate_nonhuman (mostly mammals; human via taxid override) |
| 109 | + family Herpesviridae → vertebrate_nonhuman (human via taxid override) |
| 110 | + family Coronaviridae → vertebrate_nonhuman (human via taxid override) |
| 111 | + family Flaviviridae → vertebrate_nonhuman + arthropod (vector; flag) |
| 112 | + family Filoviridae → vertebrate_nonhuman (human via taxid override) |
| 113 | + family Retroviridae → vertebrate_nonhuman (human via taxid override) |
| 114 | + ``` |
| 115 | + |
| 116 | +- After-rule sweep, force any taxid in NCBI `Viruses_human` curated |
| 117 | + list → `host_group = human` (overrides family default). |
| 118 | + |
| 119 | +### 5. Scientific-name pattern match — last resort |
| 120 | + |
| 121 | +- BFVD's scientific name often embeds the host: `Gordonia phage Dardanus`, |
| 122 | + `Abalone herpesvirus`, `Acanthamoeba polyphaga mimivirus`. Regex: |
| 123 | + - `phage` or `prophage` → bacteria |
| 124 | + - First word is a known prokaryote genus → bacteria (via NCBI taxonomy |
| 125 | + dump cross-check) |
| 126 | + - First word ends in `virus` and is preceded by a host species name → |
| 127 | + derive host_organism from preceding tokens |
| 128 | +- This catches an estimated 20-30% of remaining unknowns. Tagged |
| 129 | + `host_source = name_regex` so we can downweight in any quantitative |
| 130 | + analysis. |
| 131 | + |
| 132 | +## Alternative sources NOT used (and why) |
| 133 | + |
| 134 | +- **ViralZone (Expasy)** — hand-curated, web-only, no bulk download. |
| 135 | + Useful for spot-checks of high-interest viruses, not bulk fill. |
| 136 | +- **NCBI Virus** (the portal, not the taxdump) — overlaps with NCBI |
| 137 | + taxonomy host field; portal API is rate-limited and intended for |
| 138 | + interactive use. |
| 139 | +- **CHVD / IMG/VR / GOV2** — environmental virus catalogs with host |
| 140 | + prediction. Useful if our novel hits cluster around uncharacterized |
| 141 | + BFVD entries; would attach via target uniprot → environmental virus |
| 142 | + catalog ID → predicted host. Out of scope for v1. |
| 143 | +- **CRISPR-spacer-based host prediction** (e.g. iPHoP, PHIST) — strongest |
| 144 | + predictor for phages whose host has CRISPR records. Worth running on |
| 145 | + the BFVD subset that fails layers 1-5; deferred to a separate task |
| 146 | + since it requires downloading several large reference DBs. |
| 147 | +- **Sequence-similarity-based host transfer** (BLAST our query against |
| 148 | + a host-tagged virus DB, transfer host of nearest neighbor) — circular |
| 149 | + for our use case (we'd be using the same hits we're trying to label). |
| 150 | + |
| 151 | +## Cost of layers 1-3 |
| 152 | + |
| 153 | +| Layer | API calls | Wall time (single-thread) | Cache reuse | |
| 154 | +|---|---|---|---| |
| 155 | +| 1 ICTV VMR | 1 (CSV download) | 5 s | Forever | |
| 156 | +| 2 UniProt REST | ~700 batched queries | ~30 min (with rate-limit) | Per uniprot | |
| 157 | +| 3 NCBI efetch | ~120 batches of 200 | ~10 min | Per taxid | |
| 158 | + |
| 159 | +All caches stored under `refs/cache/` as parquet; only refetch on |
| 160 | +explicit `--refresh-cache`. |
| 161 | + |
| 162 | +## Expected final coverage |
| 163 | + |
| 164 | +| Source layer | Estimated cumulative coverage | |
| 165 | +|---|---| |
| 166 | +| ICTV VMR | 60-75% | |
| 167 | +| + UniProt host | 75-85% | |
| 168 | +| + NCBI taxonomy host | 80-88% | |
| 169 | +| + Rule-based by lineage | 92-97% | |
| 170 | +| + Name regex | 95-99% | |
| 171 | +| `unknown` residual | 1-5% | |
| 172 | + |
| 173 | +All `unknown` entries plot as gray in the host UMAP and are excluded |
| 174 | +from host-stratified abundance bars (counted separately). |
| 175 | + |
| 176 | +## Audit trail |
| 177 | + |
| 178 | +`host_fill_audit.tsv` columns: |
| 179 | +``` |
| 180 | +taxid, scientific_name, family, genus, host_group, host_organism, |
| 181 | +host_source, host_confidence |
| 182 | +``` |
| 183 | + |
| 184 | +`host_confidence` ∈ {`high`, `medium`, `low`}: |
| 185 | +- `high` = layers 1-3 (curated) |
| 186 | +- `medium` = layer 4 (rule by lineage) |
| 187 | +- `low` = layer 5 (name regex) |
| 188 | + |
| 189 | +Plots in `out/` can be regenerated against `host_confidence ≥ medium` |
| 190 | +to drop name-regex entries when reviewer wants conservative figures. |
| 191 | + |
| 192 | +## Chosen v1 scope |
| 193 | + |
| 194 | +Implement layers 1, 4, 5 first (zero cost, fastest signal). Add |
| 195 | +layers 2 + 3 once layers 1+4+5 leave a residual we can quantify. This |
| 196 | +keeps `make refs` fast for iteration and avoids burning UniProt / |
| 197 | +NCBI quota during dev. |
0 commit comments