Files
drug-discovery-prompts/upstream/mims-harvard-ToolUniverse/skills/tooluniverse-binder-discovery/EXAMPLES.md

26 KiB

title, task, lineage_type, upstream_source, upstream_sha, imported_at, prompt_class, upstream_changes, author, validated
title task lineage_type upstream_source upstream_sha imported_at prompt_class upstream_changes author validated
Small Molecule Binder Discovery Examples import https://github.com/mims-harvard/ToolUniverse/blob/e2520a96/skills/tooluniverse-binder-discovery/EXAMPLES.md e2520a96 2026-06-26 prompt accepted upstream false

Small Molecule Binder Discovery Examples

Detailed workflow examples for common discovery scenarios.

Example 1: Well-Characterized Target (EGFR)

User Query: "Find novel small molecule binders for EGFR"

Phase 1: Target Validation

# Step 1.1: Resolve identifiers
uniprot_result = tu.tools.UniProt_search(query="EGFR human", organism="human", limit=5)
# → P00533 (EGFR_HUMAN)

gene_result = tu.tools.MyGene_query_genes(q="EGFR", species="human")
# → ENSG00000146648, NCBI: 1956

chembl_result = tu.tools.ChEMBL_search_targets(query="EGFR", organism="Homo sapiens")
# → CHEMBL203

# Step 1.2: Assess druggability
tractability = tu.tools.OpenTargets_get_target_tractability_by_ensemblID(
    ensemblId="ENSG00000146648"
)
# → Small molecule: bucket 1 (approved drugs exist)

druggability = tu.tools.DGIdb_get_gene_druggability(genes=["EGFR"])
# → Categories: Kinase, Clinically Actionable, 45 drugs

Report Section 1.2:

### 1.2 Druggability Assessment

| Factor | Assessment | Score | Source |
|--------|------------|-------|--------|
| Target class | Receptor tyrosine kinase | ★★★ | ChEMBL |
| Tractability bucket | 1 (approved drugs) | ★★★ | Open Targets |
| Known drugs | 15 approved | ★★★ | DGIdb |
| Binding site | ATP pocket (well-characterized) | ★★★ | PDB |

**Overall Druggability**: ★★★ Highly druggable

*Sources: Open Targets, DGIdb, ChEMBL*

Phase 2: Known Ligand Mining

# Step 2.1: Get all bioactivity data
activities = tu.tools.ChEMBL_get_target_activities(
    target_chembl_id="CHEMBL203",
    limit=500
)
# → 4,847 activity records

# Step 2.2: Filter to potent compounds
potent = [a for a in activities['activities'] 
          if a['standard_type'] in ['IC50', 'Ki'] 
          and a['standard_value'] and float(a['standard_value']) < 100]
# → 312 compounds with IC50/Ki < 100 nM

# Step 2.3: Get molecule details for top actives
top_actives = []
for activity in potent[:20]:
    mol = tu.tools.ChEMBL_get_molecule(
        molecule_chembl_id=activity['molecule_chembl_id']
    )
    top_actives.append({
        'chembl_id': activity['molecule_chembl_id'],
        'ic50': activity['standard_value'],
        'smiles': mol['molecule_structures']['canonical_smiles'],
        'max_phase': mol['max_phase']
    })

# Step 2.4: Get chemical probes
probes = tu.tools.OpenTargets_get_chemical_probes_by_target_ensemblID(
    ensemblId="ENSG00000146648"
)

Report Section 2:

### 2.1 ChEMBL Bioactivity Summary

**Total Activity Records**: 4,847
- IC50: 2,345 | Ki: 1,234 | Kd: 456 | EC50: 812

**Potency Distribution**:
| Potency Range | Count | % |
|---------------|-------|---|
| < 10 nM | 89 | 1.8% |
| 10-100 nM | 223 | 4.6% |
| 100-1000 nM | 567 | 11.7% |
| > 1000 nM | 3,968 | 81.9% |

### 2.2 Top 10 Most Potent Compounds

