Source code for tooluniverse.wikipathways_ext_tool

# wikipathways_ext_tool.py
"""
WikiPathways Extended tool for ToolUniverse.

Provides additional WikiPathways endpoints for extracting gene lists
from pathways and finding pathways by gene identifier.

API: https://webservice.wikipathways.org/
No authentication required. Free public access.
"""

import requests
from typing import Dict, Any
from .base_tool import BaseTool


WP_BASE_URL = "https://webservice.wikipathways.org"

CODE_TO_NAME = {
    "H": "HGNC Symbol",
    "En": "Ensembl",
    "S": "UniProt",
    "L": "Entrez Gene",
    "Ce": "ChEBI",
}


[docs] class WikiPathwaysExtTool(BaseTool): """ Tool for WikiPathways extended API endpoints. No authentication required. """
[docs] def __init__(self, tool_config: Dict[str, Any]): super().__init__(tool_config) self.timeout = tool_config.get("timeout", 30) fields = tool_config.get("fields", {}) self.endpoint = fields.get("endpoint", "get_pathway_genes")
[docs] def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]: """Execute the WikiPathways API call.""" try: return self._query(arguments) except requests.exceptions.Timeout: return {"error": f"WikiPathways API timed out after {self.timeout}s"} except requests.exceptions.ConnectionError: return {"error": "Failed to connect to WikiPathways API"} except requests.exceptions.HTTPError as e: code = e.response.status_code if e.response is not None else "unknown" return {"error": f"WikiPathways API HTTP error: {code}"} except Exception as e: return {"error": f"Unexpected error querying WikiPathways: {str(e)}"}
[docs] def _query(self, arguments: Dict[str, Any]) -> Dict[str, Any]: """Route to appropriate endpoint.""" if self.endpoint == "get_pathway_genes": return self._get_pathway_genes(arguments) elif self.endpoint == "find_pathways_by_gene": return self._find_pathways_by_gene(arguments) else: return {"error": f"Unknown endpoint: {self.endpoint}"}
[docs] def _get_pathway_genes(self, arguments: Dict[str, Any]) -> Dict[str, Any]: """Get all genes in a WikiPathways pathway.""" pathway_id = arguments.get("pathway_id", "") if not pathway_id: return {"error": "pathway_id parameter is required (e.g., 'WP254')"} code = arguments.get("code", "H") id_type_name = CODE_TO_NAME.get(code, code) url = f"{WP_BASE_URL}/getXrefList" params = { "pwId": pathway_id, "code": code, "format": "json", } response = requests.get(url, params=params, timeout=self.timeout) response.raise_for_status() data = response.json() xrefs = data.get("xrefs", []) # Deduplicate and sort unique_genes = sorted(set(xrefs)) return { "data": { "pathway_id": pathway_id, "gene_count": len(unique_genes), "identifier_type": id_type_name, "genes": unique_genes, }, "metadata": { "source": "WikiPathways API", "pathway_id": pathway_id, "code": code, }, }
[docs] def _find_pathways_by_gene(self, arguments: Dict[str, Any]) -> Dict[str, Any]: """Find pathways containing a specific gene.""" gene = arguments.get("gene", "") if not gene: return {"error": "gene parameter is required (e.g., 'TP53', 'BRCA1')"} species = arguments.get("species", "Homo sapiens") url = f"{WP_BASE_URL}/findPathwaysByXref" params = { "ids": gene, "codes": "H", "format": "json", } response = requests.get(url, params=params, timeout=self.timeout) response.raise_for_status() data = response.json() results = data.get("result", []) # Filter by species if species: results = [ r for r in results if species.lower() in r.get("species", "").lower() ] # Deduplicate by pathway ID (some genes appear multiple times in same pathway) seen = set() unique_pathways = [] for r in results: pid = r.get("id", "") if pid not in seen: seen.add(pid) unique_pathways.append( { "id": pid, "name": r.get("name", ""), "species": r.get("species", ""), "url": r.get("url"), } ) return { "data": { "gene": gene, "total_pathways": len(unique_pathways), "pathways": unique_pathways, }, "metadata": { "source": "WikiPathways API", "gene": gene, "species": species, }, }