55from rdkit import Chem
66from rdkit .Chem .Crippen import MolLogP
77from rdkit .Chem .Descriptors import MolWt
8+ from rdkit .Chem .FilterCatalog import FilterCatalog , FilterCatalogParams
89from rdkit .Chem .QED import qed
910
1011from chemfunc .constants import Molecule
1112
12-
1313PropertyFunction = Callable [[Molecule ], float ]
1414PROPERTY_FUNCTION_REGISTRY = {}
1515
@@ -20,6 +20,7 @@ def register_property_function(property_type: str) -> Callable[[PropertyFunction
2020 :param property_type: The name to use to access the property function.
2121 :return: A decorator which will add a property function to the registry using the specified name.
2222 """
23+
2324 def decorator (property_function : PropertyFunction ) -> PropertyFunction :
2425 PROPERTY_FUNCTION_REGISTRY [property_type ] = property_function
2526 return property_function
@@ -46,6 +47,7 @@ def get_available_property_functions() -> list[str]:
4647
4748def smiles_to_mol_wrapper (property_function : PropertyFunction ) -> PropertyFunction :
4849 """A decorator which converts a SMILES to an RDKit molecule before passing it to a property function."""
50+
4951 @wraps (property_function )
5052 def wrapper (molecule : Molecule ) -> float :
5153 if isinstance (molecule , str ):
@@ -89,6 +91,27 @@ def compute_qed(molecule: Molecule) -> float:
8991 return qed (molecule )
9092
9193
94+ @register_property_function ('pains_plus' )
95+ @smiles_to_mol_wrapper
96+ def compute_pains_plus (molecule : Molecule ) -> str :
97+ """Checks a molecule for PAINS (pan-assay interference compounds) and other unwanted substructures.
98+
99+ :param molecule: A molecule, either a SMILES string or an RDKit molecule.
100+ :return: The PAINS and other unwanted substructure(s) found in the molecule.
101+ """
102+ # Set up all unwanted substructures filters
103+ params = FilterCatalogParams ()
104+ params .AddCatalog (FilterCatalogParams .FilterCatalogs .ALL )
105+ catalog = FilterCatalog (params )
106+
107+ # Check for unwanted substructures
108+ matches = " | " .join (
109+ f"{ entry .GetProp ('FilterSet' )} : { entry .GetDescription ()} " for entry in catalog .GetMatches (molecule )
110+ )
111+
112+ return matches
113+
114+
92115try :
93116 import os
94117 import sys
@@ -99,6 +122,7 @@ def compute_qed(molecule: Molecule) -> float:
99122
100123 import sascorer
101124
125+
102126 @register_property_function ('sa_score' )
103127 @smiles_to_mol_wrapper
104128 def compute_sa_score (molecule : Molecule ) -> float :
0 commit comments