Source code for tooluniverse.pathway_commons_tool

from typing import Dict, Any, List, Optional
import requests
from .base_tool import BaseTool
from .tool_registry import register_tool


[docs] @register_tool("PathwayCommonsTool") class PathwayCommonsTool(BaseTool): """ Tool for interacting with Pathway Commons (PC2). """ BASE_URL = "https://www.pathwaycommons.org/pc2"
[docs] def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]: """ Executes the Pathway Commons tool action. """ action = arguments.get("action") if action == "search_pathways": return self.search_pathways( keyword=arguments.get("keyword"), datasource=arguments.get("datasource"), limit=arguments.get("limit", 10), ) elif action == "get_interaction_graph": gene_list = arguments.get("gene_list") if not gene_list: raise ValueError("gene_list is required for get_interaction_graph") return self.get_interaction_graph(gene_list) else: raise ValueError(f"Unknown action: {action}")
[docs] def search_pathways( self, keyword: str, datasource: Optional[str] = None, limit: int = 10 ) -> Dict[str, Any]: """ Search for pathways. """ url = f"{self.BASE_URL}/search" params = {"q": keyword, "type": "Pathway", "format": "json"} if datasource: params["datasource"] = datasource try: response = requests.get(url, params=params, timeout=30) response.raise_for_status() data = response.json() pathways = [] for hit in data.get("searchHit", [])[:limit]: pathways.append( { "name": hit.get("name"), "uri": hit.get("uri"), "source": hit.get("dataSource"), "organism": hit.get("organism"), } ) return {"total_hits": data.get("numHits"), "pathways": pathways} except Exception as e: return {"error": str(e)}
[docs] def get_interaction_graph(self, gene_list: List[str]) -> Dict[str, Any]: """ Get SIF graph for genes. WARNING: The 'graph' endpoint usually returns SIF text, not JSON. We will return the raw text or parse it if simple. SIF format: source relation target """ url = f"{self.BASE_URL}/graph" # source parameter takes list of gene symbols # kind=neighborhood is common, or pathsbetween # Let's assume pathsbetween for list of genes if size > 1, or neighborhood if size=1? # Simpler: just use 'neighborhood' for all provided genes? Or simple interaction search? # Docs usually say `source=A,B,C`. genes_str = ",".join(gene_list) params = { "source": genes_str, "kind": "neighborhood", # Get neighborhood of these genes "format": "SIF", } try: response = requests.get(url, params=params, timeout=30) response.raise_for_status() # SIF is tab separated lines lines = response.text.strip().split("\n") interactions = [] for line in lines: parts = line.split("\t") if len(parts) >= 3: interactions.append( {"source": parts[0], "relation": parts[1], "target": parts[2]} ) return {"format": "SIF", "interactions": interactions} except Exception as e: return {"error": str(e)}