Spaces:
Running
Running
File size: 3,168 Bytes
8ce1e37 fb8c550 8ce1e37 fb8c550 8ce1e37 fb8c550 8ce1e37 bde6aea 8ce1e37 bde6aea 8ce1e37 bde6aea 8ce1e37 fb8c550 8ce1e37 fb8c550 8ce1e37 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import httpx
import json
import hashlib
import logging
from app.services.cache import cache_get, cache_set
logger = logging.getLogger(__name__)
ANALYSIS_BASE = "https://reactome.org/AnalysisService"
async def run_enrichment(identifiers: list[str]) -> dict | None:
raw = json.dumps(sorted(identifiers), sort_keys=True)
key_hash = hashlib.sha256(raw.encode()).hexdigest()[:16]
cache_key = f"enrichment:{key_hash}"
cached = cache_get(cache_key)
if cached is not None:
try:
result = json.loads(cached)
if isinstance(result, dict):
result["from_cache"] = True
return result
except (json.JSONDecodeError, TypeError):
pass
try:
body = "\n".join(identifiers)
async with httpx.AsyncClient(timeout=30) as client:
resp = await client.post(
f"{ANALYSIS_BASE}/identifiers/projection",
content=body,
headers={"Content-Type": "text/plain"},
params={"pageSize": "20", "page": "1"},
)
if resp.status_code != 200:
logger.warning(f"Reactome Analysis Service returned {resp.status_code}")
return None
data = resp.json()
token = data.get("summary", {}).get("token", "")
if not token:
logger.warning("No analysis token returned from Reactome")
return None
# The projection response already carries the enriched pathways;
# the separate /token/{token}/pathways call is unnecessary (and
# currently 404s for tokens returned with a trailing %3D).
pathways_data = data
pathways = []
for item in pathways_data.get("pathways", []):
species = item.get("species", {})
species_name = (
species.get("name", "")
if isinstance(species, dict)
else (species or "")
)
entities = item.get("entities", {})
found = entities.get("found", 0)
total = entities.get("total", 0)
pathways.append({
"stId": item.get("stId", ""),
"name": item.get("name", ""),
"species": species_name,
"entitiesFound": found,
"entitiesTotal": total,
"geneRatio": round(found / total, 4) if total else 0.0,
"entitiesFDR": entities.get("fdr", 1.0),
"entitiesPValue": entities.get("pValue", 1.0),
})
pathways.sort(key=lambda p: p["entitiesFDR"])
result = {
"token": token,
"pathways": pathways,
}
try:
cache_set(cache_key, json.dumps(result), ttl=86400)
except (TypeError, ValueError):
pass
result["from_cache"] = False
return result
except Exception as e:
logger.warning(f"Pathway enrichment failed: {e}")
return None
|