KCNG-Explorer / src /sequences.py
khairi's picture
Claude Sonnet 5
Restore missing src modules, fix esm/gradio dependency conflict
fe8c5d0
Raw History Blame Contribute Delete
1.48 kB
"""FASTA parsing and UniProt sequence fetching."""
from __future__ import annotations
from dataclasses import dataclass
from io import StringIO
import requests
from Bio import SeqIO
UNIPROT_FASTA_URL = "https://rest.uniprot.org/uniprotkb/{accession}.fasta"
@dataclass
class ProteinRecord:
id: str
description: str
sequence: str
def parse_fasta(text: str) -> list[ProteinRecord]:
records = SeqIO.parse(StringIO(text), "fasta")
return [
ProteinRecord(id=r.id, description=r.description, sequence=str(r.seq).upper())
for r in records
]
def extract_accession(record_id: str) -> str:
"""Pull the accession out of a FASTA record id.
UniProt headers follow the `db|accession|entry_name` convention (e.g.
`sp|Q9UK17|KCNG1_HUMAN`), so the accession is the middle field. Anything
else (a plain accession, a custom id, ...) is returned as-is.
"""
parts = record_id.split("|")
if len(parts) == 3:
return parts[1]
return record_id
def fetch_uniprot_sequence(accession: str, timeout: float = 10.0) -> ProteinRecord:
"""Fetch a single sequence from UniProt by accession (e.g. "Q9Y2W7")."""
url = UNIPROT_FASTA_URL.format(accession=accession.strip())
response = requests.get(url, timeout=timeout)
response.raise_for_status()
records = parse_fasta(response.text)
if not records:
raise ValueError(f"No sequence returned for accession {accession!r}")
return records[0]