Download refresh_common_names.py from HuggingFaceBio/carbon-a-database-explorer: direct link, hf CLI and curl.
- Browser
- Download file 13.6 kB
-
https://huggingface.co/spaces/HuggingFaceBio/carbon-a-database-explorer/resolve/main/refresh_common_names.py
- Command line
-
hf download hf://spaces/HuggingFaceBio/carbon-a-database-explorer/refresh_common_names.py
-
curl -L -o refresh_common_names.py https://huggingface.co/spaces/HuggingFaceBio/carbon-a-database-explorer/resolve/main/refresh_common_names.py
13.6 kB
| """Build the English name lookup used by the Genome Atlas labels. | |
| Two sources are merged, curated names winning over NCBI: | |
| * NCBI Taxonomy ``names.dmp`` supplies ``genbank common name`` and ``common name`` | |
| for roughly 9,000 taxa, almost all of them species, genera and familiar classes. | |
| * A curated table below covers the large unranked clades that NCBI leaves | |
| unnamed. These are exactly the groups the atlas shows first — Opisthokonta, | |
| Eumetazoa, Ecdysozoa and their kin — so without them the top of the tree reads | |
| as untranslated Latin. | |
| Curated glosses are short, lower-case noun phrases describing the living members | |
| of the clade. They are plain-language summaries, not formal synonyms; the | |
| scientific name stays the primary label everywhere in the interface. | |
| """ | |
| import argparse | |
| from collections import Counter | |
| from datetime import datetime, timezone | |
| import json | |
| from pathlib import Path | |
| import sqlite3 | |
| import tarfile | |
| ROOT = Path(__file__).resolve().parent | |
| NAME_CLASSES = ("genbank common name", "common name") | |
| # taxid: (scientific name, English gloss). The scientific name is verified | |
| # against the snapshot so a wrong taxid fails the build instead of mislabelling | |
| # a clade. | |
| CURATED = { | |
| 2698737: ("Sar", "marine algae and protists"), | |
| 554915: ("Amoebozoa", "amoebas"), | |
| 2611352: ("Discoba", "flagellate protists"), | |
| 33682: ("Euglenozoa", "euglenids and trypanosomes"), | |
| 2704647: ("Metakinetoplastina", "trypanosomes and kin"), | |
| 2696291: ("Ochrophyta", "brown algae and diatoms"), | |
| 431838: ("Intramacronucleata", "ciliates"), | |
| 422676: ("Aconoidasida", "malaria parasites and kin"), | |
| 1280412: ("Conoidasida", "gut parasites"), | |
| 2692248: ("core chlorophytes", "green algae"), | |
| 3166: ("Chlorophyceae", "green algae"), | |
| 75966: ("Trebouxiophyceae", "green algae"), | |
| 1035538: ("Mamiellophyceae", "tiny marine green algae"), | |
| 13792: ("Mamiellales", "tiny marine green algae"), | |
| 127916: ("Ichthyosporea", "parasites of fish and kin"), | |
| 2687318: ("Filasterea", "single-celled animal kin"), | |
| 2686024: ("Rotosphaerida", "amoeboid protists"), | |
| 6042: ("Demospongiae", "common sponges"), | |
| 1913637: ("Mucoromycota", "bread moulds and kin"), | |
| 451507: ("Mucoromycotina", "bread moulds"), | |
| 3704128: ("Kickxellomycota", "thread-like fungi"), | |
| 112252: ("Fungi incertae sedis", "fungi of uncertain position"), | |
| 33154: ("Opisthokonta", "animals and fungi"), | |
| 6072: ("Eumetazoa", "animals with true tissues"), | |
| 33213: ("Bilateria", "two-sided animals"), | |
| 33317: ("Protostomia", "mouth-first animals"), | |
| 1206794: ("Ecdysozoa", "moulting animals"), | |
| 2697495: ("Spiralia", "spiral-cleaving animals"), | |
| 1206795: ("Lophotrochozoa", "molluscs, worms and kin"), | |
| 88770: ("Panarthropoda", "arthropods and kin"), | |
| 3701028: ("Altocrustacea", "crustaceans and insects"), | |
| 3701030: ("Allotriocarida", "insects and some crustaceans"), | |
| 85512: ("Dicondylia", "most insects"), | |
| 33340: ("Neoptera", "wing-folding insects"), | |
| 33342: ("Paraneoptera", "bugs, lice and thrips"), | |
| 3701061: ("Eumetabola", "advanced insects"), | |
| 33392: ("Endopterygota", "insects with metamorphosis"), | |
| 3701062: ("Aparaglossata", "most metamorphic insects"), | |
| 3701063: ("Panorpida", "flies, moths and kin"), | |
| 3701064: ("Neuropteroidea", "beetles and lacewings"), | |
| 41084: ("Polyphaga", "most beetles"), | |
| 41088: ("Cucujiformia", "plant-eating beetles"), | |
| 7434: ("Aculeata", "bees, wasps and ants"), | |
| 85604: ("Amphiesmenoptera", "moths and caddisflies"), | |
| 41191: ("Glossata", "moths and butterflies"), | |
| 41196: ("Neolepidoptera", "moths and butterflies"), | |
| 41197: ("Heteroneura", "moths and butterflies"), | |
| 37567: ("Ditrysia", "most moths and butterflies"), | |
| 104430: ("Apoditrysia", "moths and butterflies"), | |
| 104431: ("Obtectomera", "macro-moths and butterflies"), | |
| 37570: ("Noctuoidea", "owlet moths"), | |
| 40092: ("Hesperioidea", "skipper butterflies"), | |
| 37568: ("Tortricoidea", "leafroller moths"), | |
| 7139: ("Tortricidae", "leafroller moths"), | |
| 7203: ("Brachycera", "short-horned flies"), | |
| 480118: ("Eremoneura", "advanced flies"), | |
| 480117: ("Cyclorrhapha", "advanced flies"), | |
| 43733: ("Muscomorpha", "house flies and kin"), | |
| 43738: ("Schizophora", "advanced flies"), | |
| 43741: ("Acalyptratae", "small flies"), | |
| 43746: ("Ephydroidea", "fruit flies and kin"), | |
| 43845: ("Drosophilinae", "fruit flies"), | |
| 46877: ("Drosophilini", "fruit flies"), | |
| 119089: ("Chromadorea", "roundworms"), | |
| 6236: ("Rhabditida", "roundworms"), | |
| 89593: ("Craniata", "animals with a skull"), | |
| 117570: ("Teleostomi", "jawed vertebrates with bone"), | |
| 8287: ("Sarcopterygii", "lobe-finned fish and kin"), | |
| 1338369: ("Dipnotetrapodomorpha", "lungfish and tetrapods"), | |
| 186623: ("Actinopteri", "ray-finned fish"), | |
| 41665: ("Neopterygii", "modern ray-finned fish"), | |
| 1489341: ("Osteoglossocephalai", "bony-tongued fish and kin"), | |
| 186625: ("Clupeocephala", "most teleost fish"), | |
| 1489388: ("Euteleosteomorpha", "advanced teleost fish"), | |
| 123365: ("Neoteleostei", "advanced bony fish"), | |
| 123366: ("Eurypterygia", "advanced bony fish"), | |
| 123367: ("Ctenosquamata", "advanced bony fish"), | |
| 123368: ("Acanthomorphata", "spiny-rayed fish"), | |
| 123369: ("Euacanthomorphacea", "spiny-rayed fish"), | |
| 1489872: ("Percomorphaceae", "perch-like fish"), | |
| 1489922: ("Eupercaria", "perch-like fish"), | |
| 1489908: ("Ovalentaria", "cichlids and relatives"), | |
| 1489910: ("Cichlomorphae", "cichlids and kin"), | |
| 318546: ("Pseudocrenilabrinae", "African cichlids"), | |
| 186634: ("Otomorpha", "carps, catfish and herrings"), | |
| 32519: ("Ostariophysi", "carps and catfish"), | |
| 186626: ("Otophysi", "carps and catfish"), | |
| 186627: ("Cypriniphysae", "carps and loaches"), | |
| 1329799: ("Archelosauria", "turtles, birds, crocodiles"), | |
| 8492: ("Archosauria", "birds and crocodiles"), | |
| 436489: ("Saurischia", "dinosaurs, birds today"), | |
| 436491: ("Theropoda", "dinosaurs, birds today"), | |
| 436492: ("Coelurosauria", "dinosaurs, birds today"), | |
| 8825: ("Neognathae", "most modern birds"), | |
| 3078114: ("Neoaves", "most modern birds"), | |
| 3073809: ("Australaves", "parrots and songbirds"), | |
| 1329950: ("Unidentata", "lizards and snakes"), | |
| 1329912: ("Episquamata", "lizards and snakes"), | |
| 32525: ("Theria", "live-bearing mammals"), | |
| 1437010: ("Boreoeutheria", "most placental mammals"), | |
| 314146: ("Euarchontoglires", "primates and rodents"), | |
| 314145: ("Laurasiatheria", "carnivores, bats, ungulates"), | |
| 376913: ("Haplorrhini", "monkeys, apes and tarsiers"), | |
| 314293: ("Simiiformes", "monkeys and apes"), | |
| 9526: ("Catarrhini", "Old World monkeys and apes"), | |
| 207598: ("Homininae", "great apes and humans"), | |
| 9845: ("Ruminantia", "ruminants"), | |
| 35500: ("Pecora", "deer, cattle and kin"), | |
| 9895: ("Bovidae", "cattle, sheep and antelope"), | |
| 451864: ("Dikarya", "higher fungi"), | |
| 716545: ("saccharomyceta", "yeasts and sac fungi"), | |
| 716546: ("leotiomyceta", "filamentous sac fungi"), | |
| 715989: ("sordariomyceta", "flask fungi and kin"), | |
| 1520881: ("OSLEUM clade", "filamentous sac fungi"), | |
| 147550: ("Sordariomycetes", "flask fungi"), | |
| 222544: ("Sordariomycetidae", "flask fungi"), | |
| 5139: ("Sordariales", "flask fungi"), | |
| 222543: ("Hypocreomycetidae", "mould-forming sac fungi"), | |
| 5125: ("Hypocreales", "moulds and insect fungi"), | |
| 110618: ("Nectriaceae", "Fusarium and relatives"), | |
| 474943: ("Cordycipitaceae", "insect-killing fungi"), | |
| 1028384: ("Glomerellales", "anthracnose fungi"), | |
| 681950: ("Glomerellaceae", "anthracnose fungi"), | |
| 5455: ("Colletotrichum", "anthracnose fungi"), | |
| 639021: ("Magnaporthales", "rice blast fungi"), | |
| 2528436: ("Pyriculariaceae", "rice blast fungi"), | |
| 48558: ("Pyricularia", "rice blast fungi"), | |
| 715962: ("dothideomyceta", "sooty moulds and kin"), | |
| 147541: ("Dothideomycetes", "sooty moulds and leaf fungi"), | |
| 451867: ("Dothideomycetidae", "sooty moulds"), | |
| 451868: ("Pleosporomycetidae", "leaf-spot fungi"), | |
| 92860: ("Pleosporales", "leaf-spot fungi"), | |
| 715340: ("Pleosporineae", "leaf-spot fungi"), | |
| 28556: ("Pleosporaceae", "leaf-spot fungi"), | |
| 451869: ("Botryosphaeriales", "canker fungi"), | |
| 45131: ("Botryosphaeriaceae", "canker fungi"), | |
| 35724: ("Macrophomina", "charcoal rot fungi"), | |
| 147545: ("Eurotiomycetes", "moulds and relatives"), | |
| 451871: ("Eurotiomycetidae", "moulds and relatives"), | |
| 1131492: ("Aspergillaceae", "Aspergillus and Penicillium"), | |
| 33183: ("Onygenales", "skin and hair fungi"), | |
| 147548: ("Leotiomycetes", "cup fungi and moulds"), | |
| 4891: ("Saccharomycetes", "budding yeasts"), | |
| 4892: ("Saccharomycetales", "budding yeasts"), | |
| 4893: ("Saccharomycetaceae", "baker's yeast family"), | |
| 4930: ("Saccharomyces", "baker's yeasts"), | |
| 3239874: ("Pichiomycetes", "budding yeasts"), | |
| 3243775: ("Pichiales", "budding yeasts"), | |
| 1156497: ("Pichiaceae", "budding yeasts"), | |
| 3239873: ("Dipodascomycetes", "budding yeasts"), | |
| 3243772: ("Dipodascales", "budding yeasts"), | |
| 766764: ("Debaryomycetaceae", "yeasts"), | |
| 27319: ("Metschnikowiaceae", "yeasts"), | |
| 5302: ("Agaricomycotina", "mushroom-forming fungi"), | |
| 155619: ("Agaricomycetes", "mushrooms and bracket fungi"), | |
| 452333: ("Agaricomycetidae", "mushroom-forming fungi"), | |
| 68889: ("Boletales", "boletes"), | |
| 155616: ("Tremellomycetes", "jelly fungi"), | |
| 4762: ("Oomycota", "water moulds"), | |
| 3418804: ("Peronosporomycetes", "water moulds"), | |
| 35493: ("Streptophyta", "land plants and their algae"), | |
| 131221: ("Streptophytina", "land plants and stoneworts"), | |
| 78536: ("Euphyllophyta", "ferns and seed plants"), | |
| 1437183: ("Mesangiospermae", "core flowering plants"), | |
| 1437197: ("Petrosaviidae", "most monocot plants"), | |
| 4734: ("commelinids", "grasses, palms and kin"), | |
| 38820: ("Poales", "grasses and sedges"), | |
| 147368: ("Pooideae", "temperate grasses"), | |
| 359160: ("BOP clade", "bamboo, rice, wheat grasses"), | |
| 1648038: ("Triticodae", "wheat and barley grasses"), | |
| 91827: ("Gunneridae", "core eudicot plants"), | |
| 1437201: ("Pentapetalae", "core eudicot plants"), | |
| 71275: ("rosids", "rose-related plants"), | |
| 91835: ("fabids", "legume-related plants"), | |
| 91836: ("malvids", "mallow-related plants"), | |
| 71274: ("asterids", "daisy-related plants"), | |
| 91888: ("lamiids", "mint-related plants"), | |
| 72025: ("Fabales", "legumes and kin"), | |
| 3814: ("Papilionoideae", "pea-flowered legumes"), | |
| 2231393: ("50 kb inversion clade", "legumes"), | |
| 3699: ("Brassicales", "cabbages and mustards"), | |
| 980083: ("Camelineae", "thale cress and kin"), | |
| 3701: ("Arabidopsis", "thale cresses"), | |
| 3744: ("Rosales", "roses, figs and kin"), | |
| 3524: ("Caryophyllales", "cacti, beets and kin"), | |
| 3646: ("Malpighiales", "willows and spurges"), | |
| 4069: ("Solanales", "nightshades and kin"), | |
| 4143: ("Lamiales", "mints and kin"), | |
| } | |
| def dump_rows(archive, name): | |
| with archive.extractfile(name) as stream: | |
| for line in stream: | |
| yield [part.strip() for part in line.decode("utf-8").split("|")] | |
| def build(taxdump, database, output): | |
| with sqlite3.connect(f"{Path(database).resolve().as_uri()}?mode=ro", uri=True) as conn: | |
| known = dict(conn.execute("SELECT taxid, name FROM taxa")) | |
| wrong = {t: (want, known.get(t)) for t, (want, _) in CURATED.items() if known.get(t) != want} | |
| if wrong: | |
| raise ValueError(f"Curated taxids do not match the snapshot: {wrong}") | |
| names, ranked = {}, {} | |
| with tarfile.open(taxdump, "r:gz") as archive: | |
| for row in dump_rows(archive, "names.dmp"): | |
| taxid = int(row[0]) | |
| if taxid not in known or row[3] not in NAME_CLASSES: | |
| continue | |
| rank = NAME_CLASSES.index(row[3]) | |
| if taxid not in ranked or rank < ranked[taxid]: | |
| names[taxid], ranked[taxid] = row[1], rank | |
| sources = Counter(ncbi=len(names)) | |
| for taxid, (_, english) in CURATED.items(): | |
| sources["curated_override" if taxid in names else "curated"] += 1 | |
| names[taxid] = english | |
| # A gloss that only repeats the scientific name teaches nothing (Fungi -> | |
| # "fungi"), and the interface prints the scientific name anyway. | |
| redundant = [t for t, english in names.items() if english.casefold() == known[t].casefold()] | |
| for taxid in redundant: | |
| del names[taxid] | |
| payload = {"created_at": datetime.now(timezone.utc).isoformat(), | |
| "sources": {"ncbi_taxonomy": "https://ftp.ncbi.nlm.nih.gov/pub/taxonomy/taxdump.tar.gz", | |
| "name_classes": list(NAME_CLASSES), | |
| "curated": "refresh_common_names.py, plain-language glosses for unnamed clades"}, | |
| "counts": dict(sources, redundant_dropped=len(redundant), total=len(names)), | |
| "names": {str(t): names[t] for t in sorted(names)}} | |
| Path(output).write_text(json.dumps(payload, indent=1, sort_keys=False)) | |
| print(json.dumps(payload["counts"], indent=2)) | |
| def main(): | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--taxdump", type=Path, default=ROOT / ".cache/coverage/taxdump.tar.gz") | |
| parser.add_argument("--database", type=Path, default=ROOT / "data/taxonomy.sqlite") | |
| parser.add_argument("--output", type=Path, default=ROOT / "data/common_names.json") | |
| args = parser.parse_args() | |
| build(args.taxdump, args.database, args.output) | |
| if __name__ == "__main__": | |
| main() | |