| Rank | Compound | ChEMBL ID | IC50 (nM) | Phase | Scaffold |
|------|----------|-----------|-----------|-------|----------|
| 1 | Osimertinib | CHEMBL3353410 | 0.5 | 4 | Pyrimidine-amine |
| 2 | Dacomitinib | CHEMBL2110732 | 0.8 | 4 | Quinazoline |
| 3 | Afatinib | CHEMBL1173655 | 1.2 | 4 | Quinazoline |
| 4 | Erlotinib | CHEMBL553 | 2.0 | 4 | Quinazoline |
| 5 | Gefitinib | CHEMBL939 | 5.0 | 4 | Quinazoline |
| ... | ... | ... | ... | ... | ... |

*Source: ChEMBL via `ChEMBL_get_target_activities` (CHEMBL203)*

Phase 3: Structure Analysis

# Step 3.1: Find PDB structures
pdb_list = tu.tools.PDB_search_similar_structures(
    query="P00533",
    type="sequence"
)
# → 156 structures

# Step 3.2: Get metadata for key structures
key_pdbs = ["1M17", "4HJO", "5UG9", "6JX4"]
for pdb_id in key_pdbs:
    metadata = tu.tools.get_protein_metadata_by_pdb_id(pdb_id=pdb_id)
    affinity = tu.tools.get_binding_affinity_by_pdb_id(pdb_id=pdb_id)

Report Section 3:

### 3.1 Available Structures

**Total PDB Structures**: 156
- With small molecule ligand: 89
- Apo structures: 34
- With peptide/protein: 33

| PDB ID | Resolution | Ligand | Affinity | Conformation |
|--------|------------|--------|----------|--------------|
| 1M17 | 2.6 Å | Erlotinib | Ki=0.4 nM | Active |
| 4HJO | 2.1 Å | Lapatinib | Ki=3 nM | Inactive |
| 5UG9 | 1.9 Å | Osimertinib | Ki=0.5 nM | Active/C797S |
| 6JX4 | 2.2 Å | Compound X | IC50=12 nM | Active |

**Best Structure for Novel Binder Design**: 5UG9 (highest resolution, relevant mutation)

Phase 4: Compound Expansion

# Step 4.1: Select diverse seeds
seeds = [
    ("CHEMBL553", "COc1cc2ncnc(Nc3ccc(C#C)c(c3)C#C)c2cc1OCCOCCOC"),  # Erlotinib scaffold
    ("CHEMBL3353410", "COc1cc(N2CCC(CC2)n2cc(nc2c2ccc(NC(=O)C=C)c(Nc3nc(ccn3)c3cccnc3)c2)C)ccc1NC(=O)C=C"),  # Osimertinib
    ("CHEMBL1779", "Fc1ccc(Nc2ncnc3cc(OCCCN4CCOCC4)c(OC)cc23)cc1Cl"),  # Gefitinib-like
]

# Step 4.2: Similarity search
all_similar = []
for seed_id, seed_smiles in seeds:
    similar = tu.tools.ChEMBL_search_similar_molecules(
        molecule=seed_smiles,
        similarity=75
    )
    all_similar.extend(similar['molecules'])
# → 892 similar compounds

# Step 4.3: PubChem expansion
pubchem_similar = tu.tools.PubChem_search_compounds_by_similarity(
    smiles=seeds[0][1],
    threshold=0.75
)
# → 456 additional compounds

# Step 4.4: Substructure search for quinazoline
substructure = tu.tools.ChEMBL_search_substructure(
    smiles="c1ccc2ncncc2c1"  # Quinazoline core
)
# → 234 quinazoline-containing compounds

# Step 4.5: Deduplicate
unique_candidates = deduplicate_by_smiles(all_similar + pubchem_similar + substructure)
# → 1,247 unique candidates

Phase 5: ADMET Filtering

# Step 5.1: Batch ADMET prediction
smiles_list = [c['smiles'] for c in unique_candidates]

