ATLAS Offline Software
Loading...
Searching...
No Matches
EventSelectionConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
4from AsgAnalysisAlgorithms.AsgAnalysisConfig import makeEventCutFlowConfig
5from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
6
7
8class EventSelectionMergerConfig(ConfigBlock):
9 """ConfigBlock for merging the output of various selection streams"""
10
11 def __init__(self):
12 super(EventSelectionMergerConfig, self).__init__()
13 self.addOption('selections', [], type=list,
14 info="the selection decisions (list of strings) to unify into a "
15 "final decision (internally: selection_1 || selection_2 || ...). "
16 "The default is [] (empty list).")
17 self.addOption('noFilter', False, type=bool,
18 info="do not apply an event filter. The default is False, i.e. "
19 "remove events not passing the full list of selection cuts.")
20
21 def instanceName (self) :
22 """Return the instance name for this block"""
23 return '' # I think there is only one instance of this block, not sure what the name ought to be
24
25 def makeAlgs(self, config):
26 if not ( isinstance(self.selections, list) and self.selections and all(isinstance(item, str) for item in self.selections) ):
27 print('EventSelectionMerger: selections = ', self.selections)
28 raise ValueError('EventSelectionMerger requires a non-empty list of selection strings to be '
29 'passed as `selections`!')
30 alg = config.createAlgorithm('CP::SaveFilterAlg', 'EventSelectionMerger' + self.selections[0].split("_%SYS%")[0])
31 alg.FilterDescription = 'events passing at least one EventSelection algorithm'
32 alg.eventDecisionOutputDecoration = 'ignore_anySelection_%SYS%'
33 alg.selection = '||'.join([sel+',as_char' for sel in self.selections if sel])
34 alg.noFilter = self.noFilter
35 alg.selectionName = 'pass_anySelection_%SYS%'
36 alg.decorationName = 'ntuplepass_anySelection_%SYS%'
37
38class EventSelectionConfig(ConfigBlock):
39 """ConfigBlock for interpreting text-based event selections"""
40
41 def __init__(self):
42 super(EventSelectionConfig, self).__init__()
43 self.addOption('name', '', type=str,
44 noneAction='error',
45 info="the name of the event selection, used to uniquely identify "
46 "the EventSelectionConfig block.")
47 self.addOption('electrons', "", type=str,
48 info="the input electron container, with a possible selection, in "
49 "the format container or container.selection. The default is '' "
50 "(empty string).")
51 self.addOption('muons', "", type=str,
52 info="the input muon container, with a possible selection, in the "
53 "format container or container.selection. The default is '' "
54 "(empty string).")
55 self.addOption('jets', "", type=str,
56 info="the input jet container, with a possible selection, in the "
57 "format container or container.selection. The default is '' "
58 "(empty string).")
59 self.addOption('largeRjets', "", type=str,
60 info="the large-R jet container, with a possible selection, in "
61 "the format container or container.selection. The default is '' "
62 "(empty string).")
63 self.addOption('photons', "", type=str,
64 info="the input photon container, with a possible selection, in "
65 "the format container or container.selection. The default is '' "
66 "(empty string).")
67 self.addOption('taus', "", type=str,
68 info="the input tau-jet container, with a possible selection, in "
69 "the format container or container.selection. The default is '' "
70 "(empty string).")
71 self.addOption('met', "", type=str,
72 info="he input MET container. The default is '' (empty string).")
73 #TODO: add info string
74 self.addOption('metTerm', "Final", type=str,
75 info="")
76 self.addOption('btagDecoration', "", type=str,
77 info="the b-tagging decoration to use when defining b-jets. "
78 "The default is '' (empty string).")
79 self.addOption('preselection', "", type=str,
80 info="the event-wise selection flag to start this event selection "
81 "from. The default is '' (empty string).")
82 self.addOption('selectionCuts', "", type=str,
83 noneAction='error',
84 info="a single string listing one selection cut per line.")
85 self.addOption('noFilter', False, type=bool,
86 info="do not apply an event filter. The default is False, i.e. "
87 "remove events not passing the full list of selection cuts.")
88 self.addOption('debugMode', False, type=bool,
89 info="whether to create an output branch for every single line "
90 "of the selection cuts. The default is False (only saves the"
91 " final decision).")
92 self.addOption('useDressedProperties', True, type=bool,
93 info="whether to use dressed truth electron and truth muon "
94 "kinematics rather than simple P4 kinematics.")
95 self.step = 0
97 self.cutflow = []
98
99 def instanceName (self) :
100 """Return the instance name for this block"""
101 return self.name
102
103 def makeAlgs(self, config):
104 # need to re-initialize here to deal with multiple passes
105 self.step = 0
106 # initialize the pre-selection
107 self.currentDecoration = self.preselection
108 # re-initialize the cutflow
109 self.cutflow = []
110 # read the selection cuts
111 if self.selectionCuts is None:
112 raise ValueError ("[EventSelectionConfig] You must provide the 'selectionCuts' option to 'EventSelectionConfig': "
113 "a single string where each line represents a different selection cut to apply in order.")
114 for line in self.selectionCuts.split("\n"):
115 self.interpret(line, config)
116 config.addEventCutFlow(self.name, self.getCutflow())
117
118 def interpret(self, text, cfg):
119 text = text.strip()
120 if not text:
121 return
122 if text.startswith("#"):
123 return
124 self.step += 1
125 if "EL_N" in text.split():
126 self.add_NEL_selector(text, cfg)
127 elif "MU_N" in text.split():
128 self.add_NMU_selector(text, cfg)
129 elif "SUM_EL_N_MU_N" in text.split():
130 self.add_SUMNELNMU_selector(text, cfg)
131 elif "SUM_EL_N_MU_N_TAU_N" in text.split():
132 self.add_SUMNLEPTONS_selector(text, cfg)
133 elif "JET_N_GHOST" in text.split():
134 self.add_NJETGHOST_selector(text, cfg)
135 elif "JET_N" in text.split():
136 self.add_NJET_selector(text, cfg)
137 elif "JET_N_BTAG" in text.split():
138 self.add_NBJET_selector(text, cfg)
139 elif "PH_N" in text.split():
140 self.add_NPH_selector(text, cfg)
141 elif "TAU_N" in text.split():
142 self.add_NTAU_selector(text, cfg)
143 elif "LJET_N_GHOST" in text.split():
144 self.add_NLJETGHOST_selector(text, cfg)
145 elif "LJET_N" in text.split():
146 self.add_NLJET_selector(text, cfg)
147 elif "OBJ_N" in text.split():
148 self.add_NOBJ_selector(text, cfg)
149 elif "MET" in text.split():
150 self.add_MET_selector(text, cfg)
151 elif "MWT" in text.split():
152 self.add_MWT_selector(text, cfg)
153 elif "MET+MWT" in text.split():
154 self.add_METMWT_selector(text, cfg)
155 elif "MLL" in text.split():
156 self.add_MLL_selector(text, cfg)
157 elif "MLLWINDOW" in text.split():
158 self.add_MLLWINDOW_selector(text, cfg)
159 elif "OS" in text.split():
160 self.add_OS_selector(text, cfg)
161 elif "SS" in text.split():
162 self.add_SS_selector(text, cfg)
163 elif "MLL_OSSF" in text.split():
164 self.add_MLL_OSSF_selector(text, cfg)
165 elif "LJETMASS_N" in text.split():
166 self.add_NLJETMASS_selector(text, cfg)
167 elif "LJETMASSWINDOW_N" in text.split():
168 self.add_NLJETMASSWINDOW_selector(text, cfg)
169 elif "SAVE" in text.split():
170 self.add_SAVE(text, cfg)
171 elif "IMPORT" in text.split():
172 self.add_IMPORT(text, cfg)
173 elif "EVENTFLAG" in text.split():
174 self.add_EVENTFLAG(text, cfg)
175 elif "GLOBALTRIGMATCH" in text.split():
176 self.add_GLOBALTRIGMATCH(text, cfg)
177 elif "RUN_NUMBER" in text.split():
178 self.add_RUNNUMBER(text, cfg)
179 else:
180 raise ValueError (f"[EventSelectionConfig] The following selection cut is not recognised! --> {text}")
181
182 def raise_misconfig(self, text, keyword):
183 raise ValueError (f"[EventSelectionConfig] Misconfiguration! Check {keyword} in: {text}")
184
185 def raise_missinginput(self, collection):
186 raise ValueError (f"[EventSelectionConfig] Misconfiguration! Missing input collection for {collection}")
187
188 def check_float(self, test, requirePositive=True):
189 try:
190 value = float(test)
191 if not requirePositive or value >= 0:
192 return value
193 else:
194 raise ValueError (f"[EventSelectionConfig] Misconfiguration! Float {test} is not positive!")
195 except ValueError:
196 raise ValueError (f"[EventSelectionConfig] Misconfiguration! {test} should be a float, not {type(test)}!")
197
198 def check_int(self, test, requirePositive=True):
199 try:
200 value = int(test)
201 if value == float(test):
202 if not requirePositive or value >= 0:
203 return value
204 else:
205 raise ValueError (f"[EventSelectionConfig] Misconfiguration! Int {test} us not positive!")
206 else:
207 raise ValueError (f"[EventSelectionConfig] Misconfiguration! {test} should be an int, not a float!")
208 except ValueError:
209 raise ValueError (f"[EventSelectionConfig] Misconfiguration! {test} should be an int, not {type(test)}")
210
211 def check_string(self, test):
212 if not isinstance(test, str):
213 raise ValueError (f"[EventSelectionConfig] Misconfiguration! {test} should be a string, not a number!")
214 else:
215 return test
216
217 def check_sign(self, test):
218 mapping = {
219 "<" : "LT",
220 ">" : "GT",
221 "==": "EQ",
222 ">=": "GE",
223 "<=": "LE"
224 }
225 try:
226 return mapping[test]
227 except KeyError:
228 raise KeyError (f"[EventSelectionConfig] Misconfiguration! {test} should be one of {list(mapping.keys())}")
229
230 def check_btagging(self, test):
231 test = test.split(":")
232 if len(test) != 2:
233 raise ValueError (f"[EventSelectionConfig] Misconfiguration! {test} should be provided as 'btagger:btagWP'")
234 else:
235 return test
236
237 def check_ghosts(self, test):
238 test = self.check_string(test)
239 values = test.split("!")
240 ghost_map = {
241 "B": "GhostBHadronsFinalCount",
242 "C": "GhostCHadronsFinalCount",
243 "T": "GhostTQuarksFinalCount",
244 "W": "GhostWBosonsCount",
245 "Z": "GhostZBosonsCount",
246 "H": "GhostHBosonsCount",
247 "TAU": "GhostTausFinalCount"
248 }
249 return [ghost_map.get(value.upper(), value) for value in values]
250
251 def getCutflow(self):
252 return self.cutflow
253
254 def setDecorationName(self, algorithm, config, decoration):
255 self.cutflow.append( decoration )
256 if algorithm is not None:
257 algorithm.decorationName = f'{decoration},as_char'
258 self.currentDecoration = decoration
259 if self.debugMode:
260 config.addOutputVar('EventInfo', decoration, decoration.split("_%SYS%")[0])
261 else:
262 if self.currentDecoration:
263 self.currentDecoration += '&&' + decoration
264 else:
265 self.currentDecoration = decoration
266 config.addSelection('EventInfo', '', decoration)
267 return
268
269 def checkDecorationName(self, decoration):
270 if decoration == '':
271 return decoration
272 decoration = decoration.split("&&")
273 decoration = [sub + ',as_char' if ',as_char' not in sub else sub for sub in decoration]
274 return '&&'.join(decoration)
275
276 def extendObjectSelection(self, config, container, oldSelection, newSelection):
277 if oldSelection:
278 return oldSelection + "&&" + config.getFullSelection(container, newSelection)
279 else:
280 return config.getFullSelection(container, newSelection)
281
282 def add_IMPORT(self, text, config):
283 # this is used to import a previous selection
284 items = text.split()
285 if items[0] != "IMPORT":
286 self.raise_misconfig(text, "IMPORT")
287 if len(items) != 2:
288 self.raise_misconfig(text, "number of arguments")
289 region = self.check_string(items[1])
290 if not self.currentDecoration:
291 self.currentDecoration = f'pass_{region}_%SYS%,as_char'
292 else:
293 self.currentDecoration = f'{self.currentDecoration},as_char&&pass_{region}_%SYS%'
294 # for the cutflow, we need to retrieve all the cuts corresponding to this IMPORT
295 imported_cuts = [cut for cut in config.getSelectionCutFlow('EventInfo', '') if cut.startswith(region)]
296 self.cutflow += imported_cuts
297 return
298
299 def add_NEL_selector(self, text, config):
300 items = text.split()
301 if items[0] != "EL_N":
302 self.raise_misconfig(text, "EL_N")
303 if len(items) != 4 and len(items) != 5:
304 self.raise_misconfig(text, "number of arguments")
305 if not self.electrons:
306 self.raise_missinginput("electrons")
307 thisalg = f'{self.name}_NEL_{self.step}'
308 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
309 alg.particles, alg.objectSelection = config.readNameAndSelection(self.electrons)
310 if "Truth" in self.electrons:
311 alg.useDressedProperties = self.useDressedProperties
312 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
313 if len(items) == 4:
314 alg.minPt = self.check_float(items[1])
315 alg.sign = self.check_sign(items[2])
316 alg.count = self.check_int(items[3])
317 elif len(items) == 5:
318 extraSel = self.check_string(items[1])
319 alg.objectSelection = self.extendObjectSelection(config, self.electrons.split(".")[0], alg.objectSelection, extraSel)
320 alg.minPt = self.check_float(items[2])
321 alg.sign = self.check_sign(items[3])
322 alg.count = self.check_int(items[4])
323 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
324 return
325
326 def add_NMU_selector(self, text, config):
327 items = text.split()
328 if items[0] != "MU_N":
329 self.raise_misconfig(text, "MU_N")
330 if len(items) != 4 and len(items) != 5:
331 self.raise_misconfig(text, "number of arguments")
332 if not self.muons:
333 self.raise_missinginput("muons")
334 thisalg = f'{self.name}_NMU_{self.step}'
335 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
336 alg.particles, alg.objectSelection = config.readNameAndSelection(self.muons)
337 if "Truth" in self.muons:
338 alg.useDressedProperties = self.useDressedProperties
339 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
340 if len(items) == 4:
341 alg.minPt = self.check_float(items[1])
342 alg.sign = self.check_sign(items[2])
343 alg.count = self.check_int(items[3])
344 elif len(items) == 5:
345 extraSel = self.check_string(items[1])
346 alg.objectSelection = self.extendObjectSelection(config, self.muons.split(".")[0], alg.objectSelection, extraSel)
347 alg.minPt = self.check_float(items[2])
348 alg.sign = self.check_sign(items[3])
349 alg.count = self.check_int(items[4])
350 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
351 return
352
353 def add_SUMNELNMU_selector(self, text, config):
354 items = text.split()
355 if items[0] != "SUM_EL_N_MU_N":
356 self.raise_misconfig(text, "SUM_EL_N_MU_N")
357 if len(items) != 4 and len(items) != 5 and len(items) != 7:
358 self.raise_misconfig(text, "number of arguments")
359 if not self.electrons and not self.muons:
360 self.raise_missinginput("electrons or muons")
361 thisalg = f'{self.name}_SUMNELNMU_{self.step}'
362 alg = config.createAlgorithm('CP::SumNLeptonPtSelectorAlg', thisalg)
363 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
364 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
365 if "Truth" in self.electrons:
366 alg.useDressedProperties = self.useDressedProperties
367 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
368 if len(items) == 4:
369 alg.minPtEl = self.check_float(items[1])
370 alg.minPtMu = self.check_float(items[1])
371 alg.sign = self.check_sign(items[2])
372 alg.count = self.check_int(items[3])
373 elif len(items) == 5:
374 alg.minPtEl = self.check_float(items[1])
375 alg.minPtMu = self.check_float(items[2])
376 alg.sign = self.check_sign(items[3])
377 alg.count = self.check_int(items[4])
378 elif len(items) == 7:
379 extraSelEl = self.check_string(items[1])
380 extraSelMu = self.check_string(items[2])
381 alg.electronSelection = self.extendObjectSelection(config, self.electrons.split(".")[0], alg.electronSelection, extraSelEl)
382 alg.muonSelection = self.extendObjectSelection(config, self.muons.split(".")[0], alg.muonSelection, extraSelMu)
383 alg.minPtEl = self.check_float(items[3])
384 alg.minPtMu = self.check_float(items[4])
385 alg.sign = self.check_sign(items[5])
386 alg.count = self.check_int(items[6])
387 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
388 return
389
390 def add_SUMNLEPTONS_selector(self, text, config):
391 items = text.split()
392 if items[0] != "SUM_EL_N_MU_N_TAU_N":
393 self.raise_misconfig(text, "SUM_EL_N_MU_N_TAU_N")
394 if len(items) != 4 and len(items) != 6 and len(items) != 9:
395 self.raise_misconfig(text, "number of arguments")
396 if not self.electrons and not self.muons and not self.taus:
397 self.raise_missinginput("electrons, muons or taus")
398 thisalg = f'{self.name}_SUMNLEPTONS_{self.step}'
399 alg = config.createAlgorithm('CP::SumNLeptonPtSelectorAlg', thisalg)
400 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
401 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
402 alg.taus, alg.tauSelection = config.readNameAndSelection(self.taus)
403 if "Truth" in self.electrons:
404 alg.useDressedProperties = self.useDressedProperties
405 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
406 if len(items) == 4:
407 alg.minPtEl = self.check_float(items[1])
408 alg.minPtMu = self.check_float(items[1])
409 alg.minPtTau = self.check_float(items[1])
410 alg.sign = self.check_sign(items[2])
411 alg.count = self.check_int(items[3])
412 elif len(items) == 6:
413 alg.minPtEl = self.check_float(items[1])
414 alg.minPtMu = self.check_float(items[2])
415 alg.minPtTau = self.check_float(items[3])
416 alg.sign = self.check_sign(items[4])
417 alg.count = self.check_int(items[5])
418 elif len(items) == 9:
419 extraSelEl = self.check_string(items[1])
420 extraSelMu = self.check_string(items[2])
421 extraSelTau = self.check_string(items[3])
422 alg.electronSelection = self.extendObjectSelection(config, self.electrons.split(".")[0], alg.electronSelection, extraSelEl)
423 alg.muonSelection = self.extendObjectSelection(config, self.muons.split(".")[0], alg.muonSelection, extraSelMu)
424 alg.tauSelection = self.extendObjectSelection(config, self.taus.split(".")[0], alg.tauSelection, extraSelTau)
425 alg.minPtEl = self.check_float(items[4])
426 alg.minPtMu = self.check_float(items[5])
427 alg.minPtTau = self.check_float(items[6])
428 alg.sign = self.check_sign(items[7])
429 alg.count = self.check_int(items[8])
430 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
431 return
432
433 def add_NJET_selector(self, text, config):
434 items = text.split()
435 if items[0] != "JET_N":
436 self.raise_misconfig(text, "JET_N")
437 if len(items) != 4 and len(items) != 5:
438 self.raise_misconfig(text, "number of arguments")
439 if not self.jets:
440 self.raise_missinginput("jets")
441 thisalg = f'{self.name}_NJET_{self.step}'
442 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
443 alg.particles, alg.objectSelection = config.readNameAndSelection(self.jets)
444 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
445 if len(items) == 4:
446 alg.minPt = self.check_float(items[1])
447 alg.sign = self.check_sign(items[2])
448 alg.count = self.check_int(items[3])
449 elif len(items) == 5:
450 extraSel = self.check_string(items[1])
451 alg.objectSelection = self.extendObjectSelection(config, self.jets.split(".")[0], alg.objectSelection, extraSel)
452 alg.minPt = self.check_float(items[2])
453 alg.sign = self.check_sign(items[3])
454 alg.count = self.check_int(items[4])
455 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
456 return
457
458 def add_NBJET_selector(self, text, config):
459 items = text.split()
460 if items[0] != "JET_N_BTAG":
461 self.raise_misconfig(text, "JET_N_BTAG")
462 if len(items) != 3 and len(items) != 4 and len(items) != 5:
463 self.raise_misconfig(text, "number of arguments")
464 if not self.jets:
465 self.raise_missinginput("jets")
466 thisalg = f'{self.name}_NBJET_{self.step}'
467 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
468 particles, selection = config.readNameAndSelection(self.jets)
469 alg.particles = particles
470 alg.objectSelection = f'{selection}&&{self.btagDecoration},as_char' if selection else f'{self.btagDecoration},as_char'
471 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
472 if len(items) == 3:
473 alg.sign = self.check_sign(items[1])
474 alg.count = self.check_int(items[2])
475 elif len(items) == 4:
476 if ":" in text:
477 btagger, btagWP = self.check_btagging(items[1])
478 customBtag = f'ftag_select_{btagger}_{btagWP}'
479 alg.objectSelection = f'{selection}&&{customBtag},as_char' if selection else f'{customBtag},as_char'
480 else:
481 extraSel = self.check_string(items[1])
482 alg.objectSelection = self.extendObjectSelection(config, self.jets.split(".")[0], alg.objectSelection, extraSel)
483 alg.sign = self.check_sign(items[2])
484 alg.count = self.check_int(items[3])
485 elif len(items) == 5:
486 extraSel = self.check_string(items[1])
487 btagger, btagWP = self.check_btagging(items[2])
488 customBtag = f'ftag_select_{btagger}_{btagWP}'
489 alg.objectSelection = f'{selection}&&{customBtag},as_char' if selection else f'{customBtag},as_char'
490 alg.objectSelection = self.extendObjectSelection(config, self.jets.split(".")[0], alg.objectSelection, extraSel)
491 alg.sign = self.check_sign(items[3])
492 alg.count = self.check_int(items[4])
493 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
494 return
495
496 def add_NPH_selector(self, text, config):
497 items = text.split()
498 if items[0] != "PH_N":
499 self.raise_misconfig(text, "PH_N")
500 if len(items) != 4 and len(items) != 5:
501 self.raise_misconfig(text, "number of arguments")
502 if not self.photons:
503 self.raise_missinginput("photons")
504 thisalg = f'{self.name}_NPH_{self.step}'
505 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
506 alg.particles, alg.objectSelection = config.readNameAndSelection(self.photons)
507 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
508 if len(items) == 4:
509 alg.minPt = self.check_float(items[1])
510 alg.sign = self.check_sign(items[2])
511 alg.count = self.check_int(items[3])
512 elif len(items) == 5:
513 extraSel = self.check_string(items[1])
514 alg.objectSelection = self.extendObjectSelection(config, self.photons.split(".")[0], alg.objectSelection, extraSel)
515 alg.minPt = self.check_float(items[2])
516 alg.sign = self.check_sign(items[3])
517 alg.count = self.check_int(items[4])
518 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
519 return
520
521 def add_NTAU_selector(self, text, config):
522 items = text.split()
523 if items[0] != "TAU_N":
524 self.raise_misconfig(text, "TAU_N")
525 if len(items) != 4 and len(items) != 5:
526 self.raise_misconfig(text, "number of arguments")
527 if not self.taus:
528 self.raise_missinginput("taus")
529 thisalg = f'{self.name}_NTAU_{self.step}'
530 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
531 alg.particles, alg.objectSelection = config.readNameAndSelection(self.taus)
532 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
533 if len(items) == 4:
534 alg.minPt = self.check_float(items[1])
535 alg.sign = self.check_sign(items[2])
536 alg.count = self.check_int(items[3])
537 elif len(items) == 5:
538 extraSel = self.check_string(items[1])
539 alg.objectSelection = self.extendObjectSelection(config, self.taus.split(".")[0], alg.objectSelection, extraSel)
540 alg.minPt = self.check_float(items[2])
541 alg.sign = self.check_sign(items[3])
542 alg.count = self.check_int(items[4])
543 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
544 return
545
546 def add_NLJET_selector(self, text, config):
547 items = text.split()
548 if items[0] != "LJET_N":
549 self.raise_misconfig(text, "LJET_N")
550 if len(items) != 4 and len(items) != 5:
551 self.raise_misconfig(text, "number of arguments")
552 thisalg = f'{self.name}_NLJET_{self.step}'
553 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
554 alg.particles, alg.objectSelection = config.readNameAndSelection(self.largeRjets)
555 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
556 if len(items) == 4:
557 alg.minPt = self.check_float(items[1])
558 alg.sign = self.check_sign(items[2])
559 alg.count = self.check_int(items[3])
560 elif len(items) == 5:
561 extraSel = self.check_string(items[1])
562 alg.objectSelection = self.extendObjectSelection(config, self.largeRjets.split(".")[0], alg.objectSelection, extraSel)
563 alg.minPt = self.check_float(items[2])
564 alg.sign = self.check_sign(items[3])
565 alg.count = self.check_int(items[4])
566 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
567 return
568
569 def add_NLJETMASS_selector(self, text, config):
570 items = text.split()
571 if items[0] != "LJETMASS_N":
572 self.raise_misconfig(text, "LJETMASS_N")
573 if len(items) != 4 and len(items) != 5:
574 self.raise_misconfig(text, "number of arguments")
575 thisalg = f'{self.name}_NLJETMASS_{self.step}'
576 alg = config.createAlgorithm('CP::NObjectMassSelectorAlg', thisalg)
577 alg.particles, alg.objectSelection = config.readNameAndSelection(self.largeRjets)
578 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
579 if len(items) == 4:
580 alg.minMass = self.check_float(items[1])
581 alg.sign = self.check_sign(items[2])
582 alg.count = self.check_int(items[3])
583 elif len(items) == 5:
584 extraSel = self.check_string(items[1])
585 alg.objectSelection = self.extendObjectSelection(config, self.largeRjets.split(".")[0], alg.objectSelection, extraSel)
586 alg.minMass = self.check_float(items[2])
587 alg.sign = self.check_sign(items[3])
588 alg.count = self.check_int(items[4])
589 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
590 return
591
592 def add_NLJETMASSWINDOW_selector(self, text, config):
593 items = text.split()
594 if items[0] != "LJETMASSWINDOW_N":
595 self.raise_misconfig(text, "LJETMASSWINDOW_N")
596 if len(items) != 5 and len(items) != 6 and len(items) != 7:
597 self.raise_misconfig(text, "number of arguments")
598 thisalg = f'{self.name}_NLJETMASSWINDOW_{self.step}'
599 alg = config.createAlgorithm('CP::NLargeRJetMassWindowSelectorAlg', thisalg)
600 alg.ljets, alg.ljetSelection = config.readNameAndSelection(self.largeRjets)
601 vetoMode = items[-1] == 'veto' or items[-1] == 'VETO'
602 if len(items) == 5 or (len(items) == 6 and vetoMode):
603 alg.lowMass = self.check_float(items[1])
604 alg.highMass = self.check_float(items[2])
605 alg.sign = self.check_sign(items[3])
606 alg.count = self.check_int(items[4])
607 alg.vetoMode = vetoMode
608 elif (len(items) == 6 and not vetoMode) or len(items) == 7:
609 extraSel = self.check_string(items[1])
610 alg.ljetSelection = self.extendObjectSelection(config, self.largeRjets.split(".")[0], alg.ljetSelection, extraSel)
611 alg.lowMass = self.check_float(items[2])
612 alg.highMass = self.check_float(items[3])
613 alg.sign = self.check_sign(items[4])
614 alg.count = self.check_int(items[5])
615 alg.vetoMode = vetoMode
616 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
617 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
618 return
619
620 def add_NJETGHOST_selector(self, text, config):
621 items = text.split()
622 if items[0] != "JET_N_GHOST":
623 self.raise_misconfig(text, "JET_N_GHOST")
624 if len(items) != 4 and len(items) != 5:
625 self.raise_misconfig(text, "number of arguments")
626 thisalg = f'{self.name}_NJETGHOST_{self.step}'
627 alg = config.createAlgorithm('CP::JetNGhostSelectorAlg', thisalg)
628 alg.jets, alg.jetSelection = config.readNameAndSelection(self.jets)
629 ghosts = self.check_ghosts(items[1])
630 alg.ghost = ghosts[0]
631 if len(ghosts) > 1 :
632 alg.veto = ghosts[1]
633 if len(items) == 4:
634 alg.sign = self.check_sign(items[2])
635 alg.count = self.check_int(items[3])
636 elif len(items) == 5:
637 alg.minPt = self.check_float(items[2])
638 alg.sign = self.check_sign(items[3])
639 alg.count = self.check_int(items[4])
640 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
641 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
642 return
643
644 def add_NLJETGHOST_selector(self, text, config):
645 items = text.split()
646 if items[0] != "LJET_N_GHOST":
647 self.raise_misconfig(text, "LJET_N_GHOST")
648 if len(items) != 4 and len(items) != 5:
649 self.raise_misconfig(text, "number of arguments")
650 thisalg = f'{self.name}_NLJETGHOST_{self.step}'
651 alg = config.createAlgorithm('CP::JetNGhostSelectorAlg', thisalg)
652 alg.jets, alg.jetSelection = config.readNameAndSelection(self.largeRjets)
653 ghosts = self.check_ghosts(items[1])
654 alg.ghost = ghosts[0]
655 if len(ghosts) > 1 :
656 alg.veto = ghosts[1]
657 if len(items) == 4:
658 alg.sign = self.check_sign(items[2])
659 alg.count = self.check_int(items[3])
660 elif len(items) == 5:
661 alg.minPt = self.check_float(items[2])
662 alg.sign = self.check_sign(items[3])
663 alg.count = self.check_int(items[4])
664 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
665 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
666 return
667
668 def add_NOBJ_selector(self, text, config):
669 items = text.split()
670 if items[0] != "OBJ_N":
671 self.raise_misconfig(text, "OBJ_N")
672 if len(items) != 5:
673 self.raise_misconfig(text, "number of arguments")
674 thisalg = f'{self.name}_NOBJ_{self.step}'
675 alg = config.createAlgorithm('CP::NObjectPtSelectorAlg', thisalg)
676 alg.particles, alg.objectSelection = config.readNameAndSelection(self.check_string(items[1]))
677 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
678 alg.minPt = self.check_float(items[2])
679 alg.sign = self.check_sign(items[3])
680 alg.count = self.check_int(items[4])
681 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
682 return
683
684 def add_MET_selector(self, text, config):
685 items = text.split()
686 if items[0] != "MET":
687 self.raise_misconfig(text, "MET")
688 if len(items) != 3:
689 self.raise_misconfig(text, "number of arguments")
690 if not self.met:
691 self.raise_missinginput("MET")
692 thisalg = f'{self.name}_MET_{self.step}'
693 alg = config.createAlgorithm('CP::MissingETSelectorAlg', thisalg)
694 alg.met = config.readName(self.met)
695 alg.metTerm = self.metTerm
696 alg.sign = self.check_sign(items[1])
697 alg.refMET = self.check_float(items[2])
698 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
699 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
700 return
701
702 def add_MWT_selector(self, text, config):
703 items = text.split()
704 if items[0] != "MWT":
705 self.raise_misconfig(text, "MWT")
706 if len(items) != 3:
707 self.raise_misconfig(text, "number of arguments")
708 if not self.electrons and not self.muons:
709 self.raise_missinginput("electrons or muons")
710 thisalg = f'{self.name}_MWT_{self.step}'
711 alg = config.createAlgorithm('CP::TransverseMassSelectorAlg', thisalg)
712 alg.met = config.readName(self.met)
713 alg.metTerm = self.metTerm
714 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
715 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
716 if "Truth" in self.electrons or "Truth" in self.muons:
717 alg.useDressedProperties = self.useDressedProperties
718 alg.sign = self.check_sign(items[1])
719 alg.refMWT = self.check_float(items[2])
720 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
721 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
722 return
723
724 def add_METMWT_selector(self, text, config):
725 items = text.split()
726 if items[0] != "MET+MWT":
727 self.raise_misconfig(text, "MET+MWT")
728 if len(items) != 3:
729 self.raise_misconfig(text, "number of arguments")
730 if not self.met:
731 self.raise_missinginput("MET")
732 if not self.electrons and not self.muons:
733 self.raise_missinginput("electrons or muons")
734 thisalg = f'{self.name}_METMWT_{self.step}'
735 alg = config.createAlgorithm('CP::MissingETPlusTransverseMassSelectorAlg', thisalg)
736 alg.met = config.readName(self.met)
737 alg.metTerm = self.metTerm
738 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
739 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
740 if "Truth" in self.electrons or "Truth" in self.muons:
741 alg.useDressedProperties = self.useDressedProperties
742 alg.sign = self.check_sign(items[1])
743 alg.refMETMWT = self.check_float(items[2])
744 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
745 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
746 return
747
748 def add_MLL_selector(self, text, config):
749 items = text.split()
750 if items[0] != "MLL":
751 self.raise_misconfig(text, "MLL")
752 if len(items) != 3:
753 self.raise_misconfig(text, "number of arguments")
754 if not self.electrons and not self.muons:
755 self.raise_missinginput("electrons or muons")
756 thisalg = f'{self.name}_MLL_{self.step}'
757 alg = config.createAlgorithm('CP::DileptonInvariantMassSelectorAlg', thisalg)
758 if self.electrons:
759 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
760 if self.muons:
761 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
762 if "Truth" in self.electrons or "Truth" in self.muons:
763 alg.useDressedProperties = self.useDressedProperties
764 alg.sign = self.check_sign(items[1])
765 alg.refMLL = self.check_float(items[2])
766 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
767 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
768 return
769
770 def add_MLLWINDOW_selector(self, text, config):
771 items = text.split()
772 if items[0] != "MLLWINDOW":
773 self.raise_misconfig(text, "MLLWINDOW")
774 if len(items) != 3 and len(items) != 4:
775 self.raise_misconfig(text, "number of arguments")
776 if not self.electrons and not self.muons:
777 self.raise_missinginput("electrons or muons")
778 thisalg = f'{self.name}_MLLWINDOW_{self.step}'
779 alg = config.createAlgorithm('CP::DileptonInvariantMassWindowSelectorAlg', thisalg)
780 if self.electrons:
781 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
782 if self.muons:
783 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
784 if "Truth" in self.electrons or "Truth" in self.muons:
785 alg.useDressedProperties = self.useDressedProperties
786 alg.lowMLL = self.check_float(items[1])
787 alg.highMLL = self.check_float(items[2])
788 alg.vetoMode = (len(items) == 4 and self.check_string(items[3]).lower() == "veto")
789 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
790 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
791 return
792
793 def add_OS_selector(self, text, config):
794 items = text.split()
795 if not items or len(items) > 4:
796 self.raise_misconfig(text, "number of arguments")
797 if not self.electrons and not self.muons and not self.taus:
798 self.raise_missinginput("electrons or muons or taus")
799 thisalg = f'{self.name}_OS_{self.step}'
800 alg = config.createAlgorithm('CP::ChargeSelectorAlg', thisalg)
801 if self.electrons and (len(items) == 1 or "el" in items):
802 if "Particle" in self.electrons or "Truth" in self.electrons:
803 alg.truthElectrons, alg.truthElectronSelection = config.readNameAndSelection(self.electrons)
804 else:
805 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
806 if self.muons and (len(items) == 1 or "mu" in items):
807 if "Particle" in self.muons or "Truth" in self.muons:
808 alg.truthMuons, alg.truthMuonSelection = config.readNameAndSelection(self.muons)
809 else:
810 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
811 if self.taus and (len(items) == 1 or "tau" in items):
812 if "Particle" in self.taus or "Truth" in self.taus:
813 alg.truthTaus, alg.truthTauSelection = config.readNameAndSelection(self.taus)
814 else:
815 alg.taus, alg.tauSelection = config.readNameAndSelection(self.taus)
816 alg.OS = True
817 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
818 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
819 return
820
821 def add_SS_selector(self, text, config):
822 items = text.split()
823 if not items or len(items) > 4:
824 self.raise_misconfig(text, "number of arguments")
825 if not self.electrons and not self.muons and not self.taus:
826 self.raise_missinginput("electrons or muons or taus")
827 thisalg = f'{self.name}_SS_{self.step}'
828 alg = config.createAlgorithm('CP::ChargeSelectorAlg', thisalg)
829 if self.electrons and (len(items) == 1 or "el" in items):
830 if "Particle" in self.electrons or "Truth" in self.electrons:
831 alg.truthElectrons, alg.truthElectronSelection = config.readNameAndSelection(self.electrons)
832 else:
833 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
834 if self.muons and (len(items) == 1 or "mu" in items):
835 if "Particle" in self.muons or "Truth" in self.muons:
836 alg.truthMuons, alg.truthMuonSelection = config.readNameAndSelection(self.muons)
837 else:
838 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
839 if self.taus and (len(items) == 1 or "tau" in items):
840 if "Particle" in self.taus or "Truth" in self.taus:
841 alg.truthTaus, alg.truthTauSelection = config.readNameAndSelection(self.taus)
842 else:
843 alg.taus, alg.tauSelection = config.readNameAndSelection(self.taus)
844 alg.OS = False
845 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
846 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
847 return
848
849 def add_MLL_OSSF_selector(self, text, config):
850 items = text.split()
851 if items[0] != "MLL_OSSF":
852 self.raise_misconfig(text, "MLL_OSSF")
853 if len(items) != 3 and len(items) != 4:
854 self.raise_misconfig(text, "number of arguments")
855 if not self.electrons and not self.muons:
856 self.raise_missinginput("electrons or muons")
857 thisalg = f'{self.name}_MLL_OSSF_{self.step}'
858 alg = config.createAlgorithm('CP::DileptonOSSFInvariantMassWindowSelectorAlg', thisalg)
859 if self.electrons:
860 if "Particle" in self.electrons or "Truth" in self.electrons:
861 alg.truthElectrons, alg.truthElectronSelection = config.readNameAndSelection(self.electrons)
862 else:
863 alg.electrons, alg.electronSelection = config.readNameAndSelection(self.electrons)
864 if self.muons:
865 if "Particle" in self.muons or "Truth" in self.muons:
866 alg.truthMuons, alg.truthMuonSelection = config.readNameAndSelection(self.muons)
867 else:
868 alg.muons, alg.muonSelection = config.readNameAndSelection(self.muons)
869 if "Truth" in self.electrons or "Truth" in self.muons:
870 alg.useDressedProperties = self.useDressedProperties
871 alg.lowMll = self.check_float(items[1])
872 alg.highMll = self.check_float(items[2])
873 alg.vetoMode = (len(items) == 4 and self.check_string(items[3]).lower() == "veto")
874 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
875 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
876 return
877
878 def add_EVENTFLAG(self, text, config):
879 items = text.split()
880 if items[0] != "EVENTFLAG":
881 self.raise_misconfig(text, "EVENTFLAG")
882 if len(items) != 2:
883 self.raise_misconfig(text, "number of arguments")
884 existingDecoration = self.check_string(items[1])
885 self.setDecorationName(None, config, existingDecoration)
886 return
887
888 def add_GLOBALTRIGMATCH(self, text, config):
889 items = text.split()
890 if items[0] != "GLOBALTRIGMATCH":
891 self.raise_misconfig(text, "GLOBALTRIGMATCH")
892 if len(items) != 1 and len(items) != 2 :
893 self.raise_misconfig(text, "number of arguments")
894 if len(items) == 1:
895 self.setDecorationName(None, config, "globalTriggerMatch_%SYS%,as_char")
896 else:
897 postfix = self.check_string(items[1])
898 self.setDecorationName(None, config, f"globalTriggerMatch{postfix}_%SYS%,as_char")
899 return
900
901 def add_RUNNUMBER(self, text, config):
902 items = text.split()
903 if items[0] != "RUN_NUMBER":
904 self.raise_misconfig(text, "RUN_NUMBER")
905 if len(items) != 3:
906 self.raise_misconfig(text, "number of arguments")
907 thisalg = f'{self.name}_RUN_NUMBER_{self.step}'
908 alg = config.createAlgorithm('CP::RunNumberSelectorAlg', thisalg)
909 alg.sign = self.check_sign(items[1])
910 alg.runNumber = self.check_int(items[2])
911 alg.useRandomRunNumber = config.dataType() is not DataType.Data
912 alg.eventPreselection = self.checkDecorationName(self.currentDecoration)
913 self.setDecorationName(alg, config, f'{thisalg}_%SYS%')
914 return
915
916 def add_SAVE(self, text, config):
917 items = text.split()
918 if items[0] != "SAVE":
919 self.raise_misconfig(text, "SAVE")
920 if len(items) != 1:
921 self.raise_misconfig(text, "number of arguments")
922 thisalg = f'{self.name}_SAVE'
923 alg = config.createAlgorithm('CP::SaveFilterAlg', thisalg)
924 alg.FilterDescription = f'events passing < {self.name} >'
925 alg.eventDecisionOutputDecoration = f'ignore_{self.name}_%SYS%'
926 alg.selection = self.checkDecorationName(self.currentDecoration)
927 alg.noFilter = self.noFilter
928 alg.selectionName = f'pass_{self.name}_%SYS%,as_char' # this one is used as a selection
929 alg.decorationName = f'ntuplepass_{self.name}_%SYS%' # this one is saved to file
930 config.addOutputVar('EventInfo', f'ntuplepass_{self.name}_%SYS%', f'pass_{self.name}')
931 return
932
934 name,
935 electrons=None, muons=None, jets=None,
936 largeRjets=None,
937 photons=None, taus=None, met=None, metTerm=None,
938 btagDecoration=None, preselection=None,
939 selectionCuts=None, noFilter=None,
940 debugMode=None, cutFlowHistograms=None):
941 """Create an event selection config block
942
943 Keyword arguments:
944 name -- the name defining this selection
945 electrons -- the electron container and selection
946 muons -- the muon container and selection
947 jets -- the jet container and selection
948 largeRjets -- the large-R jet container and selection
949 photons -- the photon container and selection
950 taus -- the tau-jet container and selection
951 met -- the MET container
952 metTerm -- the MET term to use (e.g. 'Final', 'NonInt')
953 btagDecoration -- the b-tagging decoration to use when defining b-jets
954 preselection -- optional event-wise selection flag to start from
955 selectionCuts -- a string listing one selection cut per line
956 noFilter -- whether to disable the event filter
957 debugMode -- enables saving all intermediate decorations
958 cutFlowHistograms -- whether to toggle event cutflow histograms per systematic
959 """
960
961 config = EventSelectionConfig()
962 config.setOptionValue ('name', name)
963 config.setOptionValue ('electrons', electrons)
964 config.setOptionValue ('muons', muons)
965 config.setOptionValue ('jets', jets)
966 config.setOptionValue ('largeRjets', largeRjets)
967 config.setOptionValue ('photons', photons)
968 config.setOptionValue ('taus', taus)
969 config.setOptionValue ('met', met)
970 config.setOptionValue ('metTerm', metTerm)
971 config.setOptionValue ('btagDecoration', btagDecoration)
972 config.setOptionValue ('preselection', preselection)
973 config.setOptionValue ('selectionCuts', selectionCuts)
974 config.setOptionValue ('noFilter', noFilter)
975 config.setOptionValue ('debugMode', debugMode)
976 seq.append(config)
977
978 # add event cutflow algorithm
979 if cutFlowHistograms:
980 makeEventCutFlowConfig(seq, 'EventInfo', selectionName='', postfix=name,
981 customSelections=name)
982
984 electrons=None, muons=None, jets=None,
985 largeRjets=None,
986 photons=None, taus=None, met=None, metTerm=None,
987 btagDecoration=None, preselection=None,
988 selectionCutsDict=None, noFilter=None,
989 debugMode=None, cutFlowHistograms=None):
990 """Create multiple event selection config blocks
991
992 Keyword arguments:
993 electrons -- the electron container and selection
994 muons -- the muon container and selection
995 jets -- the jet container and selection
996 largeRjets -- the large-R jet container and selection
997 photons -- the photon container and selection
998 taus -- the tau-jet container and selection
999 met -- the MET container
1000 metTerm -- the MET term to use (e.g. 'Final', 'NonInt')
1001 btagDecoration -- the b-tagging decoration to use when defining b-jets
1002 preselection -- optional event-wise selection flag to start from
1003 selectionCutsDict -- a dictionary with key the name of the selection and value a string listing one selection cut per line
1004 noFilter -- whether to disable the event filter
1005 debugMode -- enables saving all intermediate decorations
1006 cutFlowHistograms -- whether to toggle event cutflow histograms per region and per systematic
1007 """
1008
1009 # first, we generate all the individual event selections
1010 # !!! it's important to pass noFilter=True, to avoid applying the individual filters in series
1011 for name, selectionCuts in selectionCutsDict.items():
1012 makeEventSelectionConfig(seq, name, electrons, muons, jets, largeRjets, photons, taus, met, metTerm, btagDecoration, preselection, selectionCuts, noFilter=True, debugMode=debugMode, cutFlowHistograms=cutFlowHistograms)
1013
1014 # now we are ready to collect all the filters and apply their logical OR
1015 # !!! subregions (name starts with "SUB") are not used in the final filtering
1017 config.setOptionValue ('selections', [f'pass_{name}_%SYS%' for name in selectionCutsDict.keys() if not name.startswith("SUB")])
1018 config.setOptionValue ('noFilter', noFilter)
1019 seq.append(config)
void print(char *figname, TCanvas *c1)
setDecorationName(self, algorithm, config, decoration)
extendObjectSelection(self, config, container, oldSelection, newSelection)
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
makeEventSelectionConfig(seq, name, electrons=None, muons=None, jets=None, largeRjets=None, photons=None, taus=None, met=None, metTerm=None, btagDecoration=None, preselection=None, selectionCuts=None, noFilter=None, debugMode=None, cutFlowHistograms=None)
makeMultipleEventSelectionConfigs(seq, electrons=None, muons=None, jets=None, largeRjets=None, photons=None, taus=None, met=None, metTerm=None, btagDecoration=None, preselection=None, selectionCutsDict=None, noFilter=None, debugMode=None, cutFlowHistograms=None)