Deriving new instances of OEUnaryFunctions and OEUnaryPredicates requires C++, but for many cases, a special case of these has been instantiated for atoms and bonds. OEPyAtomPredicate and OEPyBondPredicate are special case predicates that take a Python function as the single argument. In essence, we are creating a callback that itself holds a callback. This Python function must be defined a certain way. First, it can only take a single argument, an atom for an OEPyAtomPredicate and a bond for an OEPyBondPredicate. Second, it must return 1 if the atom(bond) satisifies the condition and 0 otherwise. Since it may sometimes be necessary to create predicates that hold state, a class instance method can be used. Just make sure that the method (to which a pointer will be stored inside the C++ predicate) stays in scope while the predicate is used.
The following example shows a user defined functor which screens for atoms whose atomic mass is greater than 15.
1 #!/usr/bin/env python 2 # ch21-2.py 3 4 from openeye.oechem import * 5 6 def AtomWgtGT15(atom): 7 if OEGetAverageWeight(atom.GetAtomicNum())>15: 8 return 1 9 return 0 10 11 WeightGT15 = PyAtomPredicate(AtomWgtGT15) 12 13 mol = OEGraphMol() 14 OEParseSmiles(mol, "c1c(O)c(O)c(Cl)cc1CCCBr") 15 OETriposAtomNames(mol) 16 17 for atom in mol.GetAtoms(WeightGT15): 18 print atom.GetName(), "has weight > 15." 19