# Physicochemical
physchem = tu.tools.ADMETAI_predict_physicochemical_properties(smiles=smiles_list)
# Filter: Lipinski ≤ 1, QED > 0.3
passed_physchem = [c for c in physchem if c['Lipinski_violations'] <= 1 and c['QED'] > 0.3]
# → 987 pass

# Bioavailability
bioavail = tu.tools.ADMETAI_predict_bioavailability(smiles=[c['smiles'] for c in passed_physchem])
# Filter: Oral bioavailability > 0.3
passed_bioavail = [c for c in bioavail if c['Bioavailability_Ma'] > 0.3]
# → 834 pass

# Toxicity
toxicity = tu.tools.ADMETAI_predict_toxicity(smiles=[c['smiles'] for c in passed_bioavail])
# Filter: AMES < 0.5, hERG < 0.5
passed_tox = [c for c in toxicity if c['AMES'] < 0.5 and c['hERG'] < 0.5]
# → 723 pass

# Structural alerts
final_candidates = []
for c in passed_tox:
    alerts = tu.tools.ChEMBL_search_compound_structural_alerts(smiles=c['smiles'])
    if not alerts.get('pains', []):
        final_candidates.append(c)
# → 678 pass all filters

Report Section 5:

### 5.4 Filter Summary

| Filter Stage | Input | Passed | Failed | Pass Rate |
|--------------|-------|--------|--------|-----------|
| Initial candidates | 1,247 | - | - | - |
| Physicochemical | 1,247 | 987 | 260 | 79% |
| Drug-likeness (QED) | 987 | 892 | 95 | 90% |
| Bioavailability | 892 | 834 | 58 | 93% |
| Toxicity (AMES/hERG) | 834 | 723 | 111 | 87% |
| Structural alerts | 723 | 678 | 45 | 94% |
| **Final Candidates** | **1,247** | **678** | **569** | **54%** |

**Top Failure Reasons**:
1. MW > 600 Da: 156 compounds (12.5%)
2. hERG liability (>0.5): 78 compounds (6.3%)
3. Low bioavailability (<0.3): 58 compounds (4.7%)
4. PAINS alerts: 32 compounds (2.6%)

Phase 6: Final Prioritization

Report Section 6.3:

### 6.3 Top 20 Candidate Compounds

| Rank | ID | Evidence | Sim. | ADMET | Novelty | Score | Rationale |
|------|-----|----------|------|-------|---------|-------|-----------|
| 1 | CPD-001 | ★★★ | 0.87 | 4.6 | Novel R-group | 4.5 | 87% to osimertinib, clean ADMET |
| 2 | CPD-002 | ★★☆ | 0.82 | 4.4 | Untested | 4.3 | Quinazoline analog, available |
| 3 | CPD-003 | ★★☆ | 0.79 | 4.5 | Novel core | 4.2 | Pyridine replacement |
| 4 | CPD-004 | ★★☆ | 0.81 | 4.2 | Untested | 4.1 | Improved solubility |
| 5 | CPD-005 | ★☆☆ | 0.76 | 4.3 | Novel scaffold | 4.0 | New chemotype |
| ... | ... | ... | ... | ... | ... | ... | ... |

**Scaffold Diversity**: 8 distinct scaffolds in top 20
**Commercial Availability**: 14/20 available (Enamine, MolPort)
**Estimated Hit Rate**: 20-35% based on similarity to approved drugs

*Scoring: Evidence (25%) + Similarity (25%) + ADMET (25%) + Novelty (15%) + Availability (10%)*

Example 2: Novel Target (Limited Data)

User Query: "Find small molecules for SLC7A11 (xCT transporter)"

Key Differences for Novel Targets

  1. Phase 2 will yield limited data - Few or no known ligands
  2. Rely more on structure-based - AlphaFold if no experimental structure
  3. Consider similar targets - Related transporters may have ligands
  4. Lower evidence tiers - Most candidates will be ★☆☆ or ☆☆☆

Modified Workflow

