plinder.core.structure.smallmols_similarity#
- plinder.core.structure.smallmols_similarity.smiles2nonstereo(smiles: str) str[source]#
Return a stereo-stripped RDKit canonical SMILES — the ligand identity key.
RDKit always yields a canonical SMILES from a parsed molecule, whereas InChIKey generation fails for many CCD molecules (organometallics, exotic valences), so canonical SMILES is the robust, uniform identifier. Stereochemistry is removed (identity is stereo-insensitive — used for split stratification and MMP grouping) and no charge normalization is applied: the CCD representation is taken as-is, consistent with the exact-SMILES cofactor/artifact matching.
Parsing uses the tolerant
mol_from_smiles()so over-valent ligands (boron cages, hypervalent metals) still yield a canonical 2D graph key instead of falling back to their raw, non-canonical SMILES.
- plinder.core.structure.smallmols_similarity.mol2morgan_fp(mol: Mol | str, radius: int = 2, nbits: int = 2048) ExplicitBitVect[source]#
Convert an RDKit molecule or SMILES string to a Morgan fingerprint.
- plinder.core.structure.smallmols_similarity.mol2mhfp6(mol: Mol | str) NDArray[uint32][source]#
Return the MHFP6 MinHash fingerprint of a molecule or SMILES string.
MHFP6 hashes the set of circular SMILES shingles (radii 1..3) and keeps the per-permutation minima, so the fraction of matching positions between two fingerprints estimates the Jaccard similarity of their shingle sets (Probst & Reymond, J. Cheminform. 2018). Unlike a folded Morgan bit-vector, the result is a dense vector of
MHFP6_N_PERMUTATIONSuint32 hashes.
- plinder.core.structure.smallmols_similarity.mhfp6_bulk_jaccard(query: NDArray[uint32], reference_matrix: NDArray[uint32]) NDArray[float64][source]#
Estimate one MHFP6 vector’s Jaccard similarity to every reference row.
Each reference row is a MinHash vector; the estimated Jaccard similarity is the fraction of permutations at which the two vectors share the same minimum hash – the MinHash counterpart of
BulkTanimotoSimilarityfor bit-vectors.
- class plinder.core.structure.smallmols_similarity.RascalParityMatch(atoms: dict[int, int], bonds: int, opposed: int, alternatives: tuple[dict[int, int], ...] = ())[source]#
Bases:
NamedTupleOne Rascal MCES reduced to what the PARITY-like score needs.
- atoms: dict[int, int]#
Alias for field number 0
- bonds: int#
Alias for field number 1
- opposed: int#
Alias for field number 2
- alternatives: tuple[dict[int, int], ...]#
Alias for field number 3
- score(mol1: Mol, mol2: Mol, *, stereo: bool = True) float#
PARITY-like similarity in [0, 1]; an opposed centre counts half an atom.
- coverage(mol1: Mol, mol2: Mol, *, stereo: bool = True) tuple[float, float]#
Fraction of each molecule matched,
(mol1, mol2), in [0, 1].Directional counterpart of
score(): the same atom and bond terms (an opposed centre still counts half an atom), each averaged over one molecule’s own atom and bond counts instead of the union.
- plinder.core.structure.smallmols_similarity.parity_similarity(atoms: float, bonds: float, atom_total: int, bond_total: int) float[source]#
Mean of the atom and bond Tanimotos; totals are both molecules’ counts summed.
- plinder.core.structure.smallmols_similarity.rascal_parity_match(mol1: Mol, mol2: Mol, *, target: float = 0.3, timeout: int = 2, all_best: bool = False) RascalParityMatch[source]#
Element-exact Rascal MCES with fragments allowed, pruned to a target bond similarity.
Pairs whose bond Tanimoto cannot reach
targetare pruned before the clique search and come back empty. Rascal maximises matched bonds, and the MCESs of that size differ in their largest fragment, so the bonds come from one MCES and the fragment from a second run that keeps only the largest fragment over all of them (singleLargestFrag). Withall_bestevery fragment is enumerated instead (a further 1.5x) and the one scoring best is taken; the rest follow, best first and then in a fixed order.
- plinder.core.structure.smallmols_similarity.rascal_parity_score(mol1: Mol, mol2: Mol, *, target: float = 0.3, stereo: bool = True, timeout: int = 2) float[source]#
PARITY-like similarity from one Rascal MCES, in [0, 1].
Element-exact MCES with fragments allowed, scored as the mean of two Tanimoto terms: atoms of the largest connected fragment over the atom union, and all matched bonds over the bond union. The largest fragment carries residue order (a shuffled peptide splits into one fragment per residue, a substitution does not); the bonds keep credit for matches beyond a substituted connecting atom. With
stereoa matched tetrahedral centre of opposite handedness counts half an atom.
- plinder.core.structure.smallmols_similarity.rascal_parity_coverage(mol1: Mol, mol2: Mol, *, target: float = 0.3, stereo: bool = True, timeout: int = 2) tuple[float, float][source]#
Directional PARITY-like coverage from one Rascal MCES.
- Parameters:
- mol1, mol2Mol
The molecules to compare.
- targetfloat, default=0.3
Bond Tanimoto below which a pair is pruned and scores zero. It is symmetric, so a small molecule inside a much larger one is pruned unless
targetis lowered.- stereobool, default=True
Count a matched centre of opposite handedness as half an atom.
- timeoutint, default=2
Rascal timeout in seconds.
- Returns:
- tuple[float, float]
The fraction of
mol1and ofmol2covered by the match. A fragment fully contained in a larger molecule gives(1.0, x)withx < 1, which the symmetricrascal_parity_score()cannot show.