Skill: hollyya/chembl-query (version 1.0.0)

--- name: chembl-query description: > Query ChEMBL database for bioactivity data on drug-like compounds. Use this skill when: (1) Finding compounds active against a protein target (target-based search), (2) Getting bioactivity profile for a molecule (molecule-based search), (3) Finding drugs for a disease indication (indication-based search). license: MIT category: knowledge-retrieval tags: [chembl, bioactivity, drug-discovery, target, indication] --- # ChEMBL Query Query ChEMBL database for bioactivity data on drug-like compounds. ## When to Use - Find compounds active against a protein target (target-based search) - Get bioactivity profile for a molecule (molecule-based search) - Find drugs for a disease indication (indication-based search) ## Workflow ### Use Case 1: Target-Based Compound Search Find compounds with activity against a protein target. ```python from open_biomed.tools.tool_registry import TOOLS tool = TOOLS["chembl_query"] # Search by target name results, _ = tool.run( query_type="target", target_name="EGFR", standard_type="IC50", standard_value_lte=100, # nM limit=20 ) # Or search by UniProt ID results, _ = tool.run( query_type="target", uniprot_id="P00533", standard_type="IC50", limit=20 ) ``` ### Use Case 2: Molecule Bioactivity Profile Get all known targets and activity data for a compound. ```python # Search by molecule name results, _ = tool.run( query_type="molecule", molecule_name="imatinib", limit=50 ) # Or search by SMILES results, _ = tool.run( query_type="molecule", smiles="CC(=O)Oc1ccccc1C(=O)O", limit=20 ) # Or search by ChEMBL ID results, _ = tool.run( query_type="molecule", chembl_id="CHEMBL25", limit=20 ) ``` ### Use Case 3: Disease/Indication-Based Drug Search Find drugs studied for a specific disease. ```python # Find all drugs for diabetes results, _ = tool.run( query_type="indication", disease="diabetes", limit=50 ) # Filter for approved drugs only (max_phase=4) results, _ = tool.run( query_type="indication", disease="diabetes", max_phase=4, # Approved drugs only limit=20 ) ``` ## Expected Outputs | Query Type | Output Fields | |------------|---------------| | Target | `molecule_chembl_id`, `molecule_name`, `target_chembl_id`, `target_name`, `standard_type`, `standard_value`, `standard_units`, `pchembl_value` | | Molecule | `molecule_chembl_id`, `molecule_name`, `target_chembl_id`, `target_name`, `target_organism`, `standard_type`, `standard_value`, `standard_units`, `pchembl_value` | | Indication | `molecule_chembl_id`, `molecule_name`, `indication`, `max_phase_for_ind`, `phase_description` | ## Score Interpretation ### Activity Values | pChEMBL Value | IC50/Ki Approx | Interpretation | |---------------|----------------|----------------| | > 9 | < 1 nM | Extremely potent | | 8-9 | 1-10 nM | Very potent | | 7-8 | 10-100 nM | Potent | | 6-7 | 100 nM - 1 uM | Moderately active | | 5-6 | 1-10 uM | Weakly active | | < 5 | > 10 uM | Inactive | ### Clinical Phase | Phase | Description | |-------|-------------| | 0 | Preclinical | | 1 | Phase I (safety) | | 2 | Phase II (efficacy) | | 3 | Phase III (large-scale) | | 4 | Approved | ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `query_type` | str | "target", "molecule", or "indication" | | `target_name` | str | Target name (e.g., "EGFR", "BACE1") | | `uniprot_id` | str | UniProt accession (e.g., "P00533") | | `molecule_name` | str | Molecule name (e.g., "aspirin") | | `smiles` | str | SMILES string | | `chembl_id` | str | ChEMBL ID (e.g., "CHEMBL25") | | `disease` | str | Disease name (e.g., "diabetes") | | `standard_type` | str | Activity type (e.g., "IC50", "Ki", "EC50") | | `standard_value_lte` | float | Max activity value (nM) | | `max_phase` | int | Minimum clinical phase (0-4) | | `limit` | int | Max results (default: 50) | ## Error Handling | Error | Solution | |-------|----------| | Target not found | Try alternative names or UniProt ID | | No activity data | Target may not have curated bioactivity data | | Molecule not found | Verify SMILES or try molecule name | | No indication results | Try simpler disease terms (e.g., "neoplasm" instead of "cancer") | | Timeout | Reduce limit parameter | ## Available Tools | Tool Name | Purpose | |-----------|---------| | `chembl_query` | Unified ChEMBL query interface | See `examples/basic_example.py` for complete runnable examples.