# Phase 1: Target validation
# SLC7A11: P60880 (UniProt), ENSG00000151012, limited ChEMBL data

# Phase 2: Known ligands - limited
activities = tu.tools.ChEMBL_get_target_activities(target_chembl_id="CHEMBL4523582")
# → Only 23 activity records, best IC50 = 2.5 µM

# Phase 2b: Check related targets (SLC7 family)
related_targets = ["SLC7A1", "SLC7A5", "SLC7A8"]  # Similar transporters
for target in related_targets:
    activities = tu.tools.ChEMBL_search_targets(query=target)
    # Look for ligands that might cross-react

# Phase 3: Structure - AlphaFold only
structure = tu.tools.alphafold_get_prediction(accession="P60880")
# → AF-P60880-F1 (predicted, pLDDT varies)

# Phase 4: Expand from weak actives AND related target ligands
# Use lower similarity threshold (60-70%) to find more chemotypes

# Phase 5-6: Same ADMET filtering and prioritization

Report Note for Novel Targets:

### Data Gaps & Limitations

| Gap | Impact | Mitigation |
|-----|--------|------------|
| Limited bioactivity data (23 records) | Low confidence in actives | Used related SLC7 family ligands |
| No experimental structure | Binding site uncertain | AlphaFold structure (moderate confidence) |
| Best known IC50 = 2.5 µM | Weak starting point | Prioritize diverse chemotypes |

**Recommended Strategy**: Broader screening campaign with multiple scaffolds
**Estimated Hit Rate**: 5-10% (lower confidence than well-characterized targets)

Example 3: Lead Optimization

User Query: "Find analogs of compound X (CHEMBL12345) for target Y with improved ADMET"

Focus on Narrow Expansion

# Step 1: Get reference compound
ref_compound = tu.tools.ChEMBL_get_molecule(molecule_chembl_id="CHEMBL12345")
ref_smiles = ref_compound['molecule_structures']['canonical_smiles']
ref_admet = tu.tools.ADMETAI_predict_toxicity(smiles=[ref_smiles])
# Known issue: hERG = 0.72 (liability)

# Step 2: Tight similarity search (85-95%)
similar = tu.tools.ChEMBL_search_similar_molecules(molecule=ref_smiles, similarity=85)
# → 156 close analogs

# Step 3: Predict ADMET for all
all_smiles = [m['smiles'] for m in similar['molecules']]
admet_results = tu.tools.ADMETAI_predict_toxicity(smiles=all_smiles)

# Step 4: Filter for improved hERG
improved = [m for m, a in zip(similar['molecules'], admet_results) 
            if a['hERG'] < 0.5]  # Improved from 0.72
# → 34 analogs with improved hERG

# Step 5: Check if activity maintained
# Query ChEMBL for any existing bioactivity on these compounds

Report Focus:

### Lead Optimization Summary

**Reference Compound**: CHEMBL12345
- IC50 = 45 nM (target Y)
- hERG liability = 0.72 (CONCERN)
- CYP3A4 inhibitor = 0.65 (moderate)

**Optimization Goal**: Reduce hERG while maintaining potency

### Improved Analogs

| Analog | Sim. | hERG | CYP3A4 | Modification | Activity Status |
|--------|------|------|--------|--------------|-----------------|
| CPD-A | 0.91 | 0.34 | 0.42 | N-methyl→N-H | Untested |
| CPD-B | 0.88 | 0.28 | 0.51 | Remove basic N | Untested |
| CPD-C | 0.92 | 0.41 | 0.38 | Add hydroxyl | IC50=67 nM (similar) |

**Recommended**: CPD-C (proven activity retention, improved hERG)

Example 4: NVIDIA NIM-Enhanced Workflow (CDK4 Kinase)

User Query: "Discover novel CDK4 inhibitors using all available structure prediction and docking"

Check NVIDIA NIM Availability

import os
nvidia_available = bool(os.environ.get("NVIDIA_API_KEY"))
print(f"NVIDIA NIM tools: {'Available' if nvidia_available else 'Unavailable'}")

