feat: add an opt-in MyGene.info backend for the Ensembl pull - #976
Open
SkyeAv wants to merge 3 commits into
Open
feat: add an opt-in MyGene.info backend for the Ensembl pull#976SkyeAv wants to merge 3 commits into
SkyeAv wants to merge 3 commits into
Conversation
The BioMart harvest (src/datahandlers/ensembl.py) queries every Ensembl species dataset (200+), which is slow, flaky, and impractical on a machine that cannot run a long network harvest. Add src/datahandlers/ensembl_mygene.py, which pulls only the well-covered model organisms from the MyGene.info BioThings API (a registered Translator KP) via a scrolling query - no bulk download. It writes the same ENSEMBL/<dataset>/BioMart.tsv artifacts (BioMart display-header columns) so write_ensembl_gene_ids / write_ensembl_protein_ids work unchanged. Handles MyGene's str-or-list fields, the dict-or-list-of-dicts ensembl shape (proteins scoped per entry), and strips the MGI: prefix MyGene adds (avoiding a MGI:MGI:... double prefix). Each dataset is written atomically (.part + os.replace) so a mid-pull failure can never poison a later run. Selected by config ensembl_source (default biomart, unchanged) + ensembl_mygene_taxa. Yeast/dicty stay on BioMart (MyGene coverage is near-zero). 38 offline unit tests (incl. a round-trip through the real consumers) over committed real fixtures, plus 2 network smoke tests.
Document both backends and the MyGene field mapping/coverage, correct the attribute-limit description (the limit is on external-reference attributes), add the Ensembl release-116 / July-2026 legacy-platform retirement caveat, and record two findings: the MGI double-prefix trap, and that build_gene_ensembl_relationships renders prefixes as Python sets but is dormant (gene/concords/ENSEMBL is not in config gene_concords, so it is never consumed).
astral-sh/ruff-action@v3 floats to the latest ruff, now 0.16.0 (pyproject pins only a floor, >=0.14.14). Ruff 0.16.0 formats Python code fences inside *.md, which overlaps with the dedicated rumdl Markdown check and was failing 'Check Python formatting with ruff' on every open PR. Exclude *.md from ruff format so ruff stays scoped to Python and Markdown formatting CI is deterministic across ruff releases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an opt-in MyGene.info backend for the Ensembl pull. The existing BioMart harvest
(
src/datahandlers/ensembl.py) queries every Ensembl species dataset (200+), which is slow,flaky (config already skips a "stuck" dataset), and impractical on a machine that cannot run a long
network harvest. The new backend pulls only the well-covered model organisms from the MyGene.info
BioThings API — a registered Translator Knowledge Provider — via a scrolling query, with no bulk
download.
MyGene backend
src/datahandlers/ensembl_mygene.py(pull_ensembl_via_mygene) pages MyGene withfetch_all/scroll_idand writes the sameENSEMBL/<dataset>/BioMart.tsvartifacts (BioMartdisplay-header columns), so
write_ensembl_gene_ids/write_ensembl_protein_idswork unchanged.config.yamlensembl_source(defaultbiomart, unchanged) andensembl_mygene_taxa; dispatched in theget_ensemblrule (src/snakefiles/datacollect.snakefile).Production behavior is untouched unless the default is flipped.
(0) are near-empty in MyGene and stay on BioMart; MyGene has no SGD field.
Correctness traps handled
ensembl.protein/ensembl.geneas a scalar or a list,and
ensemblitself can be a list of dicts (zebrafish) — proteins are kept scoped to their owngene entry, not pooled.
MGI:3704398) but the downstream consumerprepends
MGI:itself; the handler strips a leadingMGI:to avoidMGI:MGI:3704398.BioMart.tsv.partthenos.replaced ontoBioMart.tsvonly after the whole taxon is pulled, so a mid-pull failure can never leave a partialfile that a later run mistakes for complete (a reviewer reproduced that data-loss path; it is
regression-tested).
Design
ensembl_sourcechanges gene/protein clique membershipand should be validated with a source-impact report + clique diff on a cluster build first.
Deferred: switching the default; a full species pull smoke-test on the cluster.
http_get(url, params) -> dict,so the parsing/paging core runs against committed real fixtures (
tests/data/ensembl_mygene/,captured verbatim, each named by its gene id).
Docs
docs/sources/ENSEMBL/Download.md: documents both backends and the MyGene fieldmapping/coverage, corrects the attribute-limit description (the limit is on external-reference
attributes), and adds the Ensembl release-116 / July-2026 legacy-platform retirement caveat.
Notes (not fixed here)
gene.build_gene_ensembl_relationshipsrenders prefixes as Python sets ({'NCBIGene'}:1017),but this is dormant:
gene/concords/ENSEMBLis not inconfig.yaml gene_concords, sogene_compendianever consumes it (the live Ensembl↔NCBIGene linkage comes fromNCBIGeneENSEMBL/gene2ensembl.gz). Pinned by a test with invert instructions; worth its own issue if it should go live.Testing
uv run pytest -m unit tests/datahandlers/test_ensembl_mygene.py -q→38 passed, 2 deselected(includes a round-trip through the real
write_ensembl_gene_ids/write_ensembl_protein_ids/build_gene_ensembl_relationships).uv run pytest -m network --network tests/datahandlers/test_ensembl_mygene.py -q→2 passed(live MyGene smoke tests, incl. a real
fetch_all→scroll_idhandshake).uv run pytest -m unit -q(full CI gate) →440 passed.uv run ruff check/uv run ruff format --check/uv run snakefmt --check/uv run rumdl check→ all clean.
uv run snakemake -c1 get_ensembl -n→ DAG builds (exit 0).Questions for the reviewer
ensembl_source: mygeneever become the default, or stay a dev/partialoption (it cannot cover yeast/dicty)? I left it opt-in pending a cluster impact report.