path: examples/basic_example.py
content: """
ChEMBL Query Examples

This script demonstrates all three query types for the ChEMBL query skill.

Run from the OpenBioMed root directory:
    python skills/chembl-query/examples/basic_example.py
"""

import os
import sys

# Add the OpenBioMed root to path if running from skills directory
script_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = os.path.dirname(os.path.dirname(os.path.dirname(script_dir)))
if root_dir not in sys.path:
    sys.path.insert(0, root_dir)

import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

from open_biomed.tools.tool_registry import TOOLS


def example_target_search():
    """Find potent EGFR inhibitors."""
    print("=" * 60)
    print("Example 1: Target-Based Compound Search (EGFR)")
    print("=" * 60)

    tool = TOOLS["chembl_query"]

    results, _ = tool.run(
        query_type="target",
        target_name="EGFR",
        standard_type="IC50",
        standard_value_lte=100,  # Sub-100 nM potency
        limit=10
    )

    print(f"\nFound {len(results)} potent EGFR inhibitors (IC50 < 100 nM):\n")
    for r in results:
        name = r.get("molecule_name") or r["molecule_chembl_id"]
        value = r.get("standard_value", "N/A")
        units = r.get("standard_units", "")
        pchembl = r.get("pchembl_value", "N/A")
        print(f"  {name:<25} IC50={value} {units}  pChEMBL={pchembl}")

    return results


def example_molecule_search():
    """Get bioactivity profile for imatinib."""
    print("\n" + "=" * 60)
    print("Example 2: Molecule Bioactivity Profile (Imatinib)")
    print("=" * 60)

    tool = TOOLS["chembl_query"]

    results, _ = tool.run(
        query_type="molecule",
        molecule_name="imatinib",
        limit=20
    )

    print(f"\nFound {len(results)} activity records for imatinib:\n")

    # Group by target
    targets = {}
    for r in results:
        target = r.get("target_name", "Unknown")
        if target not in targets:
            targets[target] = []
        targets[target].append(r)

    for target, activities in list(targets.items())[:5]:
        print(f"  Target: {target}")
        for act in activities[:2]:
            act_type = act.get("standard_type", "N/A")
            value = act.get("standard_value", "N/A")
            units = act.get("standard_units", "")
            print(f"    - {act_type}={value} {units}")
        print()

    return results


def example_smiles_search():
    """Search molecule by SMILES."""
    print("=" * 60)
    print("Example 3: Molecule Search by SMILES (Aspirin)")
    print("=" * 60)

    tool = TOOLS["chembl_query"]

    aspirin_smiles = "CC(=O)Oc1ccccc1C(=O)O"

    results, _ = tool.run(
        query_type="molecule",
        smiles=aspirin_smiles,
        limit=10
    )

    if results:
        print(f"\nFound {len(results)} activity records for aspirin (CHEMBL25):\n")
        for r in results[:5]:
            target = r.get("target_name", "Unknown")[:30]
            act_type = r.get("standard_type", "N/A")
            value = r.get("standard_value", "N/A")
            print(f"  {target:<30} {act_type}={value}")
    else:
        print("No results found")

    return results


def example_indication_search():
    """Find approved drugs for diabetes."""
    print("\n" + "=" * 60)
    print("Example 4: Disease Indication Search (Diabetes)")
    print("=" * 60)

    tool = TOOLS["chembl_query"]

    # Find approved diabetes drugs
    results, _ = tool.run(
        query_type="indication",
        disease="diabetes",
        max_phase=4,  # Approved only
        limit=20
    )

    print(f"\nFound {len(results)} approved diabetes drugs:\n")
    for r in results[:10]:
        name = r.get("molecule_name") or r["molecule_chembl_id"]
        indication = r.get("indication", "")
        phase = r.get("phase_description", "")
        print(f"  {name:<20} [{phase}] {indication}")

    return results


def example_uniprot_search():
    """Search target by UniProt ID."""
    print("\n" + "=" * 60)
    print("Example 5: Target Search by UniProt ID (P04637 = TP53)")
    print("=" * 60)

    tool = TOOLS["chembl_query"]

    results, _ = tool.run(
        query_type="target",
        uniprot_id="P04637",  # TP53
        standard_type="IC50",
        limit=10
    )

    print(f"\nFound {len(results)} compounds tested against TP53:\n")
    for r in results[:5]:
        name = r.get("molecule_name") or r["molecule_chembl_id"]
        act_type = r.get("standard_type", "N/A")
        value = r.get("standard_value", "N/A")
        units = r.get("standard_units", "")
        print(f"  {name:<25} {act_type}={value} {units}")

    return results