Phase 1: Target Validation + Structure Prediction

# Step 1.1: Standard identifier resolution
uniprot_result = tu.tools.UniProt_search(query="CDK4 human", organism="human", limit=5)
# → P11802 (CDK4_HUMAN)

gene_result = tu.tools.MyGene_query_genes(q="CDK4", species="human")
# → ENSG00000135446

chembl_result = tu.tools.ChEMBL_search_targets(query="CDK4", organism="Homo sapiens")
# → CHEMBL3116

# Step 1.2: Get protein sequence
uniprot_details = tu.tools.UniProt_get_entry(accession="P11802")
cdk4_sequence = uniprot_details['sequence']

# Step 1.3: Check for existing PDB structures
pdb_structures = tu.tools.PDB_search_similar_structures(query="P11802", type="sequence")
# → 25 structures, best: 2W9Z (2.0 Å, with palbociclib)

# Step 1.4: Predict structure with NVIDIA NIM for comparison
if nvidia_available:
    predicted_structure = tu.tools.NvidiaNIM_alphafold2(
        sequence=cdk4_sequence,
        algorithm="mmseqs2",
        relax_prediction=False
    )
    # → PDB content with pLDDT scores
    # Mean pLDDT: 88.5 (high confidence)

Report Section 1.4:

### 1.4 Structure Prediction Quality

**Method**: AlphaFold2 via NVIDIA NIM
**Mean pLDDT**: 88.5 (high confidence)

| Confidence Level | Range | Fraction | Interpretation |
|------------------|-------|----------|----------------|
| Very High | ≥90 | 65.2% | Highly reliable |
| Confident | 70-90 | 28.1% | Reliable |
| Low | 50-70 | 5.8% | Use caution |
| Very Low | <50 | 0.9% | Unreliable |

**Key Binding Residue Confidence** (ATP pocket):
| Residue | Function | pLDDT |
|---------|----------|-------|
| K35 | ATP binding | 92.4 |
| E51 | Salt bridge | 89.1 |
| D99 | Catalytic | 94.2 |
| D158 | DFG motif | 91.8 |

**Recommendation**: Use experimental structure 2W9Z (2.0 Å) for docking,
predicted structure validates binding pocket geometry.

*Source: NVIDIA NIM via `NvidiaNIM_alphafold2`*

Phase 3.5: Docking Validation

# Step 3.5.1: Get reference compound (palbociclib) for validation
ref_compound = tu.tools.ChEMBL_get_molecule(molecule_chembl_id="CHEMBL1906")
palbociclib_smiles = ref_compound['molecule_structures']['canonical_smiles']

# Step 3.5.2: Get PDB structure content
pdb_content = tu.tools.get_pdb_structure_file(pdb_id="2W9Z", format="pdb")

# Step 3.5.3: Dock reference compound to validate binding pocket
if nvidia_available:
    # Option A: DiffDock (with PDB + SDF)
    validation_result = tu.tools.NvidiaNIM_diffdock(
        protein=pdb_content,
        ligand=palbociclib_sdf,  # SDF content
        num_poses=10
    )
    reference_confidence = validation_result['poses'][0]['confidence']
    # → 0.92 (excellent)
    
    # Option B: Boltz2 (from sequence + SMILES)
    boltz_result = tu.tools.NvidiaNIM_boltz2(
        polymers=[{"molecule_type": "protein", "sequence": cdk4_sequence}],
        ligands=[{"smiles": palbociclib_smiles}],
        sampling_steps=50,
        diffusion_samples=1
    )
    # → Complex structure with pTM=0.85, ipTM=0.78

Report Section 3.5:

### 3.5 Docking Validation Results

**Reference Compound**: Palbociclib (CHEMBL1906)
**Known IC50**: 11 nM

