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