1
2
3
4
5
6
7 from rdkit import six
8 from rdkit.VLib.Node import VLibNode
9
10
12 """ base class for nodes which filter their input
13
14 Assumptions:
15
16 - filter function takes a number of arguments equal to the
17 number of inputs we have. It returns a bool
18
19 - inputs (parents) can be stepped through in lockstep
20
21 - we return a tuple if there's more than one input
22
23 Usage Example:
24 >>> from rdkit.VLib.Supply import SupplyNode
25 >>> def func(a,b):
26 ... return a+b < 5
27 >>> filt = FilterNode(func=func)
28 >>> suppl1 = SupplyNode(contents=[1,2,3,3])
29 >>> suppl2 = SupplyNode(contents=[1,2,3,1])
30 >>> filt.AddParent(suppl1)
31 >>> filt.AddParent(suppl2)
32 >>> v = [x for x in filt]
33 >>> v
34 [(1, 1), (2, 2), (3, 1)]
35 >>> filt.reset()
36 >>> v = [x for x in filt]
37 >>> v
38 [(1, 1), (2, 2), (3, 1)]
39 >>> filt.Destroy()
40
41 Negation is also possible:
42 >>> filt = FilterNode(func=func,negate=1)
43 >>> suppl1 = SupplyNode(contents=[1,2,3,3])
44 >>> suppl2 = SupplyNode(contents=[1,2,3,1])
45 >>> filt.AddParent(suppl1)
46 >>> filt.AddParent(suppl2)
47 >>> v = [x for x in filt]
48 >>> v
49 [(3, 3)]
50 >>> filt.Destroy()
51
52 With no function, just return the inputs:
53 >>> filt = FilterNode()
54 >>> suppl1 = SupplyNode(contents=[1,2,3,3])
55 >>> filt.AddParent(suppl1)
56 >>> v = [x for x in filt]
57 >>> v
58 [1, 2, 3, 3]
59 >>> filt.Destroy()
60
61
62
63 """
64
65 - def __init__(self, func=None, negate=0, **kwargs):
66 VLibNode.__init__(self, **kwargs)
67 self._func = func
68 self._negate = negate
69
72
75
77 parents = self.GetParents()
78 while 1:
79 args = []
80 try:
81 for parent in parents:
82 args.append(next(parent))
83 except StopIteration:
84 raise StopIteration
85 args = tuple(args)
86 if self._func is not None:
87 r = self._func(*args)
88 if self._negate:
89 r = not r
90
91 if r:
92 res = args
93 break
94 else:
95 res = args
96 break
97 if len(parents) == 1:
98 res = res[0]
99 return res
100
101
102 if six.PY3:
103 FilterNode.__next__ = FilterNode.next
104
105
106
107
108
109
111 import sys
112 import doctest
113 failed, _ = doctest.testmod(optionflags=doctest.ELLIPSIS, verbose=verbose)
114 sys.exit(failed)
115
116
117 if __name__ == '__main__':
118 _runDoctests()
119