**DiffDock Validation**:
| Metric | Value | Interpretation |
|--------|-------|----------------|
| Best Pose Confidence | 0.92 | Excellent |
| Poses in ATP pocket | 10/10 | Correct binding mode |
| RMSD to crystal pose | 1.2 Å | Good agreement |

**Boltz2 Validation**:
| Metric | Value | Interpretation |
|--------|-------|----------------|
| pTM | 0.85 | High structure confidence |
| ipTM | 0.78 | Good interface prediction |
| Aggregate Score | 0.81 | Reliable complex |

**Validation Status**: ✓ Binding pocket correctly captured by both methods

*Source: NVIDIA NIM via `NvidiaNIM_diffdock`, `NvidiaNIM_boltz2`*

Phase 4.4: De Novo Molecule Generation

# Step 4.4.1: Identify seed scaffolds from top actives
# Palbociclib scaffold: pyrido[2,3-d]pyrimidin-7-one core
seed_smiles = "CC(=O)c1c(C)c2cnc(Nc3ccc(N4CCNCC4)cn3)nc2n(C2CCCC2)c1=O"

# Step 4.4.2: Design masked SMILES for scaffold hopping
# Vary the piperazine tail and add positions on pyridine
masked_smiles = "CC(=O)c1c(C)c2cnc(Nc3ccc([*{4-10}])c([*{1-3}])n3)nc2n(C2CCCC2)c1=O"

# Step 4.4.3: Generate with GenMol
if nvidia_available:
    genmol_result = tu.tools.NvidiaNIM_genmol(
        smiles=masked_smiles,
        num_molecules=100,
        temperature=2.0,
        scoring="QED"
    )
    # → 100 generated molecules with QED scores
    generated_mols = genmol_result['molecules']
    
    # Filter by basic criteria
    good_qed = [m for m in generated_mols if m['QED'] > 0.5]
    # → 78 pass QED filter

# Step 4.4.4: Alternative with MolMIM (close analogs)
if nvidia_available:
    molmim_result = tu.tools.NvidiaNIM_molmim(
        smi=seed_smiles,
        num_molecules=50,
        algorithm="CMA-ES"
    )
    # → 50 optimized analogs

Report Section 4.4:

### 4.4 De Novo Generation Results

**Seed Scaffold**: Pyrido[2,3-d]pyrimidin-7-one (from palbociclib)
**Method**: GenMol via NVIDIA NIM

**Masked Positions**:
- Position 1: Piperazine tail region `[*{4-10}]`
- Position 2: Pyridine substituent `[*{1-3}]`

| Metric | GenMol | MolMIM |
|--------|--------|--------|
| Molecules Generated | 100 | 50 |
| Passing QED > 0.5 | 78 (78%) | 42 (84%) |
| Mean QED Score | 0.62 | 0.68 |
| Unique Scaffolds | 8 | 3 |
| Mean LogP | 3.8 | 4.1 |

**Top Generated Compounds (GenMol)**:
| ID | SMILES (abbreviated) | QED | LogP | Modification |
|----|---------------------|-----|------|--------------|
| GEN-001 | ...Nc3ccc(N4CCN(C)CC4)c(F)n3... | 0.74 | 3.2 | Methyl-piperazine + F |
| GEN-002 | ...Nc3ccc(N4CCOCC4)c(Cl)n3... | 0.71 | 3.5 | Morpholine + Cl |
| GEN-003 | ...Nc3ccc(NC4CCNCC4)cn3... | 0.69 | 2.9 | Piperidine amine |

**Next Step**: Pass all 120 generated molecules to Phase 5 (ADMET filtering)

*Source: NVIDIA NIM via `NvidiaNIM_genmol`, `NvidiaNIM_molmim`*

Phase 6: Candidate Docking

# After ADMET filtering (Phase 5), dock all candidates
admet_passed = 67  # Compounds passing all ADMET filters

