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