Beyond 2D Fingerprints: Encoding Protein-Ligand Interactions for Machine Learning
A 2D fingerprint throws away the pose. Docking spent its time on contacts, hydrogen-bond geometry, and stacking, and a topology-only vector keeps none of that. Use a 2D fingerprint when the ligand alone is the object. Use a 3D interaction fingerprint when the pose is the object.
PLEC, SPLIF, and E3FP are three different objects. PLEC encodes which groups touch. SPLIF encodes the geometry of those contacts. E3FP never sees the protein.
PLEC
PLEC is an ECFP-style fingerprint of the interface. It describes the chemical neighborhood of contacting atom pairs, on both the ligand and the protein. The model sees which groups are next to which residue environments, and at what depth you asked for.
Use it when the chemistry of the contact is the signal: affinity, or reactivity at a site.
import oddt
import oddt.fingerprints as fps
from oddt.toolkits.rdk import readfile
# Load receptor and ligand
receptor = next(readfile('pdb', 'receptor.pdb'))
receptor.protein = True
ligand = next(readfile('sdf', 'docked_pose.sdf'))
# Calculate PLEC fingerprint
# depth_ligand and depth_protein control circular environment depth
plec = fps.PLEC(ligand, receptor, depth_ligand=2, depth_protein=4, size=16384)
size is the bit length. A longer vector collides less and costs more memory. 16384 is the starting point given here for ensemble docking.
If the task is reactivity at one catalytic site, a hand-built distance can be appended. The coordinate below is a placeholder.
import numpy as np
from oddt.interactions import close_contacts
# Example: compute distance from ligand centroid to a metal/active site atom
# Replace with your actual active site coordinate
active_site_coord = np.array([12.3, 45.6, 7.8])
ligand_centroid = ligand.atoms.coords.mean(axis=0)
dist_to_site = np.linalg.norm(ligand_centroid - active_site_coord)
# Append to PLEC vector
plec_extended = np.append(plec, dist_to_site)
close_contacts is imported in the original snippet and not called. The distance is a centroid-to-point norm.
SPLIF
SPLIF encodes the geometry of interacting fragments rather than a catalog of atom types. Stacking and T-shaped contacts sit in that geometry, without a hard-coded interaction list. That makes it less tied to one docking program’s interaction labels.
Use it when you want poses that reproduce the 3D binding geometry of a reference ligand.
# SPLIF is also available through ODDT
splif = fps.SPLIF(ligand, receptor, depth_ligand=1, depth_protein=1, size=4096)
The vectors are sparser than PLEC. Tanimoto similarity on them is the geometric comparison in this note.
from oddt.utils import binary_tanimoto
reference_splif = fps.SPLIF(reference_ligand, receptor)
similarity = binary_tanimoto(splif, reference_splif)
print(f"Geometric similarity to reference: {similarity:.3f}")
E3FP
E3FP is a circular fingerprint in Euclidean space. It grows out from atoms through distance, not through bonds. The same 2D structure in two conformations gets two fingerprints. The protein is absent, so this is a ligand-shape method: ligand-based screening and scaffold hopping.
# Install e3fp: pip install e3fp
from e3fp.pipeline import fprints_from_mol
from rdkit import Chem
from rdkit.Chem import AllChem
# Load mol with a 3D conformer
mol = Chem.MolFromSmiles('your_smiles_here')
mol = Chem.AddHs(mol)
AllChem.EmbedMolecule(mol, AllChem.ETKDGv3())
AllChem.MMFFOptimizeMolecule(mol)
# Generate E3FP fingerprints for all conformers
fprints = fprints_from_mol(mol, fprint_params={'bits': 4096, 'level': 5})
# Convert to dense array for ML
import numpy as np
e3fp_array = np.array(fprints[0].to_vector(sparse=False), dtype=np.float32)
For several poses, this note mean-pools the vectors.
# Mean-pool across poses - preserves pharmacophoric signal while reducing noise
fprint_arrays = [np.array(fp.to_vector(sparse=False)) for fp in fprints]
e3fp_consensus = np.mean(fprint_arrays, axis=0)
Which one
| PLEC | SPLIF | E3FP | |
|---|---|---|---|
| Sees | Protein and ligand | Protein and ligand | Ligand only |
| Encodes | Contact chemistry | Spatial geometry | Shape and pharmacophore |
| Ensemble noise | Tolerates it well | Moderate | Needs aggregation |
| Use | Reactivity, affinity | Geometric screening | Ligand-based screening |
Across an ensemble of receptor conformations, PLEC has a frame of reference the protein supplies, so the encoding moves less when the pose jitters. E3FP has to be aggregated or the conformer noise is the feature.
None of the three is complete. The pipelines this note describes do best when a primary fingerprint is joined to a few hand-built features that the fingerprint is not learning. Profile what the model uses before you swap the whole representation.
2D fingerprints stay the right tool for a fast ligand-only screen. For a model whose question is the binding geometry, the 3D choice above is the one that matches the question.