if nvidia_available:
    # Get reference score
    reference_confidence = 0.92  # From Phase 3.5
    
    # Dock all candidates
    docking_results = []
    for compound in admet_passed_compounds:
        result = tu.tools.NvidiaNIM_diffdock(
            protein=pdb_content,
            ligand=compound['sdf'],
            num_poses=5
        )
        
        best_confidence = result['poses'][0]['confidence']
        vs_reference = (best_confidence / reference_confidence - 1) * 100
        
        docking_results.append({
            'id': compound['id'],
            'smiles': compound['smiles'],
            'confidence': best_confidence,
            'vs_reference_pct': vs_reference,
            'evidence_tier': assign_tier(best_confidence, reference_confidence)
        })
    
    # Sort by confidence
    ranked = sorted(docking_results, key=lambda x: x['confidence'], reverse=True)

Report Section 6 (Final):

### 6. Final Candidate Ranking

**Scoring Method**: Docking (40%) + ADMET (30%) + Similarity (20%) + Novelty (10%)
**Reference**: Palbociclib (confidence: 0.92)

| Rank | ID | Evidence | Docking | vs Ref | ADMET | Score | Source |
|------|-----|----------|---------|--------|-------|-------|--------|
| 1 | GEN-001 | ★★★★ | 0.95 | +3.3% | 4.5 | 4.7 | GenMol |
| 2 | CPD-042 | ★★★ | 0.91 | -1.1% | 4.6 | 4.5 | ChEMBL (IC50=18nM) |
| 3 | GEN-002 | ★★★★ | 0.94 | +2.2% | 4.2 | 4.4 | GenMol |
| 4 | CPD-108 | ★★☆ | 0.89 | -3.3% | 4.4 | 4.2 | PubChem |
| 5 | GEN-015 | ★★☆ | 0.90 | -2.2% | 4.3 | 4.1 | MolMIM |

**Key Findings**:
- 2 de novo generated compounds outperform reference (★★★★)
- 3/5 top candidates from AI generation
- GEN-001 shows novel modification with improved docking score

**Methods Summary**:
| Step | Tool | Purpose |
|------|------|---------|
| Sequence retrieval | UniProt_search | Get CDK4 sequence |
| Structure prediction | NvidiaNIM_alphafold2 | Validate binding pocket |
| Docking validation | NvidiaNIM_diffdock | Confirm pose accuracy |
| Known ligands | ChEMBL_get_target_activities | Mining actives |
| De novo generation | NvidiaNIM_genmol | Novel scaffold exploration |
| ADMET filtering | ADMETAI_predict_* | Drug-likeness |
| Candidate docking | NvidiaNIM_diffdock | Final scoring |

*Full methods and parameters available in appendix*

Common Pitfalls and Solutions

Pitfall 1: Silent Tool Failures

Problem: ChEMBL returns empty for wrong parameter name

# WRONG - returns empty
tu.tools.ChEMBL_get_target_activities(chembl_target_id="CHEMBL203")

# CORRECT
tu.tools.ChEMBL_get_target_activities(target_chembl_id="CHEMBL203")

Solution: Always verify tool parameters before first use.

Pitfall 2: ADMET Batch Size

Problem: Sending 1000+ SMILES crashes or times out

# WRONG - too many at once
tu.tools.ADMETAI_predict_toxicity(smiles=all_1000_smiles)

# CORRECT - batch in chunks
for i in range(0, len(all_smiles), 100):
    batch = all_smiles[i:i+100]
    results = tu.tools.ADMETAI_predict_toxicity(smiles=batch)
    process_results(results)

Pitfall 3: Missing Deduplication

Problem: Same compound from multiple sources counted multiple times

# Track by canonical SMILES or InChIKey
seen_inchikeys = set()
unique_candidates = []
for compound in all_candidates:
    inchikey = get_inchikey(compound['smiles'])  # Or use canonical SMILES
    if inchikey not in seen_inchikeys:
        seen_inchikeys.add(inchikey)
        unique_candidates.append(compound)

Pitfall 4: Not Checking Existing Data

Problem: Recommending "novel" compounds that are already tested

