ATLAS Offline Software
Loading...
Searching...
No Matches
Control/GaudiSequencer/python/PyComps.py
Go to the documentation of this file.
1# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
2
3# @file: GaudiSequencer/python/PyComps.py
4# @purpose: a set of python components for event filtering
5# @author: Sebastien Binet <binet@cern.ch>
6
7__doc__ = 'A set of python components for event filtering'
8__author__ = 'Sebastien Binet <binet@cern.ch>'
9
10import AthenaPython.PyAthena as PyAthena
11from AthenaPython.PyAthena import StatusCode
12
14 """Filtering algorithm to be used in conjunction with an AthSequencer.
15 Different operating modes are possible:
16 - give a list of events to accept
17 - give a list of events to veto
18 For each of these modes, the list of events can be:
19 - a list of event numbers: [ 13, 45, 24, 90 ]
20 - a list of pairs run/evt [ (1,13), (1,45), ... ]
21
22 Note that when in 'event list' mode and an event is found in the
23 event list, the event is accepted or not according to the
24 'filter_policy' property value ('accept' XOR 'reject')
25
26 Another way of filtering events is to provide the component with a
27 filtering function (via the 'filter_fct' property) which is expected
28 to take 2 arguments:
29 def my_filter_fct (runnbr, evtnbr):
30 'accept all events'
31 return True
32
33 examples of usage:
34 athena> seq = AthSequencer('seq')
35 athena> from GaudiSequencer.PyComps import PyEvtFilter
36 athena> seq += PyEvtFilter ('alg')
37 athena> seq.alg.filter_fct = lambda run,evt: evt in xrange(100)
38
39 or:
40 athena> def my_filter_fct(runnbr, evtnbr):
41 ... if runnbr > 5001 and runnbr < 5100 and
42 ... ( evtnbr in [ 1, 34, 600] or evtnbr > 600 ):
43 ... return True
44 ... return False
45 athena> seq.alg.filter_fct = my_filter_fct
46
47 or: (veto events 3,4 and 10)
48 athena> seq.alg.filter_fct = lambda r,e : e not in [3,4,10]
49
50 or:
51 athena> seq.alg.evt_list = [ (5010, 3), (5010, 4) ]
52 athena> seq.alg.evt_list = xrange(100)
53 athena> seq.alg.evt_list = range(10) + range(15,20)
54 athena> seq.alg.evt_list = map (lambda evt: (5100, evt), xrange(100))
55
56 or, to veto events:
57 athena> seq.alg.evt_list = [ 10, 3, 40 ]
58 athena> seq.alg.filter_policy = 'reject'
59 """
60 def __init__(self, name='PyEvtFilter', **kw):
61
62 kw['name'] = name
63 super(PyEvtFilter, self).__init__(**kw)
64
65
67 self.evt_list = kw.get('evt_list', None) # default value
68 # filtering policy for current event found in event list
69 self.filter_policy = kw.get('filter_policy', 'accept')
70 # filtering function
71 self.filter_fct = kw.get('filter_fct', None) # default value
72
73 # location of EventInfo
74 self.evt_info = kw.get('evt_info', None)
75 self.is_mc = kw.get('is_mc', False) # default value
76
77 return
78
79 def initialize(self):
80 _info = self.msg.info
81 _error = self.msg.error
82 _info('==> initialize...')
83
84 # check our properties and which modus operandi is active
85 if self.evt_list is None and self.filter_fct is None:
86 _error ('invalid properties: evt_list *and* filter_fct are None !')
87 _error ('usage:\n%s', self.__doc__)
88 return StatusCode.Failure
89
90 if (not (self.evt_list is None)) and \
91 (not (self.filter_fct is None)):
92 _error ('invalid properties: evt_list *and* filter_fct '
93 'are not None !')
94 _error ('usage:\n%s', self.__doc__)
95 return StatusCode.Failure
96
97 if not (self.filter_fct is None):
98 # checking the filtering function is sound
99 import inspect
100 args = inspect.getargspec (self.filter_fct)[0]
101 # FIXME: class' methods have the hidden 'self' argument...
102 if len(args) != 2:
103 _error ('filter_fct has NOT the expected signature')
104 _error (' nbr of arguments: %i', len(args))
105 _error (' expected: 2')
106 return StatusCode.Failure
107 if not (self.filter_policy in ('reject', 'accept')):
108 _error ('invalid value for filter_policy: %r',
109 self.filter_policy)
110 _error ("valid values are 'reject' or 'accept'")
111 return StatusCode.Failure
112 else:
113 # transform the list of events into a set of pairs (run,evt)
114 evt_list = self.evt_list[:]
115 self.evt_list = set()
116 for i in evt_list:
117 if isinstance(i, tuple): irun, ievt = i
118 else: irun, ievt = None, i
119 self.evt_list.add ((irun, ievt))
120
121 _info ('EventInfo name: %s',
122 self.evt_info
123 if self.evt_info else '<any>')
124
125 if self.evt_list:
126 _info("filtering mode: evt_list")
127 _info("filtering policy: %s", self.filter_policy)
128 self.filter_policy = False if self.filter_policy == 'reject' else \
129 True
130 else:
131 _info ("filtering mode: filter_fct")
132
133 self.sg = PyAthena.py_svc ('StoreGateSvc')
134 if self.sg is None:
135 _error ('could not retrieve event store')
136 return StatusCode.Failure
137
138 self._evt_cnt = 0 # total number of events processed
139 self._evt_acc_cnt = 0 # total number of events accepted by the filter
140 self._evt_rej_cnt = 0 # total number of events rejected by the filter
141 return StatusCode.Success
142
143 def execute(self):
144 self._evt_cnt += 1
145 _info = self.msg.info
146 _error= self.msg.error
147
148 for evtinfocls in ('xAOD::EventInfo', 'EventInfo'):
149 try:
150 evtinfo = self.sg.retrieve (evtinfocls, self.evt_info)
151 except Exception as e:
152 _info ('could not retrieve %r at [%s]\n caught exception:\n%r', evtinfocls, self.evt_info, e)
153 else:
154 if evtinfo is None:
155 _info ('retrieved \'None\' for %r at [%s]', evtinfocls, self.evt_info)
156 continue
157 break
158 else:
159 _error ("could not retrieve 'EventInfo' or 'xAOD::EventInfo' at [%s]", self.evt_info)
160 return StatusCode.Failure
161
162 filter_passed = None
163
164 if evtinfocls == 'EventInfo':
165 evtid = evtinfo.event_ID()
166 runnbr = evtid.run_number()
167 evtnbr = evtid.event_number()
168 elif evtinfocls == 'xAOD::EventInfo':
169 if not self.is_mc:
170 runnbr = evtinfo.runNumber()
171 else:
172 runnbr = evtinfo.mcChannelNumber()
173 evtnbr = evtinfo.eventNumber()
174
175 if self.filter_fct:
176 filter_passed = self.filter_fct (runnbr, evtnbr)
177 else:
178 if (runnbr,evtnbr) in self.evt_list or \
179 (None, evtnbr) in self.evt_list:
180 filter_passed = self.filter_policy
181 else:
182 filter_passed = not self.filter_policy
183
184
185 if not isinstance(filter_passed, bool):
186 self.msg.error ('invalid filter-passed decision: %r', filter_passed)
187 return StatusCode.Failure
188
189 self.setFilterPassed (filter_passed)
190 if filter_passed:
191 self._evt_acc_cnt += 1
192 dec = 'accepted'
193 else:
194 self._evt_rej_cnt += 1
195 dec = 'rejected'
196 _info ('[run=%s | evt=%s] ==> [%s]',
197 str(runnbr).zfill(5),
198 str(evtnbr).zfill(5),
199 dec)
200 return StatusCode.Success
201
202 def finalize(self):
203 _info = self.msg.info
204 _info ('==> finalize...')
205 _info (' #evts processed: %i', self._evt_cnt)
206 _info (' #evts accepted : %i', self._evt_acc_cnt)
207 _info (' #evts rejected : %i', self._evt_rej_cnt)
208 return StatusCode.Success
209
210 # class PyEvtFilter
MsgStream & msg() const
virtual StatusCode execute() override
virtual StatusCode finalize() override
virtual StatusCode initialize() override
evt_list
properties and data members list of events to accept
STL class.