ATLAS Offline Software
ElectronFilter.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2 
3 
12 
13 __doc__ = """This is a short algorithm to select events that contain one
14 electron which fulfills a certain set of criteria.
15 """
16 __version__ = "0.0.3"
17 __author__ = "Karsten Koeneke <karsten.koeneke@desy.de>"
18 
19 
20 import AthenaPython.PyAthena as PyAthena
21 from AthenaPython.PyAthena import StatusCode
22 
23 from PrimaryDPDMaker import PrimaryDPDHelpers
24 
25 
26 import AthenaCommon.SystemOfUnits as Units
27 
28 class ElectronFilter( PyAthena.AthFilterAlgorithm ):
29  """
30  This class is a short algorithm to select events that contain one
31  electron which fulfills a certain set of criteria. The possible
32  criteria are (with default values):
33  cutEtMin = 20.0*Units.GeV)
34  cutIsEM = 'None' # Possible values: 'None', 'Loose', 'Medium', 'Tight', 'TightNoIsolation'
35  cutAuthor = 'either' # Possible values: 'softe', 'egamma', 'either'
36  cutEtaMax = 2.5
37  removeEtaCrack = False
38  crackEtaMin = 1.37
39  crackEtaMax = 1.52
40  minNumberPassed = 1
41  passAll = False
42  """
43 
44 
45 
46  def __init__ ( self, name = "ElectronFilter", **kw ):
47 
48  kw['name'] = name
49  super(ElectronFilter, self).__init__(**kw)
50 
51 
52  self.electronCollectionType = kw.get('electronCollectionType', "ElectronContainer")
53  self.electronCollectionName = kw.get('electronCollectionName', "ElectronAODCollection")
54  self.goodElectronCollectionName = kw.get('goodElectronCollectionName', self.name() )
55  self.cutEtMin = kw.get('cutEtMin', 20.0*Units.GeV)
56  self.cutIsEM = kw.get('cutIsEM', "None") # Possible values: "None", "Loose", 'Medium', 'Tight', 'TightNoIsolation'
57  self.cutAuthor = kw.get('cutAuthor', "either") # Possible values: 'softe', 'egamma', 'either'
58  self.cutEtaMax = kw.get('cutEtaMax', 2.5)
59  self.removeEtaCrack = kw.get('removeEtaCrack', False)
60  self.crackEtaMin = kw.get('crackEtaMin', 1.37)
61  self.crackEtaMax = kw.get('crackEtaMax', 1.52)
62  self.minNumberPassed = kw.get('minNumberPassed', 1)
63  self.passAll = kw.get('passAll', False)
64 
65  self.storeGateSvc = None
66 
67  return
68 
69 
70 
71 
72  def initialize(self):
73  self.msg.info( '************************************' )
74  self.msg.info( '==> initialize %s...', self.name() )
75  self.msg.info( 'Will apply the following cuts:' )
76  self.msg.info( ' EtMinEl = %r', self.cutEtMin )
77  self.msg.info( ' IsEmEl = %s', self.cutIsEM )
78  self.msg.info( ' AuthorEl = %s', self.cutAuthor )
79  self.msg.info( ' EtaMax = %r', self.cutEtaMax )
80  self.msg.info( ' removeEtaCrack = %r', self.removeEtaCrack )
81  self.msg.info( ' crackEtaMin = %r', self.crackEtaMin )
82  self.msg.info( ' crackEtaMax = %r', self.crackEtaMax )
83  self.msg.info( ' minNumberPassed = %r', self.minNumberPassed )
84  self.msg.info( ' passAll = %r', self.passAll )
85  self.msg.info( '************************************' )
86 
87 
88  self.nProcessed = 0
89  self.nElectrons = 0
90  self.nEventElPassEta = 0
91  self.nEventElPassEt = 0
95 
96 
97  import PyUtils.RootUtils as ru
98  ROOT = ru.import_root() # noqa: F841
99 
100 
101  self.storeGateSvc = PyAthena.py_svc('StoreGateSvc')
102  if self.storeGateSvc is None:
103  self.msg.error("Problem retrieving StoreGateSvc pointer !!")
104  return StatusCode.Failure
105 
106  return StatusCode.Success
107 
108 
109 
110 
111  def execute(self):
112  self.nProcessed+=1
113  self.msg.debug( '==> execute %s on %r. event...', self.name(), self.nProcessed )
114 
115  nElPassEta = 0
116  nElPassEt = 0
117  nElPassIsEM = 0
118  nElPassAuthor = 0
119 
120  # Create a class-member list of all electrons that passed all cuts.
121  # This can then be used by other filters to do overlap removal, etc.
122  VIEW_ELEMENTS = 1
123  goodElectrons = PyAthena.ElectronContainer(VIEW_ELEMENTS)
124  #goodElectrons = []
125 
126 
127 
128  if self.passAll :
129  self.msg.debug( '%s event passed because passAll is true', self.name() )
130  self.setFilterPassed(True)
131  return StatusCode.Success
132 
133 
134  #Then... here we go!
135 
136  # Get the electron collection from StoreGate
137  try:
138  electronCollection = self.storeGateSvc.retrieve( self.electronCollectionType, self.electronCollectionName )
139  pass
140  except LookupError:
141  self.msg.warning( 'Collection %s not found', self.electronCollectionName )
142  self.setFilterPassed(True)
143  return StatusCode.Success
144 
145  # Loop over all electrons and make the selections cuts
146  for electron in electronCollection :
147  self.nElectrons += 1
148  # Use Et of CaloCluster.
149  cluster = None
150  cluster = electron.cluster()
151  if cluster is None :
152  self.msg.warning( 'Could not get the cluster for this electron!' )
153  pass
154  else :
155  if abs(cluster.etaBE(2)) < self.cutEtaMax :
156  # Check if the EM calorimeter barrel-encap crack should be removed.
157  if not self.removeEtaCrack or ( self.removeEtaCrack and \
158  ( abs(cluster.etaBE(2)) < self.crackEtaMin
159  or abs(cluster.etaBE(2)) > self.crackEtaMax ) ):
160  nElPassEta += 1
161  # If the Et of this electron is larger than the minimum required Et
162  # of the high-Et cut, then the high-Et electron is found.
163  if cluster.et() > self.cutEtMin :
164  nElPassEt += 1
165  # Check that the electron in question comes from the right reconstruction algorithm using PrimaryDPDHelpers
166  if PrimaryDPDHelpers.checkEgammaAuthor( electron, self.cutAuthor ) :
167  nElPassAuthor += 1
168  # Check the quality of the electron using PrimaryDPDHelpers
169  if PrimaryDPDHelpers.checkElectronIsEM( electron, self.cutIsEM ):
170  nElPassIsEM += 1
171  # goodElectrons.append( electron )
172  goodElectrons.push_back( electron )
173  pass
174  pass
175  pass
176  pass
177  pass
178  pass
179  pass
180 
181 
182 
183  if nElPassEta > 0 : self.nEventElPassEta += 1
184  if nElPassEt > 0 : self.nEventElPassEt += 1
185  if nElPassIsEM > 0 : self.nEventElPassIsEM += 1
186  if nElPassAuthor > 0 : self.nEventElPassAuthor += 1
187 
188 
195  if self.storeGateSvc.record( goodElectrons, self.goodElectronCollectionName ) != StatusCode.Success :
196  self.msg.error( 'Could not record the goodElectrons into StoreGate with the key = ', self.goodElectronCollectionName )
197  pass
198 
199 
200 
201  if goodElectrons.__len__() >= self.minNumberPassed :
202  self.nEventMinNumPassed += 1
203  self.msg.debug( '%s event passed.', self.name() )
204  self.setFilterPassed(True)
205  pass
206  else :
207  self.msg.debug( '%s event failed.', self.name() )
208  self.setFilterPassed(False)
209  pass
210 
211  return StatusCode.Success
212 
213 
214 
215  def finalize(self):
216 
217  import math
218 
219 
220  effiElectrons = 0.0
221  effiElPassEta = 0.0
222  effiElPassEt = 0.0
223  effiElPassAuthor = 0.0
224  effiElPassIsEM = 0.0
225  effiMinNumPassed = 0.0
226  effiErrElectrons = 0.0
227  effiErrElPassEta = 0.0
228  effiErrElPassEt = 0.0
229  effiErrElPassAuthor = 0.0
230  effiErrElPassIsEM = 0.0
231  effiErrMinNumPassed = 0.0
232  try :
233  # Efficiencies
234  effiElectrons = self.nElectrons / (1.0*self.nProcessed)
235  effiElPassEta = self.nEventElPassEta / float(self.nProcessed)
236  effiElPassEt = self.nEventElPassEt / float(self.nProcessed)
237  effiElPassAuthor = self.nEventElPassAuthor / float(self.nProcessed)
238  effiElPassIsEM = self.nEventElPassIsEM / float(self.nProcessed)
239  effiMinNumPassed = self.nEventMinNumPassed / float(self.nProcessed)
240 
241  # Error on efficiencies; use binomial errors
242  effiErrElectrons = math.sqrt(self.nElectrons) / self.nElectrons
243  effiErrElPassEta = 100.0 * math.sqrt( effiElPassEta*(1.0 - effiElPassEta) / float(self.nProcessed) )
244  effiErrElPassEt = 100.0 * math.sqrt( effiElPassEt*(1.0 - effiElPassEt) / float(self.nProcessed) )
245  effiErrElPassAuthor = 100.0 * math.sqrt( effiElPassAuthor*(1.0 - effiElPassAuthor) / float(self.nProcessed) )
246  effiErrElPassIsEM = 100.0 * math.sqrt( effiElPassIsEM*(1.0 - effiElPassIsEM) / float(self.nProcessed) )
247  effiErrMinNumPassed = 100.0 * math.sqrt( effiMinNumPassed*(1.0 - effiMinNumPassed) / float(self.nProcessed) )
248 
249  effiElPassEta *= 100.0
250  effiElPassEt *= 100.0
251  effiElPassAuthor *= 100.0
252  effiElPassIsEM *= 100.0
253  effiMinNumPassed *= 100.0
254 
255  except ZeroDivisionError :
256  self.msg.warning( 'Division by zero error when calculating the uncertainties on the pass efficiencies...' )
257  pass
258 
259 
260  self.msg.info( '==> finalize %s...', self.name() )
261  self.msg.info( '***************************************************************' )
262  self.msg.info( 'Cut-flow table of %s skimming algorithm:', self.name() )
263  self.msg.info( '-------------' )
264  self.msg.info( ' Number of processed events: %r', self.nProcessed )
265  self.msg.info( ' Number of all electrons: %r and number of electrons per event: %3.3f +/- %3.3f', self.nElectrons, effiElectrons, effiErrElectrons )
266  self.msg.info( ' Events after eta cut: %r and resulting efficiency = (%3.3f +/- %3.3f)%%', self.nEventElPassEta, effiElPassEta, effiErrElPassEta )
267  self.msg.info( ' Events after E_T cut: %r and resulting efficiency = (%3.3f +/- %3.3f)%%', self.nEventElPassEt, effiElPassEt, effiErrElPassEt )
268  self.msg.info( ' Events after author cut: %r and resulting efficiency = (%3.3f +/- %3.3f)%%', self.nEventElPassAuthor, effiElPassAuthor, effiErrElPassAuthor )
269  self.msg.info( ' Events after IsEM cut: %r and resulting efficiency = (%3.3f +/- %3.3f)%%', self.nEventElPassIsEM, effiElPassIsEM, effiErrElPassIsEM )
270  self.msg.info( ' Events after minNumberPassed %r and resulting efficiency = (%3.3f +/- %3.3f)%%', self.nEventMinNumPassed, effiMinNumPassed, effiErrMinNumPassed )
271  self.msg.info( '***************************************************************' )
272 
273  return StatusCode.Success
274 
grepfile.info
info
Definition: grepfile.py:38
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
SystemOfUnits
python.ElectronFilter.ElectronFilter.cutEtMin
cutEtMin
Definition: ElectronFilter.py:55
python.ElectronFilter.ElectronFilter.storeGateSvc
storeGateSvc
Get the storgate handle.
Definition: ElectronFilter.py:65
python.ElectronFilter.ElectronFilter.cutEtaMax
cutEtaMax
Definition: ElectronFilter.py:58
python.ElectronFilter.ElectronFilter.nEventElPassEta
nEventElPassEta
Definition: ElectronFilter.py:90
python.ElectronFilter.ElectronFilter.nElectrons
nElectrons
Definition: ElectronFilter.py:89
python.ElectronFilter.ElectronFilter.initialize
def initialize(self)
Definition: ElectronFilter.py:72
python.ElectronFilter.ElectronFilter.nProcessed
nProcessed
Also, declare some counters and initialize them to zero.
Definition: ElectronFilter.py:88
python.ElectronFilter.ElectronFilter.crackEtaMin
crackEtaMin
Definition: ElectronFilter.py:60
python.ElectronFilter.ElectronFilter.minNumberPassed
minNumberPassed
Definition: ElectronFilter.py:62
python.ElectronFilter.ElectronFilter.execute
def execute(self)
Definition: ElectronFilter.py:111
python.ElectronFilter.ElectronFilter.passAll
passAll
Definition: ElectronFilter.py:63
python.ElectronFilter.ElectronFilter.nEventElPassEt
nEventElPassEt
Definition: ElectronFilter.py:91
python.ElectronFilter.ElectronFilter.removeEtaCrack
removeEtaCrack
Definition: ElectronFilter.py:59
python.ElectronFilter.ElectronFilter
Definition: ElectronFilter.py:28
python.ElectronFilter.ElectronFilter.cutAuthor
cutAuthor
Definition: ElectronFilter.py:57
debug
const bool debug
Definition: MakeUncertaintyPlots.cxx:53
python.ElectronFilter.ElectronFilter.crackEtaMax
crackEtaMax
Definition: ElectronFilter.py:61
python.ElectronFilter.ElectronFilter.nEventMinNumPassed
nEventMinNumPassed
Definition: ElectronFilter.py:94
python.ElectronFilter.ElectronFilter.electronCollectionType
electronCollectionType
initialize base class
Definition: ElectronFilter.py:52
python.ElectronFilter.ElectronFilter.__init__
def __init__(self, name="ElectronFilter", **kw)
Definition: ElectronFilter.py:46
python.ElectronFilter.ElectronFilter.finalize
def finalize(self)
Definition: ElectronFilter.py:215
python.ElectronFilter.ElectronFilter.nEventElPassAuthor
nEventElPassAuthor
Definition: ElectronFilter.py:93
python.ElectronFilter.ElectronFilter.cutIsEM
cutIsEM
Definition: ElectronFilter.py:56
error
Definition: IImpactPoint3dEstimator.h:70
python.ElectronFilter.ElectronFilter.electronCollectionName
electronCollectionName
Definition: ElectronFilter.py:53
readCCLHist.float
float
Definition: readCCLHist.py:83
python.ElectronFilter.ElectronFilter.nEventElPassIsEM
nEventElPassIsEM
Definition: ElectronFilter.py:92
python.ElectronFilter.ElectronFilter.goodElectronCollectionName
goodElectronCollectionName
Definition: ElectronFilter.py:54