mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-26 01:01:40 +00:00
Pharmaceutical research skill covering bioactive compound search (ChEMBL), drug-likeness screening (Lipinski Ro5 + Veber via PubChem), drug-drug interaction lookups (OpenFDA), gene-disease associations (OpenTargets GraphQL), and ADMET reasoning guidance. All free public APIs, zero auth, stdlib-only Python. Includes helper scripts for batch Ro5 screening and target-to-compound pipelines. Moved to optional-skills/research/ (niche domain skill, not built-in). Fixed: authors→author frontmatter, removed unused jq prerequisite, bare except→except Exception. Co-authored-by: bennytimz <oluwadareab12@gmail.com> Salvaged from PR #8695.
53 lines
2.2 KiB
Python
53 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
chembl_target.py — Search ChEMBL for a target and retrieve top active compounds.
|
|
Usage: python3 chembl_target.py "EGFR" --min-pchembl 7 --limit 20
|
|
No external dependencies.
|
|
"""
|
|
import sys, json, time, argparse
|
|
import urllib.request, urllib.parse, urllib.error
|
|
|
|
BASE = "https://www.ebi.ac.uk/chembl/api/data"
|
|
|
|
def get(endpoint):
|
|
try:
|
|
req = urllib.request.Request(f"{BASE}{endpoint}", headers={"Accept":"application/json"})
|
|
with urllib.request.urlopen(req, timeout=15) as r:
|
|
return json.loads(r.read())
|
|
except Exception as e:
|
|
print(f"API error: {e}", file=sys.stderr); return None
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="ChEMBL target → active compounds")
|
|
parser.add_argument("target")
|
|
parser.add_argument("--min-pchembl", type=float, default=6.0)
|
|
parser.add_argument("--limit", type=int, default=10)
|
|
args = parser.parse_args()
|
|
|
|
enc = urllib.parse.quote(args.target)
|
|
data = get(f"/target/search?q={enc}&limit=5&format=json")
|
|
if not data or not data.get("targets"):
|
|
print("No targets found."); sys.exit(1)
|
|
|
|
t = data["targets"][0]
|
|
tid = t.get("target_chembl_id","")
|
|
print(f"\nTarget: {t.get('pref_name')} ({tid})")
|
|
print(f"Type: {t.get('target_type')} | Organism: {t.get('organism','N/A')}")
|
|
print(f"\nFetching compounds with pChEMBL ≥ {args.min_pchembl}...\n")
|
|
|
|
acts = get(f"/activity?target_chembl_id={tid}&pchembl_value__gte={args.min_pchembl}&assay_type=B&limit={args.limit}&order_by=-pchembl_value&format=json")
|
|
if not acts or not acts.get("activities"):
|
|
print("No activities found."); sys.exit(0)
|
|
|
|
print(f"{'Molecule':<18} {'pChEMBL':>8} {'Type':<12} {'Value':<10} {'Units'}")
|
|
print("-"*65)
|
|
seen = set()
|
|
for a in acts["activities"]:
|
|
mid = a.get("molecule_chembl_id","N/A")
|
|
if mid in seen: continue
|
|
seen.add(mid)
|
|
print(f"{mid:<18} {str(a.get('pchembl_value','N/A')):>8} {str(a.get('standard_type','N/A')):<12} {str(a.get('standard_value','N/A')):<10} {a.get('standard_units','N/A')}")
|
|
time.sleep(0.1)
|
|
print(f"\nTotal: {len(seen)} unique molecules")
|
|
|
|
if __name__ == "__main__": main()
|