ATLAS Offline Software
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 
10 import AthenaPython.PyAthena as PyAthena
11 from 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 
76  return
77 
78  def initialize(self):
79  _info = self.msg.info
80  _error = self.msg.error
81  _info('==> initialize...')
82 
83  # check our properties and which modus operandi is active
84  if self.evt_list is None and self.filter_fct is None:
85  _error ('invalid properties: evt_list *and* filter_fct are None !')
86  _error ('usage:\n%s', self.__doc__)
87  return StatusCode.Failure
88 
89  if (not (self.evt_list is None)) and \
90  (not (self.filter_fct is None)):
91  _error ('invalid properties: evt_list *and* filter_fct '
92  'are not None !')
93  _error ('usage:\n%s', self.__doc__)
94  return StatusCode.Failure
95 
96  if not (self.filter_fct is None):
97  # checking the filtering function is sound
98  import inspect
99  args = inspect.getargspec (self.filter_fct)[0]
100  # FIXME: class' methods have the hidden 'self' argument...
101  if len(args) != 2:
102  _error ('filter_fct has NOT the expected signature')
103  _error (' nbr of arguments: %i', len(args))
104  _error (' expected: 2')
105  return StatusCode.Failure
106  if not (self.filter_policy in ('reject', 'accept')):
107  _error ('invalid value for filter_policy: %r',
108  self.filter_policy)
109  _error ("valid values are 'reject' or 'accept'")
110  return StatusCode.Failure
111  else:
112  # transform the list of events into a set of pairs (run,evt)
113  evt_list = self.evt_list[:]
114  self.evt_list = set()
115  for i in evt_list:
116  if isinstance(i, tuple): irun, ievt = i
117  else: irun, ievt = None, i
118  self.evt_list.add ((irun, ievt))
119 
120  _info ('EventInfo name: %s',
121  self.evt_info
122  if self.evt_info else '<any>')
123 
124  if self.evt_list:
125  _info("filtering mode: evt_list")
126  _info("filtering policy: %s", self.filter_policy)
127  self.filter_policy = False if self.filter_policy == 'reject' else \
128  True
129  else:
130  _info ("filtering mode: filter_fct")
131 
132  self.sg = PyAthena.py_svc ('StoreGateSvc')
133  if self.sg is None:
134  _error ('could not retrieve event store')
135  return StatusCode.Failure
136 
137  self._evt_cnt = 0 # total number of events processed
138  self._evt_acc_cnt = 0 # total number of events accepted by the filter
139  self._evt_rej_cnt = 0 # total number of events rejected by the filter
140  return StatusCode.Success
141 
142  def execute(self):
143  self._evt_cnt += 1
144  _info = self.msg.info
145  _error= self.msg.error
146 
147  evtinfo = self.sg.retrieve ('EventInfo', self.evt_info)
148  if evtinfo is None:
149  _error ('could not retrieve EventInfo at [%s]', self.evt_info)
150  return StatusCode.Failure
151 
152  filter_passed = None
153 
154  evtid = evtinfo.event_ID()
155  runnbr = evtid.run_number()
156  evtnbr = evtid.event_number()
157  if self.filter_fct:
158  filter_passed = self.filter_fct (runnbr, evtnbr)
159  else:
160  if (runnbr,evtnbr) in self.evt_list or \
161  (None, evtnbr) in self.evt_list:
162  filter_passed = self.filter_policy
163  else:
164  filter_passed = not self.filter_policy
165 
166 
167  if not isinstance(filter_passed, bool):
168  self.msg.error ('invalid filter-passed decision: %r', filter_passed)
169  return StatusCode.Failure
170 
171  self.setFilterPassed (filter_passed)
172  if filter_passed:
173  self._evt_acc_cnt += 1
174  dec = 'accepted'
175  else:
176  self._evt_rej_cnt += 1
177  dec = 'rejected'
178  _info ('[run=%s | evt=%s] ==> [%s]',
179  str(runnbr).zfill(5),
180  str(evtnbr).zfill(5),
181  dec)
182  return StatusCode.Success
183 
184  def finalize(self):
185  _info = self.msg.info
186  _info ('==> finalize...')
187  _info (' #evts processed: %i', self._evt_cnt)
188  _info (' #evts accepted : %i', self._evt_acc_cnt)
189  _info (' #evts rejected : %i', self._evt_rej_cnt)
190  return StatusCode.Success
191 
192  # class PyEvtFilter
python.PyComps.PyEvtFilter.filter_policy
filter_policy
Definition: Control/GaudiSequencer/python/PyComps.py:69
python.PyComps.PyEvtFilter.sg
sg
Definition: Control/GaudiSequencer/python/PyComps.py:132
PyAthena::Alg::initialize
virtual StatusCode initialize() override
Definition: PyAthenaAlg.cxx:60
PyAthena::Alg::execute
virtual StatusCode execute() override
Definition: PyAthenaAlg.cxx:93
python.PyComps.PyEvtFilter
Definition: Control/GaudiSequencer/python/PyComps.py:13
PyAthena::Alg::finalize
virtual StatusCode finalize() override
Definition: PyAthenaAlg.cxx:86
python.PyComps.PyEvtFilter.filter_fct
filter_fct
Definition: Control/GaudiSequencer/python/PyComps.py:71
python.PyComps.PyEvtFilter._evt_rej_cnt
_evt_rej_cnt
Definition: Control/GaudiSequencer/python/PyComps.py:139
python.PyComps.PyEvtFilter._evt_acc_cnt
_evt_acc_cnt
Definition: Control/GaudiSequencer/python/PyComps.py:138
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
python.PyComps.PyEvtFilter.evt_info
evt_info
Definition: Control/GaudiSequencer/python/PyComps.py:74
python.PyComps.PyEvtFilter.evt_list
evt_list
init base class
Definition: Control/GaudiSequencer/python/PyComps.py:67
python.PyComps.PyEvtFilter._evt_cnt
_evt_cnt
Definition: Control/GaudiSequencer/python/PyComps.py:137
AthCommonMsg< Algorithm >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
str
Definition: BTagTrackIpAccessor.cxx:11
PyAthena::Alg
Definition: PyAthenaAlg.h:33
python.PyComps.PyEvtFilter.__init__
def __init__(self, name='PyEvtFilter', **kw)
Definition: Control/GaudiSequencer/python/PyComps.py:60