ShEPhERD Scoring Functions
📄 Paper | 📚 Documentation | 📦 PyPI
This repository contains the code for generating/optimizing conformers, extracting interaction profiles, aligning interaction profiles, and differentiably scoring 3D similarity. It also contains modules to evaluate conformers generated with ShEPhERD1 and other generative models.
The formulation of the interaction profile representation, scoring, alignment, and evaluations are found in our preprint ShEPhERD: Diffusing shape, electrostatics, and pharmacophores for bioisosteric drug design. The diffusion model itself is found in a separate repository: https://github.com/coleygroup/shepherd.
1 ShEPhERD: Shape, Electrostatics, and Pharmacophores Explicit Representation Diffusion
Table of Contents
- Documentation
- File Structure
- Installation
- Requirements
- Usage
- Scoring and Alignment Examples
- Evaluation Examples and Scripts
- Data
Documentation
Full documentation is available at shepherd-score.readthedocs.io.
File Structure
.
├── shepherd_score/
│ ├── alignment/ # Alignment package with PyTorch, JAX, and utilities
│ │ ├── utils/ # SE(3) and PCA utilities (torch, numpy, jax)
│ │ │ ├── se3*.py # SE(3) transformations (torch, numpy, jax)
│ │ │ └── pca*.py # Principal component alignment (torch, numpy, jax)
│ │ ├── _torch.py # PyTorch alignment algorithms (autograd)
│ │ ├── _torch_analytical.py # PyTorch alignment algorithms (analytical gradients)
│ │ ├── _jax.py # JAX alignment algorithms
│ │ └── _jax_parallel.py # JAX parallel alignment algorithms
│ ├── alignment_jax.py # Backwards compatibility shim
│ ├── evaluations/ # Evaluation suite
│ │ ├── utils/ # Converting data types and others
│ │ ├── docking/
│ │ │ ├── pdbs/ # PDBQT files used in *ShEPhERD* manuscript
│ │ │ ├── docking.py # Docking classes
│ │ │ └── pipelines.py # Docking evaluation pipelines
│ │ └── evaluate/ # Generated conformer evaluation pipelines
│ │ ├── evals.py # Individual evaluation classes
│ │ └── pipelines.py # Evaluation pipeline classes
│ ├── pharm_utils/ # Pharmacophore definitions
│ ├── protonation/ # Functions for protonation
│ ├── score/ # Scoring related functions and constants
│ │ ├── analytical_gradients/ # Analytical gradient implementations
│ │ │ └── _torch.py # PyTorch analytical gradients for shape, ESP, pharmacophore
│ │ ├── constants.py
│ │ ├── electrostatic_scoring.py
│ │ ├── gaussian_overlap.py
│ │ └── pharmacophore_scoring.py
│ ├── conformer_generation.py # RDKit and xtb related functions for conformers
│ ├── container/ # Molecule, MoleculePair, MoleculePairBatch classes
│ ├── extract_profiles.py # Functions to extract interaction profiles
│ ├── generate_point_cloud.py
│ ├── objective.py # Objective function used for REINVENT
│ └── visualize.py # Visualization tools
├── scripts/ # Scripts for running evaluations
├── examples/ # Jupyter notebook tutorials/examples
├── tests/
└── README.md
Installation
Via PyPI
pip install shepherd-score
Install xTB
xTB will need to be installed manually since there are no PyPi bindings. This can be done in a conda environment, but since this approach has been reported to lead to conflicts, we suggest installing
from source and adding it to PATH.
With optional dependencies
# JAX support (for faster scoring and alignment)
pip install "shepherd-score[jax]"
# Include docking evaluation tools
pip install "shepherd-score[docking]"
# Everything
pip install "shepherd-score[all]"
For local development
git clone https://github.com/coleygroup/shepherd-score.git
cd shepherd-score
pip install -e ".[all]"
Requirements
This package works where PyTorch, Open3D, RDKit, and xTB can be installed for Python >=3.9. If you are coming from the ShEPhERD repository, you can use the same environment as described there. Core dependencies (installed automatically) which enables interaction profile extraction, scoring/alignment, and evaluations are listed below.
python>=3.9
numpy
torch>=1.12
open3d>=0.18
rdkit>=2023.03
pandas>=2.0
scipy>=1.10
py3Dmol
molscrub
Note: If using
torch<=2.4, ensure thatmkl==2024.0with conda since there is a known issue that prevents importing torch.
Docking with Autodock Vina
Installing shepherd-score[docking] will automatically install the python bindings for Autodock Vina for the python interface. However, a manual installation of the executable of Autodock Vina v1.2.5 is required and can be found here: https://vina.scripps.edu/downloads/.
Usage
The package has convenience wrappers and base functions. Most users should reach for the convenience wrappers below; the base functions underneath are there if you need lower-level control. Scoring can be done with either NumPy or Torch, but alignment requires Torch. There are also Jax implementations for both scoring and alignment of gaussian overlap, ESP similarity, and pharmacophore similarity.
Update 8/20/25: Applicable xTB functions and evaluation pipeline evaluations are now parallelizable through the num_workers argument in the .evaluate method.
Convenience wrappers
Moleculeclassshepherd_score.container.Moleculeaccepts an RDKitMolobject (with an associated conformer) and generates its interaction profiles, exposed via two properties:.surface→Surface(positions, esp, probe_radius).pharmacophore→Pharmacophore(types, positions, vectors, atom_ids, labels)
- Pass
return_atom_ids=Trueand/orpriority_atoms=[...]toMolecule.get_pharmacophore()to populate.pharmacophore.atom_ids/.labels, e.g. for priority-weighted pharmacophore scoring
MoleculePairclassshepherd_score.container.MoleculePairoperates on twoMoleculeobjects and prepares theirSurface/Pharmacophoreprofiles for scoring and alignment
MoleculePairBatchclassshepherd_score.container.MoleculePairBatchoperates on a list ofMoleculePairobjects and enables accelerated alignment by padding all profile arrays to a common shape so a single compiled kernel is reused across every pair. Supports optional multi-CPU parallelism.
Base functions
Conformer generation
Useful conformer generation functions are found in the shepherd_score.conformer_generation module.
Interaction profile extraction
| Interaction profile | Function | Returns |
|---|---|---|
| shape | shepherd_score.extract_profiles.get_molecular_surface() |
np.ndarray (M,3) surface positions |
| electrostatics | shepherd_score.extract_profiles.get_electrostatic_potential() |
np.ndarray (M,) ESP per surface point |
| pharmacophores | shepherd_score.extract_profiles.get_pharmacophores() |
Pharmacophore |
shepherd_score.pharm_utils.pharmacophore.Pharmacophore is a lightweight dataclass; it also unpacks as types, positions, vectors = get_pharmacophores(mol). The surface position/ESP arrays are assembled into a matching shepherd_score.container.profiles.Surface dataclass by Molecule (above). Most users won't call these extraction functions or construct the containers directly.
Scoring
shepherd_score.score contains the base scoring functions with seperate modules for those dependent on PyTorch (*.py), NumPy (*_np.py), and Jax (*_jax.py).
| Similarity | Function |
|---|---|
| shape | shepherd_score.score.gaussian_overlap.get_overlap() |
| electrostatics | shepherd_score.score.electrostatic_scoring.get_overlap_esp() |
| pharmacophores | shepherd_score.score.pharmacophore_scoring.get_overlap_pharm() |
Scoring and Alignment Examples
Full jupyter notebook tutorials/examples for extraction, scoring, and alignments are found in the examples folder. Some minimal examples are below.
Extraction
Extraction of interaction profiles via the Molecule convenience wrapper.
from shepherd_score.conformer_generation import embed_conformer_from_smiles
from shepherd_score.conformer_generation import charges_from_single_point_conformer_with_xtb
from shepherd_score.container import Molecule
# Embed conformer with RDKit and partial charges from xTB
ref_mol = embed_conformer_from_smiles('Oc1ccc(CC=C)cc1', MMFF_optimize=True)
partial_charges = charges_from_single_point_conformer_with_xtb(ref_mol)
# `Molecule` extracts and owns all interaction profiles
ref_molec = Molecule(
ref_mol,
# optional options otherwise .surface/.pharmacophore stay empty
num_surf_points=200,
partial_charges=partial_charges, # If None, MMFF charges
pharm_multi_vector=False # recommended
# e.g., carbonyls get one HBA vector rather than two
)
# Surface point cloud + electrostatic potential
surf_pos = ref_molec.surface.positions # np.array (200,3)
esp = ref_molec.surface.esp # np.array (200,)
# Pharmacophores as a `Pharmacophore` container, unpacks as (types, positions, vectors)
# ref_molec.pharmacophore.types: np.array (P,)
# ref_molec.pharmacophore.{positions/vectors}: np.array (P,3)
pharm = ref_molec.pharmacophore
3D similarity scoring
An example of scoring the similarity of two different molecules using 3D surface, ESP, and pharmacophore similarity metrics.
from shepherd_score.score.constants import ALPHA
from shepherd_score.conformer_generation import embed_conformer_from_smiles
from shepherd_score.conformer_generation import optimize_conformer_with_xtb
from shepherd_score.container import Molecule, MoleculePair
# Embed a random conformer with RDKit
ref_mol_rdkit = embed_conformer_from_smiles('Oc1ccc(CC=C)cc1', MMFF_optimize=True)
fit_mol_rdkit = embed_conformer_from_smiles('O=CCc1ccccc1', MMFF_optimize=True)
# Local relaxation with xTB
ref_mol, _, ref_charges = optimize_conformer_with_xtb(ref_mol_rdkit)
fit_mol, _, fit_charges = optimize_conformer_with_xtb(fit_mol_rdkit)
# Extract interaction profiles
ref_molec = Molecule(ref_mol,
num_surf_points=200,
partial_charges=ref_charges,
pharm_multi_vector=False)
fit_molec = Molecule(fit_mol,
num_surf_points=200,
partial_charges=fit_charges,
pharm_multi_vector=False)
# Centers the two molecules' COM's to the origin
mp = MoleculePair(ref_molec, fit_molec, num_surf_points=200, do_center=True)
# Compute the similarity score for each interaction profile
shape_score = mp.score_with_surf(ALPHA(mp.num_surf_points))
esp_score = mp.score_with_esp(ALPHA(mp.num_surf_points), lam=0.3)
pharm_score = mp.score_with_pharm()
Alignment
Next we show alignment using the same MoleculePair class.
# Centers the two molecules' COM's to the origin
mp = MoleculePair(ref_molec, fit_molec, num_surf_points=200, do_center=True)
# Align fit_molec to ref_molec with your preferred objective function
# By default we use automatic differentiation via pytorch
surf_points_aligned = mp.align_with_surf(ALPHA(mp.num_surf_points),
num_repeats=50)
surf_points_esp_aligned = mp.align_with_esp(ALPHA(mp.num_surf_points),
lam=0.3,
num_repeats=50)
pharm_pos_aligned, pharm_vec_aligned = mp.align_with_pharm(num_repeats=50)
# Optimal scores and SE(3) transformation matrices are stored as attributes
mp.sim_aligned_{surf/esp/pharm}
mp.transform_{surf/esp/pharm}
# Get a copy of the optimally aligned fit Molecule object
transformed_fit_molec = mp.get_transformed_molecule(
se3_transform=mp.transform_{surf/esp/pharm}
)
Alignment of multiple MoleculePair objects can be accelerated with MoleculePairBatch with Jax installed.
from shepherd_score.container import MoleculePairBatch
batch = MoleculePairBatch(pairs) # `pairs` is a list of MoleculePair objects
# accelerated JAX-based volumetric alignment via padding
scores, aligned = batch.align_with_vol()
# Multi-CPU parallel via shard_map (must set XLA_FLAGS *before* importing JAX)
scores, aligned = batch.align_with_vol(num_workers=4, num_buckets=4, use_shmap=True)
Evaluation Examples and Scripts
We implement three evaluations of generated 3D conformers. Evaluations can be done on an individual basis or in a pipeline. Here we show the most basic use case in the unconditional setting.
ConfEval- Checks validity, pre-/post-xTB relaxation
- Calculates 2D graph properties
ConsistencyEval- Inherits from
ConfEvaland evaluates the consistency of the molecule's jointly generated interaction profiles with the true interaction profiles using 3D similarity scoring functions
- Inherits from
ConditionalEval- Inherits from
ConfEvaland evaluates the 3D similarity between generated molecules and the target molecule
- Inherits from
Note: Evaluations can be run from any molecule's atomic numbers and positions with explicit hydrogens (i.e., straight from an xyz file).
Examples
Full jupyter notebook tutorials/examples for evaluations are found in the examples folder. Some minimal examples are below.
from shepherd_score.evaluations.evaluate import ConfEval
from shepherd_score.evaluations.evaluate import UnconditionalEvalPipeline
# ConfEval evaluates the validity of a given molecule, optimizes it with xTB,
# and also computes various 2D graph properties
# `atom_array` np.ndarray (N,) atomic numbers of the molecule (with explicit H)
# `position_array` np.ndarray (N,3) atom coordinates for the molecule
conf_eval = ConfEval(atoms=atom_array, positions=position_array)
# Alternatively, if you have a list of molecules you want to test:
uncond_pipe = UnconditionalEvalPipeline(
generated_mols = [(a, p) for a, p in zip(atom_arrays, position_arrays)]
)
uncond_pipe.evaluate(num_workers=4)
# Properties are stored as attributes and can be converted into pandas df's
global_series, sample_df = uncond_pipe.to_pandas()
Scripts
Scripts to evaluate ShEPhERD-generated samples can be found in the scripts directory.
Data
We provide the data used for model training, benchmarking, and all ShEPhERD-generated samples reported in the paper at this Dropbox link. There are comprehensive READMEs in the Dropbox describing the different folders.
License
This project is licensed under the MIT License -- see LICENSE file for details.
Citation
If you use or adapt shepherd_score or ShEPhERD in your work, please cite us:
@inproceedings{
adams2025shepherd,
title={Sh{EP}h{ERD}: Diffusing shape, electrostatics, and pharmacophores for bioisosteric drug design},
author={Keir Adams and Kento Abeywardane and Jenna Fromer and Connor W. Coley},
booktitle={The Thirteenth International Conference on Learning Representations},
year={2025},
url={https://openreview.net/forum?id=KSLkFYHlYg}
}
Release files for shepherd-score 1.3.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shepherd_score-1.3.3.tar.gz | 1.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shepherd_score-1.3.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.7 MB
Release files / shepherd_score-1.3.3.tar.gz
| Download URL | shepherd_score-1.3.3.tar.gz |
|---|---|
| Size | 1.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1840435e01cd0d010292c1f74867d0299d7abc1ae49cad44e29d5f210742e989
|
|
BLAKE2b-256 checksum How to use checksums |
ffb3c421989514d20db52ee963d895695b613609f91fb496761fcde4dae08423
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.
Transparency logRelease files / shepherd_score-1.3.3-py3-none-any.whl
| Download URL | shepherd_score-1.3.3-py3-none-any.whl |
|---|---|
| Size | 695.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e3f8133c4fda6af1b50d53b479cf8b51fcc7822f754631b41f224dde56870d0c
|
|
BLAKE2b-256 checksum How to use checksums |
badf8745f93ef5b23ac360241849f44ca5e7297e925852d8f9d982c445c57f1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.
Transparency log