chemoinformatics/pharmacophore-modeling/SKILL.md
Builds and applies 3D pharmacophore models using RDKit Pharm3D, the apo2ph4 receptor-based workflow (Heider et al. 2023), Pharmer / Pharmit for search, and PharmacoForge for protein-pocket-conditioned pharmacophore generation (Flynn et al. 2025), covering ligand-based pharmacophores from active-set alignment and receptor-based pharmacophores from binding-pocket geometry. Explicitly handles feature types, geometric tolerances, partial matching, and pharmacophore-based virtual screening. Use when identifying scaffold-hopping candidates, building shape-and-feature search queries, or transferring SAR across chemotypes.
npx skillsauth add GPTomics/bioSkills bio-pharmacophore-modelingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference examples tested with: RDKit 2024.09+, Pharmit web service, and PLIP 2.4+ (interaction analysis). Verify the deployed Pharmit/Pharmer interface and query format before automation.
Before using code patterns, verify installed versions match. If versions differ:
pip show rdkit then help(rdkit.Chem.Pharm3D) to check signaturesIf code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
Build 3D pharmacophore queries that capture the essential interaction features of a ligand-target binding event. A pharmacophore is the spatial arrangement of pharmacophore features (donor, acceptor, hydrophobe, aromatic, charged) sufficient for activity, abstracted from any specific chemotype. Use pharmacophores for scaffold hopping, virtual-screening prefilters, and cross-target SAR transfer. Derive interaction features directly from a co-crystal when available, use apo2ph4 to derive models from an apo pocket (Heider et al. 2023), or align known actives for a ligand-based model. PharmacoForge generates candidate 3D pharmacophores conditioned on a protein pocket; those pharmacophores can then retrieve matching molecules from a library (Flynn et al. 2025).
For 2D scaffold-based searches, see chemoinformatics/scaffold-analysis. For 3D shape similarity, see chemoinformatics/shape-similarity. For protein-ligand interaction analysis, see chemoinformatics/virtual-screening.
| Feature | Common shorthand | Definition | Geometric tolerance | |---------|------------|------------|----------------------| | H-bond donor | D | -OH, -NH | 1.0-1.5 Å | | H-bond acceptor | A | sp2 O / N (lone pair) | 1.0-1.5 Å | | Hydrophobe | H | sp3 C / aromatic ring centroid | 1.5-2.0 Å | | Aromatic ring | R | Aromatic ring centroid + normal | 1.0-1.5 Å | | Positive ionizable | P | -NH3+, -NR3+ | 1.0-1.5 Å | | Negative ionizable | N | -COO-, -SO3- | 1.0-1.5 Å | | Halogen | X | Cl, Br, I (halogen bond donor) | 1.0-1.5 Å | | Metal coordination | M | sp/sp2 N/O near metal | 0.5-1.0 Å |
Tolerances are pharmacophore-feature distance windows in the search. Tighter tolerances = fewer hits but more specific.
The ranges in this table are repository starting heuristics, not universal feature tolerances. Set final bounds from aligned-feature variability, coordinate uncertainty, and retrospective validation for the selected search engine.
The one-letter labels above are human-readable shorthand, not RDKit API codes. RDKit's shipped BaseFeatures.fdef uses family names such as Donor, Acceptor, Hydrophobe, Aromatic, PosIonizable, and NegIonizable. Its default feature definitions do not provide every halogen-bond or metal-coordination model; add and validate project-specific feature definitions when those interactions matter.
| Method | Origin | Use case | Fails when | |--------|--------|----------|------------| | Ligand-based (LBP) | Catalyst, MOE, RDKit Pharm3D | Multiple actives, no crystal | <3 actives; flexible actives | | Receptor-based (RBP) | apo2ph4, LigandScout, PLIP | Co-crystal or a defined apo pocket | Uncertain pocket conformation | | Common pharmacophore | Validated alignment/feature-consensus workflow; RDKit can represent and query the resulting model | Consensus from active set | Diverse actives or uncertain bioactive conformers confound alignment | | Pocket-conditioned generation (PharmacoForge) | Flynn et al. 2025 | Generate candidate pharmacophores from a protein pocket | Does not directly generate molecules; pretrained model required | | Active learning pharmacophore | Catalyst variant | Iterative refinement | Custom; not standard |
| Scenario | Method | Tools | |----------|--------|-------| | Co-crystal structure available | Interaction-derived receptor model | PLIP or LigandScout + Pharmit | | Apo structure with a defined pocket | Apo receptor model | apo2ph4; export LigandScout PML | | Multiple active compounds, no crystal | Ligand-based common pharmacophore | Alignment plus consensus-feature derivation in validated custom or external tooling; RDKit Pharm3D can apply the resulting model | | Single active compound | Single-conformer pharmacophore | RDKit Pharm3D from bioactive conformer | | Scaffold hopping prospective | Receptor-based + shape filter | apo2ph4 or interaction-derived model + shape search | | Cross-target SAR transfer | Common pharmacophore across targets | Manual + LigandScout | | Generate pocket-conditioned pharmacophores | PharmacoForge | Diffusion model followed by library retrieval | | Library pre-filtering | Pharmacophore screen | Pharmit search |
Goal: Derive a common pharmacophore from aligned bioactive conformers, then apply that established model to candidate molecules.
Approach: Consensus derivation is a separate modeling step: select or generate plausible bioactive conformers, align them using a documented method, identify conserved feature correspondences, and estimate distance bounds or tolerances. RDKit does not provide a single EmbedPharmacophore call that performs those steps. EmbedPharmacophore instead generates conformations of a molecule that satisfy an already defined pharmacophore.
from rdkit import Chem, Geometry
from rdkit.Chem import ChemicalFeatures
from rdkit.Chem.Pharm3D import EmbedLib, Pharmacophore
from rdkit.RDPaths import RDDataDir
import os
fdef_file = os.path.join(RDDataDir, 'BaseFeatures.fdef')
factory = ChemicalFeatures.BuildFeatureFactory(fdef_file)
# This is an already defined model. Coordinates and bounds must come from a
# validated consensus-derivation workflow or another justified source. RDKit
# requires FreeChemicalFeature objects, not feature-family strings.
query_features = [
ChemicalFeatures.FreeChemicalFeature(
'Aromatic', Geometry.Point3D(0.0, 0.0, 0.0)),
ChemicalFeatures.FreeChemicalFeature(
'Donor', Geometry.Point3D(4.0, 0.0, 0.0)),
]
pharmacophore = Pharmacophore.Pharmacophore(query_features)
pharmacophore.setLowerBound(0, 1, 3.5)
pharmacophore.setUpperBound(0, 1, 5.0)
target = Chem.AddHs(Chem.MolFromSmiles('c1ccc(cc1)CCN'))
can_match, feature_matches = EmbedLib.MatchPharmacophoreToMol(
target, factory, pharmacophore)
if can_match:
atom_match = tuple(tuple(matches[0].GetAtomIds())
for matches in feature_matches)
_, embeddings, n_failed = EmbedLib.EmbedPharmacophore(
target, atom_match, pharmacophore, randomSeed=23, silent=True)
BaseFeatures.fdef (RDKit-shipped) defines feature SMARTS and is a useful starting feature taxonomy. The code above demonstrates applying an existing two-feature model; it does not infer a consensus model from active compounds.
Goal: Derive a pharmacophore from a protein binding-pocket structure without requiring a bound ligand.
Approach: Identify donor, acceptor, and hydrophobic hot spots from apo-pocket geometry, cluster them, and assemble candidate pharmacophores. Heider et al. describe apo2ph4 in J. Chem. Inf. Model. 63:101-110 (2023). Use the source release's documented scripts and environment rather than assuming a packaged apo2ph4 command: the published workflow writes LigandScout PML output, not a generic .ph4 file. Treat conversion to Pharmit, Pharmer, MOE, or Phase as a separate, explicitly validated step because pharmacophore formats are not interchangeable.
When a co-crystal ligand is available, derive pharmacophore directly from the ligand binding pose: each ligand feature in contact with a complementary protein residue is part of the pharmacophore.
from plip.basic import config
from plip.structure.preparation import PDBComplex
mol_complex = PDBComplex()
mol_complex.load_pdb('complex.pdb')
mol_complex.analyze()
for site in mol_complex.interaction_sets.values():
for interaction in site.all_itypes:
# Objects are interaction-class-specific. Inspect the documented fields
# for HydrophobicContact, HydrogenBond, PiStacking, SaltBridge, etc.;
# there is no universal `.type` or `.ligatom.coords` interface.
interaction_class = type(interaction).__name__
print(interaction_class, interaction)
PLIP exposes typed interaction records with class-specific ligand/protein atoms and coordinates. Map those records to pharmacophore features explicitly and retain the interaction class and source atom identifiers.
For library screening, configure feature types, centers, radii, and optional shape constraints in Pharmit, or use a Pharmer database and query produced in the format required by the installed release. Do not pass LigandScout PML or a vendor .ph4 file directly unless the selected interface documents that import path. Pharmit reported searching millions of conformers in seconds to minutes; actual runtime depends on query selectivity, database size, and deployment (Sunseri & Koes 2016).
Evaluate a pharmacophore by:
def pharmacophore_enrichment(query_pharmacophore, actives, inactives,
matches_pharmacophore):
"""Return active/inactive match-rate enrichment for a supplied matcher."""
if not actives or not inactives:
raise ValueError('actives and inactives must both be non-empty')
n_active_match = sum(
bool(matches_pharmacophore(mol, query_pharmacophore))
for mol in actives)
n_inactive_match = sum(
bool(matches_pharmacophore(mol, query_pharmacophore))
for mol in inactives)
active_rate = n_active_match / len(actives)
inactive_rate = n_inactive_match / len(inactives)
return float('inf') if inactive_rate == 0 else active_rate / inactive_rate
For this repository, enrichment >=5x may be used as a starting triage heuristic only after the active/decoy construction and matching policy are documented. Report the full metric and uncertainty, and calibrate the acceptance threshold on the project dataset.
PharmacoForge (Flynn et al. 2025) applies a diffusion model to a protein pocket and generates candidate 3D pharmacophores. It does not directly generate molecular structures from an input pharmacophore. The validated workflow is:
The paper compares pharmacophore and downstream retrieval performance with other pocket-based approaches; it does not support a drug-likeness or novelty comparison with REINVENT.
| Method | Captures | Best for | |--------|----------|----------| | ECFP4 Tanimoto | Local atom environments | Lead optimization (same series) | | FCFP4 Tanimoto | Pharmacophore-equivalent atoms | Loose similarity in series | | Shape similarity (ROCS) | 3D shape volume | Scaffold hopping by shape | | Pharmacophore | Discrete features in space | Scaffold hopping with feature specificity | | Combined (Tanimoto + shape) | Multi-objective | Production VS |
Pharmacophore is more interpretable than shape: a hit explains why it matched (donor at position X, hydrophobe at position Y).
Trigger: Active set spans multiple scaffolds with different bound conformations.
Mechanism: No common pharmacophore exists; algorithm forces non-consensus features.
Symptom: Pharmacophore matches no actives in retrospective.
Fix: Cluster actives by scaffold first; derive per-cluster pharmacophore.
Trigger: Protein in apo form (no bound ligand).
Mechanism: Side-chain rotamers differ between apo and holo; "binding site" geometry is wrong.
Symptom: Pharmacophore inferred from apo doesn't match holo experimental data.
Fix: Use AlphaFold3 / Boltz-1 to predict holo conformation; derive pharmacophore from predicted holo.
Trigger: Active aligned to its first generated conformer, not bioactive conformer.
Mechanism: Crystal structure not available; generated conformer may not be the bound one.
Symptom: Pharmacophore inconsistent across runs (different starting conformer chosen).
Fix: Use conformer ensemble; align all to common scaffold; choose conformer most consistent with other actives.
Trigger: Default geometric tolerance < 0.5 Å.
Mechanism: Real bioactive conformers have flexibility; rigid pharmacophore filters most molecules out.
Symptom: Search returns zero hits.
Fix: Use tolerance 1.0-1.5 Å for drug-like; up to 2 Å for flexible peptide-like.
Trigger: Bioisostere replacement (e.g., -COOH replaced by tetrazole).
Mechanism: Tetrazole functions as acid bioisostere but RDKit features may not classify identically.
Symptom: Known bioisosteric active not found.
Fix: Use ChemAxon-style bioisosteric feature equivalence; or pharmacophore feature class expansion (acid generic vs -COOH specific).
Trigger: Bridging water between ligand donor and protein acceptor.
Mechanism: PLIP can report water bridges, but the required crystallographic water must be present in the input and satisfy its geometric criteria.
Symptom: Pharmacophore missing critical H-bond feature.
Fix: Retain relevant crystallographic waters, inspect PLIP water-bridge output, and review borderline geometry manually.
| Aspect | Ligand-based | Receptor-based | |--------|--------------|----------------| | Data needed | Multiple actives with defensible conformers/alignment | A defined pocket, optionally with a co-crystal ligand | | Main bias | Known active chemotypes, conformer choice, and alignment | Pocket structure, protonation, retained waters, and interaction-detection/modeling rules | | Hit-set behavior | Depends on feature abstraction and tolerances | Depends on selected pocket interactions, excluded volumes, and tolerances | | Confidence evidence | Retrospective recovery across held-out actives/inactives | Recovery of known interaction geometry and retrospective or prospective validation |
Choose between ligand- and receptor-based models using the available structural/activity evidence and target-relevant validation. Neither approach is universally more reliable, diverse, or suitable for scaffold hopping.
| Symptom | Cause | Fix |
|---------|-------|-----|
| Pharm3D.EmbedPharmacophore fails | Bounds matrix infeasible | Review/loosen justified bounds and, when more attempts are warranted, increase the documented count argument; inspect n_failed |
| Pharmacophore matches everything | Too few features | Add features; tighten tolerances |
| Pharmacophore matches nothing | Too many features or tight bounds | Reduce feature count; loosen tolerances |
| BaseFeatures.fdef not found | RDKit installation issue | Check from rdkit.RDPaths import RDDataDir |
| Pharmacophore-conformer mismatch | Wrong conformer used | Use bioactive conformer from crystal |
| Pharmit search timeout | Library too large | Pre-filter by 2D fingerprint Tanimoto |
| apo2ph4 PML has no useful model | No robust pocket hot spots at selected settings | Recheck pocket definition and documented thresholds; inspect alternative models |
Chem.Pharm3D API documentation. https://www.rdkit.org/docs/source/rdkit.Chem.Pharm3D.htmlEmbedPharmacophore API documentation -- embedding molecules against an existing pharmacophore. https://www.rdkit.org/docs/source/rdkit.Chem.Pharm3D.EmbedLib.html#rdkit.Chem.Pharm3D.EmbedLib.EmbedPharmacophoretools
End-to-end CLIP-seq pipeline from FASTQ to ENCODE-compliant binding sites, single-nucleotide crosslink maps, annotation, motifs, and (optionally) differential binding. Use when running the full Yeo lab eCLIP / iCLIP / iCLIP2 / iCLIP3 / irCLIP / PAR-CLIP analysis with SMInput control, protocol-specific UMI extraction, ENCODE STAR parameters, CLIPper or Skipper peak calling with stringent log2 FC and -log10 p thresholds, IDR rescue and self-consistency QC, and downstream motif registration with mCross or PEKA.
development
Detect, date, and contextualize whole-genome duplication (WGD / paleopolyploidy) events using wgd v2 (Chen et al 2024), KsRates (Sensalari 2022 substitution-rate-corrected Ks dating), DupGen_finder (Qiao 2019), MAPS (Li 2018 phylogenomic), POInT (Conant 2008 ordered-block), SLEDGe (2024 ML-based), Whale.jl (Bayesian DL+WGD), and synteny-anchored paranome construction. Use when identifying ancient polyploidy from Ks distributions and synteny block analysis, positioning WGD events relative to speciation, distinguishing tandem from segmental from WGD duplications, dating the 2R/3R vertebrate / fish / salmonid WGDs, building paranome and Ks-age mixture models, applying KsRates substitution-rate correction across lineages, or testing alternative biased-fractionation / dosage-balance models post-WGD.
tools
Build whole-genome alignments using Progressive Cactus (Armstrong 2020 reference-free clade-level WGA), Minigraph-Cactus (Hickey 2024 pangenome-aware), LASTZ chain/net (UCSC pipeline), MUMmer4 (Marçais 2018 pairwise), minimap2 -x asm5/10/20 (Li 2018 fast pairwise), AnchorWave (Song 2022 WGD-aware), and Mauve / progressiveMauve (bacterial). Operates the HAL toolkit (Hickey 2013) for downstream extraction including halSynteny, halLiftover, halBranchMutations, and hal2maf. Use when constructing multi-species alignments for comparative-annotation projection (TOGA), synteny detection, conservation analyses (phyloP / PhastCons), or pangenome graph construction; selecting between reference-free (Cactus) and reference-anchored (LASTZ chains/nets) approaches; tuning sensitivity for closely vs distantly related genomes; or producing HAL files for genome-wide downstream tools.
development
Detect syntenic blocks and structural rearrangements between genomes using MCScanX (Wang 2012), JCVI/MCScan (Tang 2008 Python), GENESPACE (Lovell 2022) for orthology-anchored riparian visualization, SyRI for structural variation, AnchorWave for sequence-level synteny, i-ADHoRe 3.0 for highly diverged species, SynNet for synteny networks, and ntSynt for multi-genome macrosynteny. Use when identifying collinear gene blocks across species, distinguishing macrosynteny from microsynteny, detecting inversions/translocations/duplications, anchoring orthology in WGD lineages, producing publication riparian plots, computing synteny block age via Ks (cross-references whole-genome-duplication), or running synteny-aware ortholog inference in polyploids.