22.3 Writing your own Functors in Python

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

Listing:22.2 User defined functors can be simple