domains / science / bioinformatics-service-workflows / bioservices
The three copies overlap on the core BioServices use case (UniProt, KEGG, UniChem, QuickGO, PSICQUIC) but each contains material steps or constraints the others lack. K-Dense-AI provides version-pinned installation, response-type validation, pagination/limit guidance, KEGG rate limits, and SIF namespace caveats. aipoch provides a broader cross-service example including QuickGO and PSICQUIC and optional dependencies. FreedomIntelligence provides BLAST asynchronous workflow, organism/pathway lookup methods, and a direct-REST alternative note. Crowning one would hide real alternatives and constraints.
| Repository | Path |
|---|---|
| K-Dense-AI/scientific-agent-skills | skills/bioservices/SKILL.md |
| aipoch/medical-research-skills | scientific-skills/Data Analysis/bioservices/SKILL.md |
| FreedomIntelligence/OpenClaw-Medical-Skills | skills/bioservices/SKILL.md |
| Role | Repository | Path |
|---|---|---|
| peer | K-Dense-AI/scientific-agent-skills | skills/bioservices/SKILL.md |
| peer | aipoch/medical-research-skills | scientific-skills/Data Analysis/bioservices/SKILL.md |
| peer | FreedomIntelligence/OpenClaw-Medical-Skills | skills/bioservices/SKILL.md |
---
name: bioservices
description: Python interface to bioinformatics services including UniProt, KEGG, ChEMBL, Reactome, QuickGO, UniChem, and PSICQUIC. Use for cross-database protein annotation, pathway retrieval, chemical identifier mapping, and integrated biological data workflows.
license: MIT
---
# BioServices
## When to use
Use BioServices when combining protein annotation, gene/pathway membership, compound cross-references, or genomic resources in Python. Its service clients share transport helpers, but their request parameters and return types differ. Use the service reference before composing clients; method names from PubChemPy, mygene, or older BioServices are not portable.
Install a compatible version. K-Dense-AI pins bioservices==1.16.0 for Python >=3.9,<4; other copies leave the version environment-dependent. Choose the pin that matches your environment and test before batching.
```bash
uv pip install "bioservices==1.16.0"
```
## Workflow
1. Resolve the requested organism and entity to stable accessions. Review search hits before selecting one; gene symbols and compound names may be ambiguous.
2. Inspect the service's actual response type, including pagination and errors. BioServices can return an integer-like HTTP error or None, not only raise.
3. Preserve one-to-many mappings, failed identifiers, taxonomy, database release, query parameters, and retrieval date alongside derived tables.
4. Distinguish annotations and inferred associations from experimental evidence. Pathway membership alone is not an enrichment analysis or causal finding.
5. Run a small lookup before batching; honor provider limits and retain failures separately from confirmed empty results.
## Protein search, sequence retrieval, and mapping
```python
from bioservices import UniProt
u = UniProt(verbose=False)
u.services.TIMEOUT = 30
rows = u.search(
"gene_exact:ZAP70 AND organism_id:9606 AND reviewed:true",
frmt="tsv", columns="accession,gene_names,organism_name,length",
limit=5, size=5,
)
if not isinstance(rows, str):
raise RuntimeError("UniProt search failed")
print(rows)
fasta = u.retrieve("P43403", frmt="fasta")
record = u.retrieve("P43403", frmt="json")
mapping = u.mapping(fr="UniProtKB_AC-ID", to="KEGG", query="P43403")
if not isinstance(mapping, dict) or "results" not in mapping:
raise RuntimeError("Mapping incomplete or failed")
kegg_ids = [row["to"] for row in mapping["results"] if row["from"] == "P43403"]
print(kegg_ids, mapping.get("failedIds", []))
```
Use frmt="tsv" for tabular output; some older examples use frmt="tab". Current field names include accession, gene_names, organism_name, protein_name, go_id, and xref_pdb. mapping() returns a results/failedIds envelope, not a source-to-list dictionary. Mapping to UniProt uses to="UniProtKB" and returns full records in row["to"]; extract primaryAccession. UniProtKB_AC-ID is a source code. For bounded searches set size=limit (at most 500); 1.16.0 mixes the two values in its pagination loop.
## KEGG pathways and networks
```python
from bioservices import KEGG
k = KEGG(verbose=False)
k.services.url = "https://rest.kegg.jp"
pathway_names = k.get_pathway_by_gene("7535", "hsa") # dict: pathway ID -> name
print(pathway_names)
kgml = k.parse_kgml_pathway("hsa04660")
entries = {entry["id"]: entry for entry in kgml["entries"]}
for relation in kgml["relations"][:5]:
print(entries[relation["entry1"]]["name"], relation["name"],
entries[relation["entry2"]]["name"])
```
The reviewed /list/organism endpoint returned HTTP 400 despite remaining in the manual. SDK methods that validate against that catalogue can fail. Use documented scoped endpoints through k.services.http_get to avoid that unrelated catalogue dependency.
KEGG get permits at most ten entries; KGML permits one pathway per request. Keep requests at or below three per second. list/find return TSV strings; get returns a flat-file string unless an option changes the representation. KGML entries include genes, compounds, groups, and maps. A relation can produce several subtype records; those counts are neither unique genes nor independent physical interactions. Entry IDs are local to each pathway. The bundled SIF export namespaces them as pathway#entry so combining pathways cannot merge unrelated nodes. pathway2sif(..., uniprot=False) is an optional lossy projection of gene-to-gene activation/inhibition, not a complete pathway network.
## Compound cross-references
```python
from bioservices import UniChem
uc = UniChem(verbose=False)
response = uc.get_compounds("CHEBI:15365", "chebi") # aspirin
if not isinstance(response, dict) or "compounds" not in response:
raise RuntimeError("UniChem request failed")
chembl_ids = sorted({source["compoundId"]
for match in response["compounds"] for source in match.get("sources", [])
if source.get("shortName") == "chembl"})
print(chembl_ids)
```
UniChem 2 uses POST /api/v1/compounds with a JSON body; BioServices assembles it. Discover source names through uc.source_ids; KEGG is absent at review. From a KEGG compound, preserve every ChEBI cross-reference and use only a uniquely resolved, structurally reviewed candidate. Check charge, stereochemistry, salts, and parent.
## QuickGO annotations
```python
from bioservices import QuickGO
g = QuickGO(verbose=False)
ann = g.Annotation(protein="P43403", format="tsv")
print(ann.splitlines()[0])
```
## PSICQUIC interactions
```python
from bioservices import PSICQUIC
p = PSICQUIC(verbose=False)
interactions = p.query("intact", "ZAP70 AND species:9606")
print("\n".join(interactions.splitlines()[:3]))
```
Choose a database that is active in your environment; "intact" is commonly available. List available databases through p.activeDBs.
## BLAST (optional)
```python
from bioservices import NCBIblast
s = NCBIblast(verbose=False)
jobid = s.run(
program="blastp",
sequence=protein_sequence,
stype="protein",
database="uniprotkb",
email="your.email@example.com",
)
s.getStatus(jobid)
results = s.getResult(jobid, "out")
```
BLAST jobs are asynchronous. Check status before retrieving results. EMBL-EBI BLAST submission requires a real contact email; the bundled script reads NCBI_EMAIL or an explicit parameter.
## Conflicts
- K-Dense-AI/scientific-agent-skills pins bioservices==1.16.0 and Python >=3.9,<4; aipoch/medical-research-skills says version depends on your environment; FreedomIntelligence/OpenClaw-Medical-Skills gives no version pin.
- K-Dense-AI/scientific-agent-skills says use frmt="tsv", not "tab"; aipoch/medical-research-skills and FreedomIntelligence/OpenClaw-Medical-Skills use frmt="tab" in examples.
- K-Dense-AI/scientific-agent-skills says mapping() returns a results/failedIds envelope; aipoch/medical-research-skills and FreedomIntelligence/OpenClaw-Medical-Skills use mapping results without that envelope handling.
- FreedomIntelligence/OpenClaw-Medical-Skills includes NCBI BLAST as a core capability and says to use individual database skills for direct REST control; K-Dense-AI treats BLAST as an optional compatibility note; aipoch omits BLAST from the main example to stay lightweight.