if __name__ == "__main__":
    example_target_search()
    example_molecule_search()
    example_smiles_search()
    example_indication_search()
    example_uniprot_search()

    print("\n" + "=" * 60)
    print("All examples completed successfully!")
    print("=" * 60)


path: references/api_endpoints.md
content: # ChEMBL API Reference

## API Endpoints

**Base URL:** `https://www.ebi.ac.uk/chembl/api/data`

### Target Endpoints

| Endpoint | Description |
|----------|-------------|
| `/target/search.json?q={query}` | Search targets by name |
| `/target/{chembl_id}.json` | Get target by ChEMBL ID |
| `/target?target_chembl_id__exact={uniprot}.json` | Get target by UniProt ID |

### Molecule Endpoints

| Endpoint | Description |
|----------|-------------|
| `/molecule/search.json?q={name}` | Search molecules by name |
| `/molecule/filter.json?molecule_structures__canonical_smiles__exact={smiles}` | Search by exact SMILES |
| `/molecule/{chembl_id}.json` | Get molecule by ChEMBL ID |

### Activity Endpoints

| Endpoint | Description |
|----------|-------------|
| `/activity.json?target_chembl_id={id}` | Get activities for target |
| `/activity.json?molecule_chembl_id={id}` | Get activities for molecule |

### Drug Indication Endpoints

| Endpoint | Description |
|----------|-------------|
| `/drug_indication.json?mesh_heading__icontains={term}` | Search by disease name |

## Common Filters

### Activity Filters

| Filter | Description | Example |
|--------|-------------|---------|
| `standard_type` | Activity type | `IC50`, `Ki`, `EC50`, `Kd` |
| `standard_value__lte` | Max value (nM) | `1000` |
| `standard_value__gte` | Min value (nM) | `10` |
| `pchembl_value__gte` | Min pChEMBL | `7` |

### Indication Filters

| Filter | Description | Example |
|--------|-------------|---------|
| `mesh_heading__icontains` | Disease name search | `diabetes` |
| `max_phase_for_ind` | Clinical phase | `4` (approved) |

## Response Format

### Activity Response Fields

```json
{
  "molecule_chembl_id": "CHEMBL25",
  "molecule_pref_name": "ASPIRIN",
  "target_chembl_id": "CHEMBL240",
  "target_pref_name": "Cyclooxygenase-2",
  "target_organism": "Homo sapiens",
  "standard_type": "IC50",
  "standard_value": "4260",
  "standard_units": "nM",
  "pchembl_value": "5.37",
  "assay_chembl_id": "CHEMBL644534",
  "assay_description": "Inhibition of COX-2..."
}
```

### Drug Indication Response Fields

```json
{
  "molecule_chembl_id": "CHEMBL1073",
  "molecule_pref_name": "GLIPIZIDE",
  "mesh_heading": "Diabetes Mellitus",
  "max_phase_for_ind": "4.0",
  "efo_term": "diabetes mellitus",
  "drugind_id": "12345"
}
```

## Rate Limits

- Default rate limit: 5 requests per second
- Use `limit` parameter to control result size
- Large result sets are paginated

## Common Issues

### SMILES Search Returns No Results

**Problem:** Exact SMILES match fails

**Solution:**
1. Ensure SMILES is canonical (use RDKit to standardize)
2. Try molecule name search instead
3. Check for stereochemistry differences

### Target Search Returns Wrong Target

**Problem:** Generic name matches multiple targets

**Solution:**
1. Use UniProt ID for precise matching
2. Specify `standard_type` to filter relevant activities
3. Check target organism if needed

### Disease Search Returns No Results

**Problem:** "breast cancer" returns no results

**Solution:**
1. Use simpler terms: "breast" or "neoplasm"
2. ChEMBL uses MeSH headings, not common names
3. Check `efo_term` field for alternative disease names

## Related Resources

- [ChEMBL Web Services Documentation](https://chembl.gitbook.io/chembl-interface-documentation/web-resource-api)
- [ChEMBL API Explorer](https://www.ebi.ac.uk/chembl/api/data/docs)
- [ChEMBL Beaker (Utility Services)](https://chembl.gitbook.io/chembl-interface-documentation/chEMBL-beaker)


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)