# Check if compound already has bioactivity for target
for candidate in candidates:
    existing = tu.tools.ChEMBL_search_activities(
        molecule_chembl_id=candidate['chembl_id'],
        target_chembl_id=target_id
    )
    if existing['activities']:
        candidate['status'] = 'ALREADY_TESTED'
        candidate['known_ic50'] = existing['activities'][0]['standard_value']
    else:
        candidate['status'] = 'NOVEL'

Pitfall 5: NVIDIA NIM API Key Not Set

Problem: Tools fail silently or return errors

# WRONG - No fallback when NIM unavailable
result = tu.tools.NvidiaNIM_alphafold2(sequence=seq)
# → Error: NVIDIA_API_KEY not set

# CORRECT - Check availability first
import os
nvidia_available = bool(os.environ.get("NVIDIA_API_KEY"))

if nvidia_available:
    result = tu.tools.NvidiaNIM_alphafold2(sequence=seq)
else:
    print("NVIDIA NIM unavailable, using AlphaFold DB")
    result = tu.tools.alphafold_get_prediction(accession=uniprot_id)

Pitfall 6: GenMol Mask Syntax Errors

Problem: Invalid mask syntax causes generation failure

# WRONG - Missing mask or wrong syntax
tu.tools.NvidiaNIM_genmol(smiles="CCCc1ccc(O)cc1")  # No mask
tu.tools.NvidiaNIM_genmol(smiles="CCCc1ccc([*])cc1")  # No size range
tu.tools.NvidiaNIM_genmol(smiles="CCCc1ccc([*{1,3}])cc1")  # Wrong separator

# CORRECT - Proper mask syntax with dash separator
tu.tools.NvidiaNIM_genmol(
    smiles="CCCc1ccc([*{1-3}])cc1",  # [*{min-max}] format
    num_molecules=50,
    temperature=2.0
)

Pitfall 7: Boltz2 Polymer Format Errors

Problem: Wrong input format for protein-ligand complex

# WRONG - Direct sequence input
tu.tools.NvidiaNIM_boltz2(sequence="MKTAYIAK...", smiles="CCO")

# CORRECT - Use polymers and ligands lists
tu.tools.NvidiaNIM_boltz2(
    polymers=[{"molecule_type": "protein", "sequence": "MKTAYIAK..."}],
    ligands=[{"smiles": "CCO"}],
    sampling_steps=50,
    diffusion_samples=1
)

Pitfall 8: Over-relying on Docking Scores

Problem: Ranking by docking alone ignores ADMET and novelty

# WRONG - Rank by docking only
ranked = sorted(candidates, key=lambda x: x['docking_score'], reverse=True)

# CORRECT - Multi-factor scoring
def calculate_score(c):
    return (
        c['docking_score'] * 0.40 +      # Docking
        c['admet_score'] * 0.30 +         # ADMET
        c['similarity_score'] * 0.20 +    # Evidence
        c['novelty_score'] * 0.10         # Novelty
    )

ranked = sorted(candidates, key=calculate_score, reverse=True)

Pitfall 9: Not Reporting pLDDT for Predicted Structures

Problem: Using predicted structure without confidence assessment

# WRONG - Use structure without quality check
structure = tu.tools.NvidiaNIM_alphafold2(sequence=seq)
# Immediately use for docking...

# CORRECT - Parse and report confidence
structure = tu.tools.NvidiaNIM_alphafold2(sequence=seq)
plddt_scores = parse_plddt_from_pdb(structure['pdb_content'])
mean_plddt = sum(plddt_scores) / len(plddt_scores)

# Report in output
print(f"Mean pLDDT: {mean_plddt:.1f}")
if mean_plddt < 70:
    print("WARNING: Low confidence structure, binding site predictions may be unreliable")
    
# Check binding residue confidence specifically
binding_residues = [10, 15, 50, 80]  # Known binding site residues
for res in binding_residues:
    if plddt_scores[res-1] < 70:
        print(f"WARNING: Binding residue {res} has low confidence ({plddt_scores[res-1]:.1f})")