Spaces:
Paused
Paused
| import httpx | |
| import time | |
| GRAPHQL_URL = "https://api.platform.opentargets.org/api/v4/graphql" | |
| ENSEMBL_URL = "https://rest.ensembl.org/lookup/symbol/homo_sapiens" | |
| async def _resolve_ensembl_id(gene_symbol: str) -> str | None: | |
| """Resolve a gene symbol to an Ensembl gene ID.""" | |
| async with httpx.AsyncClient(timeout=10) as client: | |
| r = await client.get( | |
| f"{ENSEMBL_URL}/{gene_symbol}", | |
| headers={"Content-Type": "application/json"}, | |
| ) | |
| if r.status_code == 200: | |
| return r.json().get("id") | |
| return None | |
| async def query_open_targets(gene_symbol: str) -> list[dict]: | |
| """Query Open Targets for drug-target associations.""" | |
| ensembl_id = await _resolve_ensembl_id(gene_symbol) | |
| if not ensembl_id: | |
| return [] | |
| query = """ | |
| { | |
| target(ensemblId: "%s") { | |
| approvedName | |
| drugAndClinicalCandidates { | |
| rows { | |
| drug { name } | |
| maxClinicalStage | |
| diseases { diseaseFromSource } | |
| } | |
| } | |
| } | |
| } | |
| """ % ensembl_id | |
| async with httpx.AsyncClient(timeout=15) as client: | |
| r = await client.post(GRAPHQL_URL, json={"query": query}) | |
| if r.status_code != 200: | |
| return [] | |
| data = r.json().get("data", {}).get("target", {}) | |
| results = [] | |
| rows = data.get("drugAndClinicalCandidates", {}).get("rows", []) if data else [] | |
| for row in rows[:5]: | |
| name = row.get("drug", {}).get("name", "") | |
| phase = row.get("maxClinicalStage", "") | |
| diseases = row.get("diseases", []) | |
| disease = diseases[0].get("diseaseFromSource", "") if diseases else "" | |
| results.append( | |
| { | |
| "url": f"https://platform.opentargets.org/target/{ensembl_id}", | |
| "snippet": f"{name} ({phase}) — associated with {disease}", | |
| "date_retrieved": int(time.time()), | |
| "source_name": "Open Targets", | |
| } | |
| ) | |
| return results | |