Spaces:
Running
Running
Download bioai-platform/backend/app/integrations/ncbi/blast.py from Samad14/bio-nexus-api: direct link, hf CLI and curl.
- Browser
- Download file 2.6 kB
-
https://huggingface.co/spaces/Samad14/bio-nexus-api/resolve/fb8c550baa97630a7ea75c27656d800982f513c5/bioai-platform/backend/app/integrations/ncbi/blast.py
- Command line
-
hf download hf://spaces/Samad14/bio-nexus-api@fb8c550baa97630a7ea75c27656d800982f513c5/bioai-platform/backend/app/integrations/ncbi/blast.py
-
curl -L -o blast.py https://huggingface.co/spaces/Samad14/bio-nexus-api/resolve/fb8c550baa97630a7ea75c27656d800982f513c5/bioai-platform/backend/app/integrations/ncbi/blast.py
2.6 kB
| """ | |
| Thin client for NCBI BLAST URL API (QBLAST). | |
| Rate limit: NCBI enforces 1 request per 10 seconds without an API key, | |
| 3 req/s with an API key. Rate limiting is the caller's responsibility. | |
| API docs: https://ncbi.github.io/blast-cloud/api.html | |
| """ | |
| import re | |
| import httpx | |
| from typing import Optional | |
| NCBI_BLAST_URL = "https://blast.ncbi.nlm.nih.gov/blast/Blast.cgi" | |
| RATE_LIMIT_SECONDS = 10 | |
| async def submit_blast( | |
| sequence: str, | |
| program: str = "blastp", | |
| database: str = "nr", | |
| hitlist_size: int = 100, | |
| expect: float = 10.0, | |
| gapopen: int = -1, | |
| gapextend: int = -1, | |
| matrix: str = "BLOSUM62", | |
| async_flag: bool = True, | |
| ) -> dict: | |
| params = { | |
| "CMD": "Put", | |
| "PROGRAM": program, | |
| "DATABASE": database, | |
| "QUERY": sequence, | |
| "HITLIST_SIZE": str(hitlist_size), | |
| "EXPECT": str(expect), | |
| "MATRIX": matrix, | |
| "ASYNC": "1" if async_flag else "0", | |
| } | |
| if gapopen > 0: | |
| params["GAPOPEN"] = str(gapopen) | |
| if gapextend > 0: | |
| params["GAPEXTEND"] = str(gapextend) | |
| async with httpx.AsyncClient(timeout=30) as client: | |
| resp = await client.post(NCBI_BLAST_URL, data=params) | |
| resp.raise_for_status() | |
| text = resp.text | |
| rid_match = re.search(r"RID\s*=\s*(\S+)", text) | |
| rtoe_match = re.search(r"RTOE\s*=\s*(\d+)", text) | |
| if not rid_match: | |
| return {"error": "No RID returned from NCBI", "raw": text[:500]} | |
| rid = rid_match.group(1) | |
| rtoe = int(rtoe_match.group(1)) if rtoe_match else 60 | |
| return {"rid": rid, "estimated_seconds": rtoe} | |
| async def check_status(rid: str, fmt: str = "XML") -> dict: | |
| params = {"CMD": "Get", "FORMAT_TYPE": fmt, "RID": rid} | |
| async with httpx.AsyncClient(timeout=30) as client: | |
| resp = await client.get(NCBI_BLAST_URL, params=params) | |
| resp.raise_for_status() | |
| text = resp.text | |
| if "Status=" in text: | |
| status_match = re.search(r"Status\s*=\s*(\w+)", text) | |
| status = status_match.group(1) if status_match else "UNKNOWN" | |
| else: | |
| status = "READY" | |
| return {"status": status, "raw": text, "rid": rid} | |
| async def fetch_results(rid: str, fmt: str = "XML") -> dict: | |
| params = {"CMD": "Get", "FORMAT_TYPE": fmt, "RID": rid} | |
| async with httpx.AsyncClient(timeout=60) as client: | |
| resp = await client.get(NCBI_BLAST_URL, params=params) | |
| resp.raise_for_status() | |
| text = resp.text | |
| if "Status=" in text and "Status=READY" not in text: | |
| return {"error": "Results not ready", "raw": text[:200]} | |
| return {"raw": text, "rid": rid} | |