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