From 0fa91c0872296004f50ab77e9de4e06960462df5 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 24 Jun 2026 23:10:56 +0800 Subject: [PATCH 01/13] feat(mitocarta): new module to fetch the MitoCarta3.0 database (#118) Add `gget mitocarta` (Python API and CLI) to fetch the Broad Institute's MitoCarta3.0 inventory of mammalian mitochondrial proteins and pathways. - species: 'human' (default) or 'mouse'. - which: 'mitocarta' (default, the mitochondrial gene inventory), 'all_genes' (all genes with Maestro localization scores), or 'pathways' (the MitoPathways hierarchy and their genes). - Returns a pandas DataFrame (or list of dicts / JSON with json=True). - Adds xlrd (>=2) as a dependency to read the MitoCarta .xls workbook. - New module docs, introduction grid entry, citation, tests + fixtures. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/en/cite.md | 3 + docs/src/en/introduction.md | 9 ++- docs/src/en/mitocarta.md | 67 ++++++++++++++++ docs/src/en/updates.md | 3 + gget/__init__.py | 1 + gget/constants.py | 6 ++ gget/gget_mitocarta.py | 120 +++++++++++++++++++++++++++++ gget/main.py | 84 ++++++++++++++++++++ pyproject.toml | 1 + tests/fixtures/test_mitocarta.json | 41 ++++++++++ tests/test_mitocarta.py | 31 ++++++++ 11 files changed, 364 insertions(+), 2 deletions(-) create mode 100644 docs/src/en/mitocarta.md create mode 100644 gget/gget_mitocarta.py create mode 100644 tests/fixtures/test_mitocarta.json create mode 100644 tests/test_mitocarta.py diff --git a/docs/src/en/cite.md b/docs/src/en/cite.md index cc46ab598..538a7c931 100644 --- a/docs/src/en/cite.md +++ b/docs/src/en/cite.md @@ -67,6 +67,9 @@ Luebbert, L., & Pachter, L. (2023). Efficient querying of genomic reference data - The UniProt Consortium , UniProt: the Universal Protein Knowledgebase in 2023, Nucleic Acids Research, Volume 51, Issue D1, 6 January 2023, Pages D523–D531, [https://doi.org/10.1093/nar/gkac1052](https://doi.org/10.1093/nar/gkac1052) +- If using `gget mitocarta`, please also cite: + - Rath S, Sharma R, Gupta R, Ast T, Chan C, Durham TJ, Goodman RP, Grabarek Z, Haas ME, Hung WHW, Joshi PR, Jourdain AA, Kim SH, Kotrys AV, Lam SS, McCoy JG, Meisel JD, Miranda M, Panda A, Patgiri A, Rogers R, Sadre S, Shah H, Skinner OS, To TL, Walker MA, Wang H, Ward PS, Wengrod J, Yuan CC, Calvo SE, Mootha VK. MitoCarta3.0: an updated mitochondrial proteome now with sub-organelle localization and pathway annotations. Nucleic Acids Res. 2021 Jan 8;49(D1):D1541-D1547. doi: [10.1093/nar/gkaa1011](https://doi.org/10.1093/nar/gkaa1011). PMID: 33174596; PMCID: PMC7779016. + - If using `gget muscle`, please also cite: - Edgar RC (2021), MUSCLE v5 enables improved estimates of phylogenetic tree confidence by ensemble bootstrapping, bioRxiv 2021.06.20.449169. [https://doi.org/10.1101/2021.06.20.449169](https://doi.org/10.1101/2021.06.20.449169) diff --git a/docs/src/en/introduction.md b/docs/src/en/introduction.md index a487b6653..e546c6d88 100644 --- a/docs/src/en/introduction.md +++ b/docs/src/en/introduction.md @@ -46,18 +46,23 @@ These are the `gget` core modules. Click on any module to access detailed docume gget info
Fetch all of the information associated with an Ensembl ID. + gget mitocarta
Fetch the MitoCarta3.0 inventory of mitochondrial proteins and pathways. gget muscle
Align multiple nucleotide or amino acid sequences to each other. - gget mutate
Mutate nucleotide sequences based on specified mutations. + gget mutate
Mutate nucleotide sequences based on specified mutations. gget opentargets
Explore which diseases and drugs a gene is associated with. gget pdb
Fetch data from the Protein Data Bank (PDB) based on a PDB ID. - gget ref
Get reference genomes from Ensembl. + gget ref
Get reference genomes from Ensembl. gget search
Find Ensembl IDs associated with the specified search word. gget seq
Fetch the nucleotide or amino acid sequence of a gene. + + gget virus
Filter and fetch global viral sequences and extensive metadata. + + diff --git a/docs/src/en/mitocarta.md b/docs/src/en/mitocarta.md new file mode 100644 index 000000000..244608584 --- /dev/null +++ b/docs/src/en/mitocarta.md @@ -0,0 +1,67 @@ +[ View page source on GitHub ](https://github.com/scverse/gget/blob/main/docs/src/en/mitocarta.md) + +> Python arguments are equivalent to long-option arguments (`--arg`), unless otherwise specified. Flags are True/False arguments in Python. The manual for any gget tool can be called from the command-line using the `-h` `--help` flag. +# gget mitocarta 🫀 +Fetch the [MitoCarta3.0](https://www.broadinstitute.org/mitocarta/) inventory of mammalian mitochondrial proteins and pathways from the Broad Institute. +Return format: JSON (command-line) or data frame (Python). + +MitoCarta3.0 is a curated inventory of genes encoding proteins with strong support of mitochondrial localization, annotated with sub-mitochondrial localization and pathway membership. + +**Optional arguments** +`-s` `--species` +Species to fetch: `human` (default) or `mouse`. + +`-w` `--which` +Which table to return. Default: `mitocarta`. +`mitocarta` - The MitoCarta3.0 inventory of mitochondrial genes (one row per mitochondrial gene, with sub-mitochondrial localization, MitoPathways, evidence, and scores). +`all_genes` - All genes scored for mitochondrial localization (Maestro scores), not only the mitochondrial ones. +`pathways` - The MitoPathways hierarchy and the list of genes in each pathway. + +`-o` `--out` +Path to the file the results will be saved in, e.g. path/to/directory/results.json (or .csv). Default: Standard out. +Python: `save=True` will save the output in the current working directory. + +**Flags** +`-csv` `--csv` +Command-line only. Returns results in CSV format instead of JSON. +Python: Use `json=True` to return a list of dictionaries instead of a data frame. + +`-q` `--quiet` +Command-line only. Prevents progress information from being displayed. +Python: Use `verbose=False` to prevent progress information from being displayed. + + +### Examples + +**Fetch the human MitoCarta3.0 mitochondrial gene inventory:** +```bash +gget mitocarta --species human --csv +``` +```python +# Python +import gget +gget.mitocarta(species="human", which="mitocarta") +``` +→ Returns the ~1,100 human mitochondrial genes and their MitoCarta3.0 annotations (sub-mitochondrial localization, MitoPathways, evidence, scores). + +| HumanGeneID | Symbol | Description | MitoCarta3.0_List | MitoCarta3.0_SubMitoLocalization | MitoCarta3.0_MitoPathways | +|-------------|--------|----------------|-------------------|----------------------------------|-----------------------------------------| +| 1537 | CYC1 | cytochrome c1 | 1 | MIM | OXPHOS > Complex III assembly | +| 6390 | SDHB | ... | 1 | MIM | OXPHOS, Metabolism | + +

+ +**Fetch the MitoPathways hierarchy and their genes:** +```bash +gget mitocarta --which pathways --csv +``` +```python +# Python +gget.mitocarta(which="pathways") +``` +→ Returns the MitoPathways and the genes assigned to each pathway. + +# References +If you use `gget mitocarta` in a publication, please cite the following article: + +- Rath S, Sharma R, Gupta R, et al. MitoCarta3.0: an updated mitochondrial proteome now with sub-organelle localization and pathway annotations. Nucleic Acids Res. 2021 Jan 8;49(D1):D1541-D1547. doi: [10.1093/nar/gkaa1011](https://doi.org/10.1093/nar/gkaa1011). PMID: 33174596; PMCID: PMC7779016. diff --git a/docs/src/en/updates.md b/docs/src/en/updates.md index 89be22281..c8b2c88d9 100644 --- a/docs/src/en/updates.md +++ b/docs/src/en/updates.md @@ -5,6 +5,9 @@ #### *gget* officially became part of [*scverse*](https://scverse.org/) on June 9, 2026. 🥳🥳🥳 **Version ≥ 0.30.9** (XXX XX, 2026): +- [`gget mitocarta`](mitocarta.md): **New module** to fetch the [MitoCarta3.0](https://www.broadinstitute.org/mitocarta/) inventory of mammalian mitochondrial proteins and pathways from the Broad Institute (resolves [issue 118](https://github.com/scverse/gget/issues/118)). + - Supports human and mouse via the `species` argument; the `which` argument returns the mitochondrial gene inventory (`mitocarta`, default), all genes with Maestro localization scores (`all_genes`), or the MitoPathways hierarchy and their genes (`pathways`). + - Returns a `pandas` DataFrame (or a list of dictionaries / JSON with `json=True`). Adds `xlrd` as a dependency to read the MitoCarta Excel file. **Version ≥ 0.30.8** (Jun 28, 2026): - [`gget g2p`](g2p.md): Either `gene` or `--uniprot_id` is now sufficient — whichever is missing is resolved via UniProt and cached. Gene→UniProt picks the canonical reviewed human Swiss-Prot entry; the resolution and its limitations are logged. The canonical pair is **always** prepended to the result as `gene_name` / `uniprot_id` columns (and stored on `df.attrs`), so the output schema is invariant regardless of input mode. Existing call sites continue to work. diff --git a/gget/__init__.py b/gget/__init__.py index f56cbcddc..5b6e50603 100644 --- a/gget/__init__.py +++ b/gget/__init__.py @@ -18,6 +18,7 @@ from .gget_g2p import g2p from .gget_gpt import gpt from .gget_info import info +from .gget_mitocarta import mitocarta from .gget_muscle import muscle from .gget_mutate import mutate from .gget_opentargets import opentargets diff --git a/gget/constants.py b/gget/constants.py index 38f90119f..1de7738c5 100644 --- a/gget/constants.py +++ b/gget/constants.py @@ -17,6 +17,12 @@ # NCBI URL for gget info NCBI_URL = "https://www.ncbi.nlm.nih.gov" +# MitoCarta3.0 download URLs (Broad Institute) for gget mitocarta +MITOCARTA_URLS = { + "human": "https://personal.broadinstitute.org/scalvo/MitoCarta3.0/Human.MitoCarta3.0.xls", + "mouse": "https://personal.broadinstitute.org/scalvo/MitoCarta3.0/Mouse.MitoCarta3.0.xls", +} + # NCBI VIRUS REST API URL for gget virus - Version 2 API endpoint NCBI_API_BASE = "https://api.ncbi.nlm.nih.gov/datasets/v2" diff --git a/gget/gget_mitocarta.py b/gget/gget_mitocarta.py new file mode 100644 index 000000000..30943dd03 --- /dev/null +++ b/gget/gget_mitocarta.py @@ -0,0 +1,120 @@ +from __future__ import annotations + +import io +import json as json_package +from typing import Any + +import pandas as pd +import requests + +from .constants import DEFAULT_REQUESTS_TIMEOUT, MITOCARTA_URLS +from .utils import set_up_logger + +logger = set_up_logger() + +# Map the `which` argument to the leading character of the corresponding Excel sheet name. +# The MitoCarta3.0 workbook contains the sheets: +# "A MitoCarta3.0" -> the mitochondrial gene inventory +# "B All Genes" -> all genes with Maestro mitochondrial-localization scores +# "C MitoPathways" -> the MitoPathways hierarchy and their genes +_WHICH_TO_SHEET_PREFIX = { + "mitocarta": "A ", + "all_genes": "B ", + "pathways": "C ", +} + +# Accepted species spellings -> canonical key +_SPECIES_ALIASES = { + "human": "human", + "homo_sapiens": "human", + "homo sapiens": "human", + "mouse": "mouse", + "mus_musculus": "mouse", + "mus musculus": "mouse", +} + + +def mitocarta( + species: str = "human", + which: str = "mitocarta", + json: bool = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame | list[dict[str, Any]]: + """Fetch the MitoCarta3.0 inventory of mammalian mitochondrial proteins and pathways. + + MitoCarta3.0 (Broad Institute) is an inventory of genes encoding proteins with strong support + of mitochondrial localization, with sub-mitochondrial localization and pathway annotations. + See https://www.broadinstitute.org/mitocarta/. + + Args: + - species Species to fetch: 'human' (default) or 'mouse' + ('homo_sapiens'/'mus_musculus' are also accepted). + - which Which table to return: + 'mitocarta' (default) -> the MitoCarta3.0 inventory of mitochondrial genes. + 'all_genes' -> all genes scored for mitochondrial localization (Maestro scores). + 'pathways' -> the MitoPathways hierarchy and the genes in each pathway. + - json If True, returns a list of dictionaries instead of a pandas DataFrame (default: False). + - save If True, saves the result to 'gget_mitocarta_{species}_{which}.csv' + (or .json if json=True) in the current working directory (default: False). + - verbose True/False whether to print progress information (default: True). + + Returns the requested MitoCarta3.0 table as a pandas DataFrame (or a list of dictionaries if json=True). + """ + species_key = _SPECIES_ALIASES.get(species.lower()) + if species_key is None: + raise ValueError( + f"Species '{species}' not supported. MitoCarta3.0 is available for 'human' and 'mouse' only.\n" + ) + + if which not in _WHICH_TO_SHEET_PREFIX: + raise ValueError( + f"Argument 'which' must be one of {sorted(_WHICH_TO_SHEET_PREFIX)}, but '{which}' was passed.\n" + ) + + url = MITOCARTA_URLS[species_key] + + if verbose: + logger.info(f"Downloading MitoCarta3.0 ({species_key}) from {url} ...") + + response = requests.get(url, timeout=DEFAULT_REQUESTS_TIMEOUT) + if response.status_code != 200: + raise RuntimeError( + f"MitoCarta3.0 download returned status code {response.status_code} ({url}). Please try again.\n" + ) + + try: + excel_file = pd.ExcelFile(io.BytesIO(response.content), engine="xlrd") + except ImportError as e: + raise RuntimeError( + "Reading the MitoCarta3.0 Excel file requires the 'xlrd' package. Install it with `pip install xlrd`.\n" + ) from e + + # Resolve the sheet name by its leading character (species word differs between human/mouse) + prefix = _WHICH_TO_SHEET_PREFIX[which] + matching = [name for name in excel_file.sheet_names if name.startswith(prefix)] + if not matching: + raise RuntimeError( + f"Could not find the '{which}' sheet in the MitoCarta3.0 workbook. " + f"Available sheets: {excel_file.sheet_names}\n" + ) + sheet_name = matching[0] + + if verbose: + logger.info(f"Parsing MitoCarta3.0 sheet '{sheet_name}'.") + + df = pd.read_excel(excel_file, sheet_name=sheet_name) + + if save: + if json: + records = json_package.loads(df.to_json(orient="records", force_ascii=False)) + with open(f"gget_mitocarta_{species_key}_{which}.json", "w", encoding="utf-8") as f: + json_package.dump(records, f, ensure_ascii=False, indent=4) + else: + df.to_csv(f"gget_mitocarta_{species_key}_{which}.csv", index=False) + + if json: + result: list[dict[str, Any]] = json_package.loads(df.to_json(orient="records", force_ascii=False)) + return result + + return df diff --git a/gget/main.py b/gget/main.py index 7a2944b09..08347bd1f 100644 --- a/gget/main.py +++ b/gget/main.py @@ -33,6 +33,7 @@ from .gget_g2p import g2p # noqa: E402 from .gget_gpt import gpt # noqa: E402 from .gget_info import info # noqa: E402 +from .gget_mitocarta import mitocarta # noqa: E402 from .gget_muscle import muscle # noqa: E402 from .gget_mutate import mutate # noqa: E402 from .gget_opentargets import OPENTARGETS_RESOURCES, opentargets # noqa: E402 @@ -2292,6 +2293,66 @@ def main() -> None: ## bgee parser arguments bgee_desc = "Query the Bgee database for orthology and gene expression data using Ensembl IDs." + ## gget mitocarta subparser + mitocarta_desc = "Fetch the MitoCarta3.0 inventory of mammalian mitochondrial proteins and pathways." + parser_mitocarta = parent_subparsers.add_parser( + "mitocarta", + parents=[parent], + description=mitocarta_desc, + help=mitocarta_desc, + add_help=True, + formatter_class=CustomHelpFormatter, + ) + parser_mitocarta.add_argument( + "-s", + "--species", + type=str, + choices=["human", "mouse"], + default="human", + required=False, + help="Species to fetch: 'human' (default) or 'mouse'.", + ) + parser_mitocarta.add_argument( + "-w", + "--which", + type=str, + choices=["mitocarta", "all_genes", "pathways"], + default="mitocarta", + required=False, + help=( + "Which table to return:\n" + "'mitocarta' (default) - the MitoCarta3.0 inventory of mitochondrial genes.\n" + "'all_genes' - all genes scored for mitochondrial localization (Maestro scores).\n" + "'pathways' - the MitoPathways hierarchy and the genes in each pathway." + ), + ) + parser_mitocarta.add_argument( + "-o", + "--out", + type=str, + required=False, + help=( + "Path to the file the results will be saved in, e.g. path/to/directory/results.json.\n" + "Default: Standard out." + ), + ) + parser_mitocarta.add_argument( + "-csv", + "--csv", + default=False, + action="store_true", + required=False, + help="Returns results in csv format instead of json.", + ) + parser_mitocarta.add_argument( + "-q", + "--quiet", + default=True, + action="store_false", + required=False, + help="Does not print progress information.", + ) + parser_bgee = parent_subparsers.add_parser( "bgee", parents=[parent], @@ -3806,6 +3867,29 @@ def main() -> None: ) ## bgee return + ## mitocarta return + if args.command == "mitocarta": + mitocarta_results: pd.DataFrame = mitocarta( + species=args.species, + which=args.which, + verbose=args.quiet, + ) + + if args.out is not None and args.out != "": + directory = os.path.dirname(args.out) + if directory != "": + os.makedirs(directory, exist_ok=True) + with open(args.out, "w", encoding="utf-8") as f: + if args.csv: + mitocarta_results.to_csv(f, index=False) + else: + mitocarta_results.to_json(f, orient="records", force_ascii=False, indent=4) + else: + if args.csv: + mitocarta_results.to_csv(sys.stdout, index=False) + else: + print(mitocarta_results.to_json(orient="records", force_ascii=False, indent=4)) + if args.command == "bgee": bgee_results: pd.DataFrame = bgee( args.ens_id, diff --git a/pyproject.toml b/pyproject.toml index f36091db5..d2360c210 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ dependencies = [ "pandas>=1", "requests>=2.22", "tqdm", + "xlrd>=2", ] # Optional feature dependency for `gget cellxgene` (install: pip install gget[cellxgene]). # No wheels for the newest Python versions yet (e.g. 3.14 via tiledbsoma). diff --git a/tests/fixtures/test_mitocarta.json b/tests/fixtures/test_mitocarta.json new file mode 100644 index 000000000..87d1974af --- /dev/null +++ b/tests/fixtures/test_mitocarta.json @@ -0,0 +1,41 @@ +{ + "test_mitocarta_human": { + "type": "code_defined", + "args": { + "species": "human", + "which": "mitocarta", + "verbose": false + }, + "expected_n_rows": 1136, + "expected_columns": [ + "Symbol", + "MitoCarta3.0_List", + "MitoCarta3.0_SubMitoLocalization", + "MitoCarta3.0_MitoPathways" + ] + }, + "test_mitocarta_pathways": { + "type": "code_defined", + "args": { + "species": "human", + "which": "pathways", + "verbose": false + }, + "expected_min_rows": 100 + }, + "test_mitocarta_bad_species": { + "type": "error", + "args": { + "species": "zebrafish" + }, + "expected_result": "ValueError" + }, + "test_mitocarta_bad_which": { + "type": "error", + "args": { + "species": "human", + "which": "nope" + }, + "expected_result": "ValueError" + } +} diff --git a/tests/test_mitocarta.py b/tests/test_mitocarta.py new file mode 100644 index 000000000..ce222412c --- /dev/null +++ b/tests/test_mitocarta.py @@ -0,0 +1,31 @@ +import json +import unittest + +from gget.gget_mitocarta import mitocarta + +from .from_json import from_json + +# Load dictionary containing arguments and expected results +with open("./tests/fixtures/test_mitocarta.json") as json_file: + mitocarta_dict = json.load(json_file) + + +class TestMitocarta(unittest.TestCase, metaclass=from_json(mitocarta_dict, mitocarta)): + # Error tests are generated from json; property tests are defined below. + + def test_mitocarta_human(self): + test = "test_mitocarta_human" + td = mitocarta_dict[test] + df = mitocarta(**td["args"]) + self.assertEqual(len(df), td["expected_n_rows"]) + for col in td["expected_columns"]: + self.assertIn(col, df.columns) + # A well-known mitochondrial gene should be in the inventory + self.assertIn("MT-CO1", set(df["Symbol"].astype(str))) + + def test_mitocarta_pathways(self): + test = "test_mitocarta_pathways" + td = mitocarta_dict[test] + df = mitocarta(**td["args"]) + self.assertIn("MitoPathway", df.columns) + self.assertGreaterEqual(len(df), td["expected_min_rows"]) From 3435f141545049240106884e859a359fecd0d49a Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 24 Jun 2026 23:23:40 +0800 Subject: [PATCH 02/13] docs(mitocarta): add mitocarta to SUMMARY.md site navigation (#118) Add the missing nav entry linking docs/src/en/mitocarta.md so the new module appears in the site navigation. (The Spanish SUMMARY entries and es/ pages are auto-generated and are not edited manually.) Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index b112fd0f2..340d20277 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -24,6 +24,7 @@ * [gget g2p](en/g2p.md) * [gget gpt](en/gpt.md) * [gget info](en/info.md) +* [gget mitocarta](en/mitocarta.md) * [gget muscle](en/muscle.md) * [gget mutate](en/mutate.md) * [gget opentargets](en/opentargets.md) From 484fb633c535bd9463f7dfc0aa9289eca031598a Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 21:54:22 +0800 Subject: [PATCH 03/13] feat(mitocarta): return a tidy DataFrame (L2 normalization) Normalize the raw Excel into an analysis-ready ("tidy") table instead of a raw dump: - pathways ('C') sheet: drop the stray unlabeled leading column (header reads as an integer), leaving MitoPathway / MitoPathways Hierarchy / Genes. - split delimited string columns into Python lists: Synonyms and MitoCarta3.0_MitoPathways ('|'-separated) and the pathways sheet's Genes (','-separated); missing values become an empty list. Add network-free unit tests (TestMitocartaClean) for _clean_df. Co-Authored-By: Claude Opus 4.8 (1M context) --- gget/gget_mitocarta.py | 37 ++++++++++++++++++++++++++++++++- tests/test_mitocarta.py | 46 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/gget/gget_mitocarta.py b/gget/gget_mitocarta.py index 30943dd03..518c95869 100644 --- a/gget/gget_mitocarta.py +++ b/gget/gget_mitocarta.py @@ -33,6 +33,37 @@ "mus musculus": "mouse", } +# Delimited string columns that we split into Python lists so the result is analysis-ready +# (a "tidy" table) rather than a raw Excel dump. Maps column name -> delimiter. +_LIST_COLUMNS = { + "Synonyms": "|", + "MitoCarta3.0_MitoPathways": "|", # each element is a `A > B > C` pathway path + "Genes": ",", # the pathways ('C') sheet lists member genes as a comma-separated string +} + + +def _split_delimited(value: Any, sep: str) -> Any: + """Split a delimited string into a stripped list; missing values become an empty list.""" + if isinstance(value, str) and value.strip(): + return [part.strip() for part in value.split(sep) if part.strip()] + return [] + + +def _clean_df(df: pd.DataFrame, which: str) -> pd.DataFrame: + """Normalize a raw MitoCarta sheet into a tidy DataFrame (L2). + + - The 'pathways' (C) sheet carries a stray, unlabeled leading column (its header is read + as an integer, e.g. 2); drop it so only MitoPathway / MitoPathways Hierarchy / Genes remain. + - Split delimited string columns (pathways, synonyms, gene lists) into Python lists. + Column names are left unchanged; no rows are dropped. + """ + if which == "pathways": + df = df.loc[:, [col for col in df.columns if isinstance(col, str)]].reset_index(drop=True) + for col, sep in _LIST_COLUMNS.items(): + if col in df.columns: + df[col] = df[col].map(lambda value, _sep=sep: _split_delimited(value, _sep)) + return df + def mitocarta( species: str = "human", @@ -59,7 +90,10 @@ def mitocarta( (or .json if json=True) in the current working directory (default: False). - verbose True/False whether to print progress information (default: True). - Returns the requested MitoCarta3.0 table as a pandas DataFrame (or a list of dictionaries if json=True). + Returns the requested MitoCarta3.0 table as a tidy pandas DataFrame (or a list of dictionaries + if json=True). The raw Excel is normalized for analysis: delimited columns (Synonyms, + MitoCarta3.0_MitoPathways, and the pathways sheet's Genes) are split into Python lists, and the + pathways sheet's stray unlabeled leading column is dropped. """ species_key = _SPECIES_ALIASES.get(species.lower()) if species_key is None: @@ -104,6 +138,7 @@ def mitocarta( logger.info(f"Parsing MitoCarta3.0 sheet '{sheet_name}'.") df = pd.read_excel(excel_file, sheet_name=sheet_name) + df = _clean_df(df, which) if save: if json: diff --git a/tests/test_mitocarta.py b/tests/test_mitocarta.py index ce222412c..55d5036e0 100644 --- a/tests/test_mitocarta.py +++ b/tests/test_mitocarta.py @@ -1,7 +1,8 @@ import json import unittest -from gget.gget_mitocarta import mitocarta +import pandas as pd +from gget.gget_mitocarta import _clean_df, mitocarta from .from_json import from_json @@ -29,3 +30,46 @@ def test_mitocarta_pathways(self): df = mitocarta(**td["args"]) self.assertIn("MitoPathway", df.columns) self.assertGreaterEqual(len(df), td["expected_min_rows"]) + + +class TestMitocartaClean(unittest.TestCase): + """Network-free unit tests for the L2 tidy normalization (_clean_df).""" + + def test_pathways_drops_stray_column(self): + # The 'C' sheet is read with a stray unlabeled integer-named leading column. + raw = pd.DataFrame( + { + 2: [7, 8], + "MitoPathway": ["P1", "P2"], + "MitoPathways Hierarchy": ["P1", "P1 > P2"], + "Genes": ["AARS2, ALKBH1", "DNA2"], + } + ) + out = _clean_df(raw, "pathways") + self.assertEqual(list(out.columns), ["MitoPathway", "MitoPathways Hierarchy", "Genes"]) + self.assertNotIn(2, out.columns) + + def test_pathways_genes_split_into_list(self): + raw = pd.DataFrame({"MitoPathway": ["P1"], "Genes": ["AARS2, ALKBH1, ANGEL2"]}) + out = _clean_df(raw, "pathways") + self.assertEqual(out.loc[0, "Genes"], ["AARS2", "ALKBH1", "ANGEL2"]) + + def test_mitocarta_splits_pathways_and_synonyms(self): + raw = pd.DataFrame( + { + "Symbol": ["CYC1"], + "Synonyms": ["MC3DN6|UQCR4"], + "MitoCarta3.0_MitoPathways": ["OXPHOS > Complex III | Metabolism > Heme"], + } + ) + out = _clean_df(raw, "mitocarta") + self.assertEqual(out.loc[0, "Synonyms"], ["MC3DN6", "UQCR4"]) + self.assertEqual( + out.loc[0, "MitoCarta3.0_MitoPathways"], + ["OXPHOS > Complex III", "Metabolism > Heme"], + ) + + def test_missing_delimited_value_becomes_empty_list(self): + raw = pd.DataFrame({"Symbol": ["X"], "Synonyms": [None]}) + out = _clean_df(raw, "mitocarta") + self.assertEqual(out.loc[0, "Synonyms"], []) From 5b61d233ab06b6eeef3b438dbaaf9209419cfb67 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 21:58:27 +0800 Subject: [PATCH 04/13] feat(mitocarta): retry the download on transient network errors Wrap the requests.get in a small retry loop (3 attempts, linear backoff) that retries on connection errors/timeouts and 5xx responses, but fails fast on 4xx (e.g. 404). Add a network-free test that mocks a persistent ConnectionError and asserts the download is retried before raising. Co-Authored-By: Claude Opus 4.8 (1M context) --- gget/gget_mitocarta.py | 35 ++++++++++++++++++++++++++++++----- tests/test_mitocarta.py | 18 ++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/gget/gget_mitocarta.py b/gget/gget_mitocarta.py index 518c95869..1093f8a36 100644 --- a/gget/gget_mitocarta.py +++ b/gget/gget_mitocarta.py @@ -2,6 +2,7 @@ import io import json as json_package +import time from typing import Any import pandas as pd @@ -12,6 +13,10 @@ logger = set_up_logger() +# Retry the download on transient network errors (connection drops, timeouts, 5xx). +_DOWNLOAD_RETRIES = 3 +_RETRY_BACKOFF_SEC = 2 + # Map the `which` argument to the leading character of the corresponding Excel sheet name. # The MitoCarta3.0 workbook contains the sheets: # "A MitoCarta3.0" -> the mitochondrial gene inventory @@ -111,11 +116,31 @@ def mitocarta( if verbose: logger.info(f"Downloading MitoCarta3.0 ({species_key}) from {url} ...") - response = requests.get(url, timeout=DEFAULT_REQUESTS_TIMEOUT) - if response.status_code != 200: - raise RuntimeError( - f"MitoCarta3.0 download returned status code {response.status_code} ({url}). Please try again.\n" - ) + response = None + last_error = "" + for attempt in range(1, _DOWNLOAD_RETRIES + 1): + try: + response = requests.get(url, timeout=DEFAULT_REQUESTS_TIMEOUT) + except requests.RequestException as e: + last_error = str(e) + response = None + else: + if response.status_code == 200: + break + if response.status_code < 500: + # Client error (e.g. 404) is permanent; do not retry. + raise RuntimeError(f"MitoCarta3.0 download returned status code {response.status_code} ({url}).\n") + last_error = f"status code {response.status_code}" + response = None + if attempt < _DOWNLOAD_RETRIES: + if verbose: + logger.warning( + f"MitoCarta3.0 download attempt {attempt}/{_DOWNLOAD_RETRIES} failed ({last_error}); retrying..." + ) + time.sleep(_RETRY_BACKOFF_SEC * attempt) + + if response is None: + raise RuntimeError(f"MitoCarta3.0 download failed after {_DOWNLOAD_RETRIES} attempts ({last_error}) ({url}).\n") try: excel_file = pd.ExcelFile(io.BytesIO(response.content), engine="xlrd") diff --git a/tests/test_mitocarta.py b/tests/test_mitocarta.py index 55d5036e0..08669a1f3 100644 --- a/tests/test_mitocarta.py +++ b/tests/test_mitocarta.py @@ -1,7 +1,10 @@ import json import unittest +from unittest.mock import patch +import gget.gget_mitocarta as gget_mitocarta import pandas as pd +import requests from gget.gget_mitocarta import _clean_df, mitocarta from .from_json import from_json @@ -73,3 +76,18 @@ def test_missing_delimited_value_becomes_empty_list(self): raw = pd.DataFrame({"Symbol": ["X"], "Synonyms": [None]}) out = _clean_df(raw, "mitocarta") self.assertEqual(out.loc[0, "Synonyms"], []) + + +class TestMitocartaRetry(unittest.TestCase): + """Network-free test that the download retries on transient network errors.""" + + @patch("gget.gget_mitocarta.time.sleep") # don't actually wait between retries + @patch( + "gget.gget_mitocarta.requests.get", + side_effect=requests.exceptions.ConnectionError("boom"), + ) + def test_retries_then_raises_after_exhausting_attempts(self, mock_get, _mock_sleep): + with self.assertRaises(RuntimeError): + mitocarta("human", which="mitocarta", verbose=False) + # Retried the configured number of times before giving up. + self.assertEqual(mock_get.call_count, gget_mitocarta._DOWNLOAD_RETRIES) From 7f55f641cc6d2f407e03b6ccfca4c1f5dac28468 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 22:08:46 +0800 Subject: [PATCH 05/13] fix(mitocarta): guard sheet-name filter with isinstance(str) for mypy excel_file.sheet_names is typed int | str; narrow to str before .startswith so the baseline-filtered mypy pre-commit hook passes. --- gget/gget_mitocarta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gget/gget_mitocarta.py b/gget/gget_mitocarta.py index 1093f8a36..26d976467 100644 --- a/gget/gget_mitocarta.py +++ b/gget/gget_mitocarta.py @@ -151,7 +151,7 @@ def mitocarta( # Resolve the sheet name by its leading character (species word differs between human/mouse) prefix = _WHICH_TO_SHEET_PREFIX[which] - matching = [name for name in excel_file.sheet_names if name.startswith(prefix)] + matching = [name for name in excel_file.sheet_names if isinstance(name, str) and name.startswith(prefix)] if not matching: raise RuntimeError( f"Could not find the '{which}' sheet in the MitoCarta3.0 workbook. " From 0146091c4e7b2d65f6e6be2e667b9b454f3b2cdc Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 22:15:27 +0800 Subject: [PATCH 06/13] docs(mitocarta): note tidy list columns and add a JSON output example --- docs/src/en/mitocarta.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/src/en/mitocarta.md b/docs/src/en/mitocarta.md index 244608584..b05fd4cae 100644 --- a/docs/src/en/mitocarta.md +++ b/docs/src/en/mitocarta.md @@ -7,6 +7,8 @@ Return format: JSON (command-line) or data frame (Python). MitoCarta3.0 is a curated inventory of genes encoding proteins with strong support of mitochondrial localization, annotated with sub-mitochondrial localization and pathway membership. +The returned table is *tidy* (analysis-ready) rather than the raw Excel: delimited columns — `Synonyms` and `MitoCarta3.0_MitoPathways`, plus the pathways table's `Genes` — are split into lists, which become nested arrays in JSON output. + **Optional arguments** `-s` `--species` Species to fetch: `human` (default) or `mouse`. @@ -61,6 +63,19 @@ gget.mitocarta(which="pathways") ``` → Returns the MitoPathways and the genes assigned to each pathway. +

+ +**JSON output.** The command line returns JSON by default (use `--csv` for CSV; in Python use `json=True` for a list of dictionaries). List columns are emitted as arrays: +```json +[ + { + "MitoPathway": "Mitochondrial central dogma", + "MitoPathways Hierarchy": "Mitochondrial central dogma", + "Genes": ["AARS2", "ALKBH1", "ANGEL2", "APEX1", "..."] + } +] +``` + # References If you use `gget mitocarta` in a publication, please cite the following article: From 12b1894e2ec6281082853fd125c04d0a83e6b2a8 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 22:22:17 +0800 Subject: [PATCH 07/13] build(mitocarta): make xlrd an optional extra (gget[mitocarta]) - move xlrd out of the core dependencies into optional-dependencies.mitocarta (matches the gget[cellxgene] pattern; xlrd is only needed to read the .xls) - install the mitocarta extra in the hatch-test matrix on every tested Python version so the gget mitocarta tests can still read the workbook - point the missing-xlrd error message and the docs at `pip install gget[mitocarta]` Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/en/mitocarta.md | 2 ++ gget/gget_mitocarta.py | 3 ++- pyproject.toml | 13 +++++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/src/en/mitocarta.md b/docs/src/en/mitocarta.md index b05fd4cae..fa34f0c1c 100644 --- a/docs/src/en/mitocarta.md +++ b/docs/src/en/mitocarta.md @@ -9,6 +9,8 @@ MitoCarta3.0 is a curated inventory of genes encoding proteins with strong suppo The returned table is *tidy* (analysis-ready) rather than the raw Excel: delimited columns — `Synonyms` and `MitoCarta3.0_MitoPathways`, plus the pathways table's `Genes` — are split into lists, which become nested arrays in JSON output. +> `gget mitocarta` needs the optional `xlrd` dependency to read MitoCarta's `.xls` file. Install it with `pip install gget[mitocarta]`. + **Optional arguments** `-s` `--species` Species to fetch: `human` (default) or `mouse`. diff --git a/gget/gget_mitocarta.py b/gget/gget_mitocarta.py index 26d976467..6b00a18ed 100644 --- a/gget/gget_mitocarta.py +++ b/gget/gget_mitocarta.py @@ -146,7 +146,8 @@ def mitocarta( excel_file = pd.ExcelFile(io.BytesIO(response.content), engine="xlrd") except ImportError as e: raise RuntimeError( - "Reading the MitoCarta3.0 Excel file requires the 'xlrd' package. Install it with `pip install xlrd`.\n" + "Reading the MitoCarta3.0 Excel file requires the optional 'xlrd' dependency. " + "Install it with `pip install gget[mitocarta]` (or `pip install xlrd`).\n" ) from e # Resolve the sheet name by its leading character (species word differs between human/mouse) diff --git a/pyproject.toml b/pyproject.toml index d2360c210..774c4d8ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,8 +40,10 @@ dependencies = [ "pandas>=1", "requests>=2.22", "tqdm", - "xlrd>=2", ] +# Optional feature dependency for `gget mitocarta` (install: pip install gget[mitocarta]). +# xlrd is only needed to read MitoCarta's legacy .xls; kept out of the core deps. +optional-dependencies.mitocarta = [ "xlrd>=2" ] # Optional feature dependency for `gget cellxgene` (install: pip install gget[cellxgene]). # No wheels for the newest Python versions yet (e.g. 3.14 via tiledbsoma). # scanpy>=1.10 is pinned defensively, not because gget uses scanpy directly, @@ -78,10 +80,13 @@ envs.default.installer = "uv" envs.hatch-test.matrix = [ { python = [ "3.12", "3.13", "3.14" ] }, ] -# cellxgene-census (the `cellxgene` extra) has no wheels for the newest Python -# versions yet (e.g. 3.14 via tiledbsoma), so install it only where available; -# the gget cellxgene test skips itself when the dependency is absent. +# Install the `mitocarta` extra (xlrd) on every tested Python version so the +# gget mitocarta tests can read the .xls. cellxgene-census (the `cellxgene` +# extra) has no wheels for the newest Python versions yet (e.g. 3.14 via +# tiledbsoma), so install it only where available; the gget cellxgene test +# skips itself when the dependency is absent. envs.hatch-test.overrides.matrix.python.features = [ + { value = "mitocarta", if = [ "3.12", "3.13", "3.14" ] }, { value = "cellxgene", if = [ "3.12", "3.13" ] }, ] # pyproject.toml is the single source of truth for the environments CI tests: From 8ca0ee54128aad7f4285f30ebde0bec662b584f3 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 22:25:51 +0800 Subject: [PATCH 08/13] docs(mitocarta): add Spanish (es) translation and mirror docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add docs/src/es/mitocarta.md and register it in SUMMARY.md's Español section; mirror the mitocarta additions into the es introduction grid, updates, and cite pages so the Spanish docs stay in sync with English. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/SUMMARY.md | 1 + docs/src/es/cite.md | 3 ++ docs/src/es/introduction.md | 9 +++- docs/src/es/mitocarta.md | 84 +++++++++++++++++++++++++++++++++++++ docs/src/es/updates.md | 5 +++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 docs/src/es/mitocarta.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 340d20277..6c9e4ae0d 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -68,6 +68,7 @@ * [gget g2p](es/g2p.md) * [gget gpt](es/gpt.md) * [gget info](es/info.md) +* [gget mitocarta](es/mitocarta.md) * [gget muscle](es/muscle.md) * [gget mutate](es/mutate.md) * [gget opentargets](es/opentargets.md) diff --git a/docs/src/es/cite.md b/docs/src/es/cite.md index da959cb38..c1a8c8873 100644 --- a/docs/src/es/cite.md +++ b/docs/src/es/cite.md @@ -67,6 +67,9 @@ Luebbert, L., & Pachter, L. (2023). Efficient querying of genomic reference data - The UniProt Consortium , UniProt: the Universal Protein Knowledgebase in 2023, Nucleic Acids Research, Volume 51, Issue D1, 6 January 2023, Pages D523–D531, [https://doi.org/10.1093/nar/gkac1052](https://doi.org/10.1093/nar/gkac1052) +- Si utiliza `gget mitocarta`, favor de citar también: + - Rath S, Sharma R, Gupta R, Ast T, Chan C, Durham TJ, Goodman RP, Grabarek Z, Haas ME, Hung WHW, Joshi PR, Jourdain AA, Kim SH, Kotrys AV, Lam SS, McCoy JG, Meisel JD, Miranda M, Panda A, Patgiri A, Rogers R, Sadre S, Shah H, Skinner OS, To TL, Walker MA, Wang H, Ward PS, Wengrod J, Yuan CC, Calvo SE, Mootha VK. MitoCarta3.0: an updated mitochondrial proteome now with sub-organelle localization and pathway annotations. Nucleic Acids Res. 2021 Jan 8;49(D1):D1541-D1547. doi: [10.1093/nar/gkaa1011](https://doi.org/10.1093/nar/gkaa1011). PMID: 33174596; PMCID: PMC7779016. + - Si utiliza `gget muscle`, favor de citar también: - Edgar RC (2021), MUSCLE v5 enables improved estimates of phylogenetic tree confidence by ensemble bootstrapping, bioRxiv 2021.06.20.449169. [https://doi.org/10.1101/2021.06.20.449169](https://doi.org/10.1101/2021.06.20.449169) diff --git a/docs/src/es/introduction.md b/docs/src/es/introduction.md index b0911957a..a86666017 100644 --- a/docs/src/es/introduction.md +++ b/docs/src/es/introduction.md @@ -47,18 +47,23 @@ Estos son los módulos principales de `gget`. Haga clic en cualquier módulo par gget info
Recuperar toda la información asociada con un ID de Ensembl. + gget mitocarta
Obtener el inventario MitoCarta3.0 de proteínas y vías mitocondriales. gget muscle
Alinear múltiples secuencias de nucleótidos o aminoácidos entre sí. - gget mutate
Mutar secuencias de nucleótidos según mutaciones específicas. + gget mutate
Mutar secuencias de nucleótidos según mutaciones específicas. gget opentargets
Explorar qué enfermedades y medicamentos están asociados con un gen. gget pdb
Recuperar datos de la Base de Datos de Proteínas (PDB) según un ID de PDB. - gget ref
Obtener genomas de referencia de Ensembl. + gget ref
Obtener genomas de referencia de Ensembl. gget search
Encontrar IDs de Ensembl asociados con la palabra de búsqueda especificada. gget seq
Recuperar la secuencia de nucleótidos o aminoácidos de un gen. + + gget virus
Filtrar y obtener secuencias virales globales y metadatos extensos. + + diff --git a/docs/src/es/mitocarta.md b/docs/src/es/mitocarta.md new file mode 100644 index 000000000..743ee6066 --- /dev/null +++ b/docs/src/es/mitocarta.md @@ -0,0 +1,84 @@ +[ Ver el codigo fuente de la pagina en GitHub ](https://github.com/scverse/gget/blob/main/docs/src/es/mitocarta.md) + +> Parámetros de Python són iguales a los parámetros largos (`--parámetro`) de Terminal, si no especificado de otra manera. Banderas son parámetros de verdadero o falso (True/False) en Python. El manuál para cualquier modulo de gget se puede llamar desde la Terminal con la bandera `-h` `--help`. +# gget mitocarta 🫀 +Obtenga el inventario [MitoCarta3.0](https://www.broadinstitute.org/mitocarta/) de proteínas y vías mitocondriales de mamíferos del Broad Institute. +Regresa: JSON (línea de comandos) o un data frame (Python). + +MitoCarta3.0 es un inventario curado de genes que codifican proteínas con fuerte respaldo de localización mitocondrial, anotados con la localización submitocondrial y la pertenencia a vías. + +La tabla que se regresa está *ordenada* (*tidy*, lista para análisis) en lugar del Excel sin procesar: las columnas delimitadas — `Synonyms` y `MitoCarta3.0_MitoPathways`, además de la columna `Genes` de la tabla de vías — se dividen en listas, que se convierten en arreglos anidados en la salida JSON. + +> `gget mitocarta` necesita la dependencia opcional `xlrd` para leer el archivo `.xls` de MitoCarta. Instálala con `pip install gget[mitocarta]`. + +**Parámetros optionales** +`-s` `--species` +Especie a obtener: `human` (por defecto) o `mouse`. + +`-w` `--which` +Qué tabla regresar. Por defecto: `mitocarta`. +`mitocarta` - El inventario MitoCarta3.0 de genes mitocondriales (una fila por gen mitocondrial, con localización submitocondrial, MitoPathways, evidencia, y puntuaciones). +`all_genes` - Todos los genes puntuados para localización mitocondrial (puntuaciones Maestro), no solo los mitocondriales. +`pathways` - La jerarquía de MitoPathways y la lista de genes en cada vía. + +`-o` `--out` +Ruta al archivo en el que se guardarán los resultados, p. ej. ruta/al/directorio/resultados.json (o .csv). Por defecto: salida estándar (STDOUT). +Para Python, usa `save=True` para guardar los resultados en el directorio de trabajo actual. + +**Banderas** +`-csv` `--csv` +Solo para Terminal. Produce los resultados en formato CSV en lugar de JSON. +Para Python, usa `json=True` para producir una lista de diccionarios en lugar de un data frame. + +`-q` `--quiet` +Solo para Terminal. Impide la información de progreso de ser exhibida durante la ejecución del programa. +Para Python, usa `verbose=False` para impedir la información de progreso de ser exhibida durante la ejecución del programa. + + +### Ejemplos + +**Obtenga el inventario de genes mitocondriales MitoCarta3.0 humano:** +```bash +gget mitocarta --species human --csv +``` +```python +# Python +import gget +gget.mitocarta(species="human", which="mitocarta") +``` +→ Regresa los ~1,100 genes mitocondriales humanos y sus anotaciones MitoCarta3.0 (localización submitocondrial, MitoPathways, evidencia, puntuaciones). + +| HumanGeneID | Symbol | Description | MitoCarta3.0_List | MitoCarta3.0_SubMitoLocalization | MitoCarta3.0_MitoPathways | +|-------------|--------|----------------|-------------------|----------------------------------|-----------------------------------------| +| 1537 | CYC1 | cytochrome c1 | 1 | MIM | OXPHOS > Complex III assembly | +| 6390 | SDHB | ... | 1 | MIM | OXPHOS, Metabolism | + +

+ +**Obtenga la jerarquía de MitoPathways y sus genes:** +```bash +gget mitocarta --which pathways --csv +``` +```python +# Python +gget.mitocarta(which="pathways") +``` +→ Regresa los MitoPathways y los genes asignados a cada vía. + +

+ +**Salida JSON.** La línea de comandos regresa JSON por defecto (usa `--csv` para CSV; en Python usa `json=True` para una lista de diccionarios). Las columnas de tipo lista se emiten como arreglos: +```json +[ + { + "MitoPathway": "Mitochondrial central dogma", + "MitoPathways Hierarchy": "Mitochondrial central dogma", + "Genes": ["AARS2", "ALKBH1", "ANGEL2", "APEX1", "..."] + } +] +``` + +# Citar +Si utiliza `gget mitocarta` en una publicación, favor de citar el siguiente artículo: + +- Rath S, Sharma R, Gupta R, et al. MitoCarta3.0: an updated mitochondrial proteome now with sub-organelle localization and pathway annotations. Nucleic Acids Res. 2021 Jan 8;49(D1):D1541-D1547. doi: [10.1093/nar/gkaa1011](https://doi.org/10.1093/nar/gkaa1011). PMID: 33174596; PMCID: PMC7779016. diff --git a/docs/src/es/updates.md b/docs/src/es/updates.md index 0aa103023..525758e79 100644 --- a/docs/src/es/updates.md +++ b/docs/src/es/updates.md @@ -4,6 +4,11 @@ #### *gget* se unió oficialmente a *scverse* el 9 de junio de 2026. 🥳🥳🥳 +**Versión ≥ 0.30.9** (XXX XX de 2026): +- [`gget mitocarta`](mitocarta.md): **Nuevo módulo** para obtener el inventario [MitoCarta3.0](https://www.broadinstitute.org/mitocarta/) de proteínas y vías mitocondriales de mamíferos del Broad Institute (resuelve el [issue 118](https://github.com/scverse/gget/issues/118)). + - Admite humano y ratón mediante el argumento `species`; el argumento `which` regresa el inventario de genes mitocondriales (`mitocarta`, por defecto), todos los genes con puntuaciones de localización Maestro (`all_genes`), o la jerarquía de MitoPathways y sus genes (`pathways`). + - Regresa un DataFrame de `pandas` (o una lista de diccionarios / JSON con `json=True`). Añade `xlrd` como dependencia para leer el archivo Excel de MitoCarta. + **Versión ≥ 0.30.8** (28 de junio de 2026): - [`gget g2p`](g2p.md): Ahora es suficiente con `gene` o `--uniprot_id` — el que falte se resuelve a través de UniProt y se almacena en caché. Gene→UniProt selecciona la entrada canónica revisada humana de Swiss-Prot; la resolución y sus limitaciones se registran. El par canónico **siempre** se añade al inicio del resultado como columnas `gene_name` / `uniprot_id` (y se almacena en `df.attrs`), por lo que el esquema de salida es invariante independientemente del modo de entrada. Los sitios de llamada existentes siguen funcionando. - Nuevo filtro `residues=` (Python: int / list / range / set; CLI `--residues 100,200,300` o `100-200`) restringe `features` / `alignment` a posiciones específicas del lado del cliente. From 8948562acfac291180564627d8a182f289dd4f87 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 22:43:10 +0800 Subject: [PATCH 09/13] fix(mitocarta): add @overload stubs so json-typed return resolves (mypy) mitocarta() returns DataFrame | list[dict]; without overloads the CLI handler's 'mitocarta_results: pd.DataFrame = mitocarta(...)' fails mypy. Mirror the bgee pattern: json=True -> list[dict], json=False (default) -> DataFrame. --- gget/gget_mitocarta.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/gget/gget_mitocarta.py b/gget/gget_mitocarta.py index 6b00a18ed..50d9bc258 100644 --- a/gget/gget_mitocarta.py +++ b/gget/gget_mitocarta.py @@ -3,7 +3,7 @@ import io import json as json_package import time -from typing import Any +from typing import Any, Literal, overload import pandas as pd import requests @@ -70,6 +70,37 @@ def _clean_df(df: pd.DataFrame, which: str) -> pd.DataFrame: return df +@overload +def mitocarta( + species: str, + which: str, + json: Literal[True], + save: bool = ..., + verbose: bool = ..., +) -> list[dict[str, Any]]: ... + + +@overload +def mitocarta( + species: str = ..., + which: str = ..., + *, + json: Literal[True], + save: bool = ..., + verbose: bool = ..., +) -> list[dict[str, Any]]: ... + + +@overload +def mitocarta( + species: str = ..., + which: str = ..., + json: Literal[False] = False, + save: bool = ..., + verbose: bool = ..., +) -> pd.DataFrame: ... + + def mitocarta( species: str = "human", which: str = "mitocarta", From 876c1889204a193e144617fc103dc07439428d6e Mon Sep 17 00:00:00 2001 From: Elarwei Date: Wed, 1 Jul 2026 22:44:43 +0800 Subject: [PATCH 10/13] chore(mitocarta): apply pyproject-fmt ordering of optional-dependencies --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 774c4d8ca..4b2fe6202 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,9 +41,6 @@ dependencies = [ "requests>=2.22", "tqdm", ] -# Optional feature dependency for `gget mitocarta` (install: pip install gget[mitocarta]). -# xlrd is only needed to read MitoCarta's legacy .xls; kept out of the core deps. -optional-dependencies.mitocarta = [ "xlrd>=2" ] # Optional feature dependency for `gget cellxgene` (install: pip install gget[cellxgene]). # No wheels for the newest Python versions yet (e.g. 3.14 via tiledbsoma). # scanpy>=1.10 is pinned defensively, not because gget uses scanpy directly, @@ -51,6 +48,9 @@ optional-dependencies.mitocarta = [ "xlrd>=2" ] # Under certain resolver paths uv lands on scanpy 1.9.8, which transitively # pins numba 0.53.1 and llvmlite 0.36.x — both of which only support Python 3.6-3.9. optional-dependencies.cellxgene = [ "cellxgene-census", "scanpy>=1.10" ] +# Optional feature dependency for `gget mitocarta` (install: pip install gget[mitocarta]). +# xlrd is only needed to read MitoCarta's legacy .xls; kept out of the core deps. +optional-dependencies.mitocarta = [ "xlrd>=2" ] # https://docs.pypi.org/project_metadata/#project-urls urls.Documentation = "https://pachterlab.github.io/gget" urls.Homepage = "https://github.com/pachterlab/gget" From 3fec98015ecdfef41091b41fb54070ef34b20cce Mon Sep 17 00:00:00 2001 From: Elarwei Date: Thu, 2 Jul 2026 08:54:51 +0800 Subject: [PATCH 11/13] ci: re-trigger (flaky live tests in test_seq/test_virus, unrelated to this PR) From 9aa3ac0a6f008babcdd57ea81e595619ba766f40 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Thu, 2 Jul 2026 09:29:08 +0800 Subject: [PATCH 12/13] ci: re-trigger (Ensembl recovered; earlier failures were rest.ensembl.org 500) From a1bd9da1646c4c0d613723ecc616ff1d2d145c80 Mon Sep 17 00:00:00 2001 From: Elarwei Date: Thu, 2 Jul 2026 20:19:38 +0800 Subject: [PATCH 13/13] ci: re-trigger (Ensembl 500 window over; prior failures were rest.ensembl.org outage across Ensembl-backed modules)