ATLAS Offline Software
AsgAnalysisConfig.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
2 
3 # AnaAlgorithm import(s):
4 from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
5 from AthenaConfiguration.Enums import LHCPeriod
6 from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
7 from enum import Enum
8 
10  JETS = ['JET_']
11  ELECTRONS = ['EG_', 'EL_']
12  MUONS = ['MUON_']
13  PHOTONS = ['EG_', 'PH_']
14  TAUS = ['TAUS_']
15  MET = ['MET_']
16  EVENT = ['GEN_', 'PRW_']
17  FTAG = ['FT_']
18 
19 class CommonServicesConfig (ConfigBlock) :
20  """the ConfigBlock for common services
21 
22  The idea here is that all algorithms need some common services, and I should
23  provide configuration blocks for those. For now there is just a single
24  block, but in the future I might break out e.g. the systematics service.
25  """
26 
27  def __init__ (self) :
28  super (CommonServicesConfig, self).__init__ ()
29  self.addOption ('runSystematics', None, type=bool,
30  info="whether to turn on the computation of systematic variations. "
31  "The default is to run them on MC.")
32  self.addOption ('filterSystematics', None, type=str,
33  info="a regexp string against which the systematics names will be "
34  "matched. Only positive matches are retained and used in the evaluation "
35  "of the various algorithms.")
36  self.addOption ('onlySystematicsCategories', None, type=list,
37  info="a list of strings defining categories of systematics to enable "
38  "(only recommended for studies / partial ntuple productions). Choose amongst: "
39  "jets, electrons, muons, photons, taus, met, ftag, event. This option is overridden "
40  "by 'filterSystematics'.")
41  self.addOption ('systematicsHistogram', None , type=str,
42  info="the name (string) of the histogram to which a list of executed "
43  "systematics will be printed. The default is None (don't write out "
44  "the histogram).")
45 
46  def makeAlgs (self, config) :
47 
48  sysService = config.createService( 'CP::SystematicsSvc', 'SystematicsSvc' )
49 
50  if config.dataType() is not DataType.Data:
51  if self.runSystematics is not None :
52  runSystematics = self.runSystematics
53  elif config.noSystematics() is not None :
54  # if option not set:
55  # check to see if set in config accumulator
56  self.runSystematics = not config.noSystematics()
57  runSystematics = self.runSystematics
58  else :
59  runSystematics = True
60  else:
61  runSystematics = False
62  if runSystematics :
63  sysService.sigmaRecommended = 1
64  if self.onlySystematicsCategories is not None:
65  # Convert strings to enums and validate
66  requested_categories = []
67  for category_str in self.onlySystematicsCategories:
68  try:
69  category_enum = SystematicsCategories[category_str.upper()]
70  requested_categories += category_enum.value
71  except KeyError:
72  raise ValueError(f"Invalid systematics category passed to option 'onlySystematicsCategories': {category_str}. Must be one of {', '.join(category.name for category in SystematicsCategories)}")
73  # Construct regex pattern as logical-OR of category names
74  if len(requested_categories):
75  sysService.systematicsRegex = "^(?=.*(" + "|".join(requested_categories) + ")|$).*"
76  if self.filterSystematics is not None:
77  sysService.systematicsRegex = self.filterSystematics
78  config.createService( 'CP::SelectionNameSvc', 'SelectionNameSvc')
79 
80  if self.systematicsHistogram is not None:
81  sysDumper = config.createAlgorithm( 'CP::SysListDumperAlg', 'SystematicsPrinter' )
82  sysDumper.histogramName = self.systematicsHistogram
83 
84 
85 class IOStatsBlock(ConfigBlock):
86  """Print what branches are used in analysis"""
87 
88  def __init__(self):
89  super(IOStatsBlock, self).__init__()
90  self.addOption("printOption", "Summary", type=str,
91  info='option to pass the standard ROOT printing function. Can be "Summary", "ByEntries" or "ByBytes".')
92 
93  def makeAlgs(self, config):
94  alg = config.createAlgorithm('CP::IOStatsAlg', 'IOStatsAlg')
95  alg.printOption = self.printOption
96 
97 
98 class PileupReweightingBlock (ConfigBlock):
99  """the ConfigBlock for pileup reweighting"""
100 
101  def __init__ (self) :
102  super (PileupReweightingBlock, self).__init__ ()
103  self.addOption ('campaign', None, type=None,
104  info="the MC campaign for the PRW auto-configuration.")
105  self.addOption ('files', None, type=None,
106  info="the input files being processed (list of strings). "
107  "Alternative to auto-configuration.")
108  self.addOption ('useDefaultConfig', True, type=bool,
109  info="whether to use the central PRW files. The default is True.")
110  self.addOption ('userLumicalcFiles', None, type=None,
111  info="user-provided lumicalc files (list of strings). Alternative "
112  "to auto-configuration.")
113  self.addOption ('userLumicalcFilesPerCampaign', None, type=None,
114  info="user-provided lumicalc files (dictionary of list of strings, "
115  "with MC campaigns as the keys). Alternative to auto-configuration.")
116  self.addOption ('userPileupConfigs', None, type=None,
117  info="user-provided PRW files (list of strings). Alternative to "
118  "auto-configuration. Alternative to auto-configuration.")
119  self.addOption ('userPileupConfigsPerCampaign', None, type=None,
120  info="user-provided PRW files (dictionary of list of strings, with "
121  "MC campaigns as the keys)")
122 
123 
124  def makeAlgs (self, config) :
125 
126  from Campaigns.Utils import Campaign
127 
128  try:
129  from AthenaCommon.Logging import logging
130  except ImportError:
131  import logging
132  log = logging.getLogger('makePileupAnalysisSequence')
133 
134  if config.isPhyslite():
135  # PHYSLITE already has these variables defined, just need to copy them to the output
136  log.info(f'Physlite does not need pileup reweighting. Variables will be copied from input instead. {config.isPhyslite}')
137  config.addOutputVar ('EventInfo', 'runNumber', 'runNumber', noSys=True)
138  config.addOutputVar ('EventInfo', 'eventNumber', 'eventNumber', noSys=True)
139  if config.dataType() is not DataType.Data:
140  config.addOutputVar ('EventInfo', 'mcChannelNumber', 'mcChannelNumber', noSys=True)
141  config.addOutputVar ('EventInfo', 'PileupWeight_%SYS%', 'weight_pileup')
142  if config.geometry() is LHCPeriod.Run2:
143  config.addOutputVar ('EventInfo', 'beamSpotWeight', 'weight_beamspot', noSys=True)
144  return
145 
146  # check files from autoconfig flags
147  if self.files is None and config.autoconfigFlags() is not None:
148  self.files = config.autoconfigFlags().Input.Files
149 
150  campaign = self.campaign
151  # if user didn't explicitly configure campaign, let's try setting it from metadata
152  # only needed on MC
153  if config.dataType() is not DataType.Data and self.campaign is None:
154  # if we used autoconfigflags, campaign is auto-determined
155  if config.campaign() is not None and config.campaign() is not Campaign.Unknown:
156  campaign = config.campaign()
157  log.info(f'Auto-configuring campaign for PRW from flags: {campaign.value}')
158  else:
159  # we try to determine campaign from files if above failed
160  if self.files is not None:
161  from Campaigns.Utils import getMCCampaign
162  campaign = getMCCampaign(self.files)
163  if campaign and campaign is not Campaign.Unknown:
164  log.info(f'Auto-configuring campaign for PRW from files: {campaign.value}')
165  else:
166  log.info('Campaign could not be determined.')
167 
168 
169  toolConfigFiles = []
170  toolLumicalcFiles = []
171 
172  # PRW config files should only be configured if we run on MC
173  if config.dataType() is not DataType.Data:
174  # check if user provides per-campaign pileup config list
175  if self.userPileupConfigs is not None and self.userPileupConfigsPerCampaign is not None:
176  raise ValueError('Both userPileupConfigs and userPileupConfigsPerCampaign specified, '
177  'use only one of the options!')
178  if self.userPileupConfigsPerCampaign is not None:
179  if not campaign:
180  raise Exception('userPileupConfigsPerCampaign requires campaign to be configured!')
181  if campaign is Campaign.Unknown:
182  raise Exception('userPileupConfigsPerCampaign used, but campaign = Unknown!')
183  try:
184  toolConfigFiles = self.userPileupConfigsPerCampaign[campaign.value][:]
185  log.info('Using user provided per-campaign PRW configuration')
186  except KeyError as e:
187  raise KeyError(f'Unconfigured campaign {e} for userPileupConfigsPerCampaign!')
188 
189  elif self.userPileupConfigs is not None:
190  toolConfigFiles = self.userPileupConfigs[:]
191  log.info('Using user provided PRW configuration')
192 
193  else:
194  from PileupReweighting.AutoconfigurePRW import getConfigurationFiles
195  if campaign and campaign is not Campaign.Unknown:
196  toolConfigFiles = getConfigurationFiles(campaign=campaign,
197  files=self.files,
198  useDefaultConfig=self.useDefaultConfig,
199  data_type=config.dataType())
200  if self.useDefaultConfig:
201  log.info('Auto-configuring universal/default PRW config')
202  else:
203  log.info('Auto-configuring per-sample PRW config files based on input files')
204  else:
205  log.info('No campaign specified, no PRW config files configured')
206 
207  # check if user provides per-campaign lumical config list
208  if self.userLumicalcFilesPerCampaign is not None and self.userLumicalcFiles is not None:
209  raise ValueError('Both userLumicalcFiles and userLumicalcFilesYear specified, '
210  'use only one of the options!')
211  if self.userLumicalcFilesPerCampaign is not None:
212  try:
213  toolLumicalcFiles = self.userLumicalcFilesPerCampaign[campaign.value][:]
214  log.info('Using user-provided per-campaign lumicalc files')
215  except KeyError as e:
216  raise KeyError(f'Unconfigured campaign {e} for userLumicalcFilesPerCampaign!')
217  elif self.userLumicalcFiles is not None:
218  toolLumicalcFiles = self.userLumicalcFiles[:]
219  log.info('Using user-provided lumicalc files')
220  else:
221  if campaign and campaign is not Campaign.Unknown:
222  from PileupReweighting.AutoconfigurePRW import getLumicalcFiles
223  toolLumicalcFiles = getLumicalcFiles(campaign)
224  log.info('Using auto-configured lumicalc files')
225  else:
226  log.info('No campaign specified, no lumicalc files configured for PRW')
227  else:
228  log.info('Data needs no lumicalc and PRW configuration files')
229 
230  # Set up the only algorithm of the sequence:
231  alg = config.createAlgorithm( 'CP::PileupReweightingAlg', 'PileupReweightingAlg' )
232  config.addPrivateTool( 'pileupReweightingTool', 'CP::PileupReweightingTool' )
233  alg.pileupReweightingTool.ConfigFiles = toolConfigFiles
234  if not toolConfigFiles and config.dataType() is not DataType.Data:
235  log.info("No PRW config files provided. Disabling reweighting")
236  # Setting the weight decoration to the empty string disables the reweighting
237  alg.pileupWeightDecoration = ""
238  alg.pileupReweightingTool.LumiCalcFiles = toolLumicalcFiles
239  config.addOutputVar ('EventInfo', 'runNumber', 'runNumber', noSys=True)
240  config.addOutputVar ('EventInfo', 'eventNumber', 'eventNumber', noSys=True)
241 
242  if config.dataType() is not DataType.Data:
243  config.addOutputVar ('EventInfo', 'mcChannelNumber', 'mcChannelNumber', noSys=True)
244  if toolConfigFiles:
245  config.addOutputVar ('EventInfo', 'PileupWeight_%SYS%', 'weight_pileup')
246  if config.geometry() is LHCPeriod.Run2:
247  config.addOutputVar ('EventInfo', 'beamSpotWeight', 'weight_beamspot', noSys=True)
248 
249 
250 class GeneratorAnalysisBlock (ConfigBlock):
251  """the ConfigBlock for generator algorithms"""
252 
253  def __init__ (self) :
254  super (GeneratorAnalysisBlock, self).__init__ ()
255  self.addOption ('saveCutBookkeepers', True, type=bool,
256  info="whether to save the cut bookkeepers information into the "
257  "output file. The default is True.")
258  self.addOption ('runNumber', None, type=int,
259  info="the MC runNumber (int). The default is None (autoconfigure "
260  "from metadata).")
261  self.addOption ('cutBookkeepersSystematics', None, type=bool,
262  info="whether to also save the cut bookkeepers systematics. The "
263  "default is None (follows the global systematics flag). Set to "
264  "False or True to override.")
265 
266  def makeAlgs (self, config) :
267 
268  if config.dataType() is DataType.Data:
269  # there are no generator weights in data!
270  return
271 
272  if self.runNumber is None:
273  self.runNumber = config.runNumber()
274 
275  if self.saveCutBookkeepers and not self.runNumber:
276  raise ValueError ("invalid run number: " + str(self.runNumber))
277 
278  # Set up the CutBookkeepers algorithm:
279  if self.saveCutBookkeepers:
280  alg = config.createAlgorithm('CP::AsgCutBookkeeperAlg', 'CutBookkeeperAlg')
281  alg.runNumber = self.runNumber
282  if self.cutBookkeepersSystematics:
283  alg.enableSystematics = self.cutBookkeepersSystematics
284  else:
285  alg.enableSystematics = not config.noSystematics()
286  config.addPrivateTool( 'truthWeightTool', 'PMGTools::PMGTruthWeightTool' )
287 
288  # Set up the weights algorithm:
289  alg = config.createAlgorithm( 'CP::PMGTruthWeightAlg', 'PMGTruthWeightAlg' )
290  config.addPrivateTool( 'truthWeightTool', 'PMGTools::PMGTruthWeightTool' )
291  alg.decoration = 'generatorWeight_%SYS%'
292  config.addOutputVar ('EventInfo', 'generatorWeight_%SYS%', 'weight_mc')
293 
294 
295 class PtEtaSelectionBlock (ConfigBlock):
296  """the ConfigBlock for a pt-eta selection"""
297 
298  def __init__ (self, containerName='', selectionName='') :
299  super (PtEtaSelectionBlock, self).__init__ ()
300  self.addOption ('containerName', containerName, type=str,
301  noneAction='error',
302  info="the name of the input container.")
303  self.addOption ('selectionName', selectionName, type=str,
304  noneAction='error',
305  info="the name of the selection to append this to. The default is "
306  "'' (empty string), meaning that the cuts are applied to every "
307  "object within the container. Specifying a name (e.g. loose) "
308  "applies the cut only to those object who also pass that selection.")
309  self.addOption ('postfix', '', type=str,
310  info="a postfix to apply to decorations and algorithm names. "
311  "Typically not needed here since we tend apply a single set of "
312  "pT and eta cuts to a given type of object.")
313  self.addOption ('minPt', None, type=float,
314  info="minimum pT value to cut on, in MeV. No default value.")
315  self.addOption ('maxEta', None, type=float,
316  info="maximum |eta| value to cut on. No default value.")
317  self.addOption ('selectionDecoration', 'selectPtEta', type=str,
318  info="the name of the decoration to set.")
319  self.addOption ('useClusterEta', False, type=bool,
320  info="whether to use the cluster eta (etaBE(2)) instead of the object "
321  "eta (for electrons and photons). The default is False.")
322 
323 
324  def makeAlgs (self, config) :
325 
326  postfix = self.postfix
327  if postfix != '' and postfix[0] != '_' :
328  postfix = '_' + postfix
329 
330  alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PtEtaSelectionAlg' + self.containerName + postfix )
331  config.addPrivateTool( 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
332  if self.minPt is not None :
333  alg.selectionTool.minPt = self.minPt
334  if self.maxEta is not None :
335  alg.selectionTool.maxEta = self.maxEta
336  alg.selectionTool.useClusterEta = self.useClusterEta
337  alg.selectionDecoration = self.selectionDecoration
338  alg.particles = config.readName (self.containerName)
339  alg.preselection = config.getPreselection (self.containerName, '')
340  config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration)
341 
342 
343 
344 class ObjectCutFlowBlock (ConfigBlock):
345  """the ConfigBlock for an object cutflow"""
346 
347  def __init__ (self, containerName='', selectionName='') :
348  super (ObjectCutFlowBlock, self).__init__ ()
349  self.addOption ('containerName', containerName, type=str,
350  noneAction='error',
351  info="the name of the input container.")
352  self.addOption ('selectionName', selectionName, type=str,
353  noneAction='error',
354  info="the name of the selection to perform the cutflow for. The "
355  "default is '' (empty string), meaning that the cutflow is "
356  "performed for every object within the container. Specifying a "
357  "name (e.g. loose) generates the cutflow only for those object "
358  "that also pass that selection.")
359  self.addOption ('postfix', '', type=str,
360  info="a postfix to apply to decorations and algorithm names. "
361  "Typically not needed here.")
362 
363  def makeAlgs (self, config) :
364 
365  postfix = self.postfix
366  if postfix != '' and postfix[0] != '_' :
367  postfix = '_' + postfix
368 
369  alg = config.createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'CutFlowDumperAlg_' + self.containerName + '_' + self.selectionName + postfix )
370  alg.histPattern = 'cflow_' + self.containerName + "_" + self.selectionName + postfix + '_%SYS%'
371  alg.selections = config.getSelectionCutFlow (self.containerName, self.selectionName)
372  alg.input = config.readName (self.containerName)
373  alg.histTitle = "Object Cutflow: " + self.containerName + "." + self.selectionName
374 
375 
376 class EventCutFlowBlock (ConfigBlock):
377  """the ConfigBlock for an event-level cutflow"""
378 
379  def __init__ (self, containerName='', selectionName='') :
380  super (EventCutFlowBlock, self).__init__ ()
381  self.addOption ('containerName', containerName, type=str,
382  noneAction='error',
383  info="the name of the input container, typically EventInfo.")
384  self.addOption ('selectionName', selectionName, type=str,
385  noneAction='error',
386  info="the name of an optional selection decoration to use.")
387  self.addOption ('customSelections', [], type=None,
388  info="the selections for which to generate cutflow histograms. If "
389  "a single string, corresponding to a particular event selection, "
390  "the event cutflow for that selection will be looked up. If a list "
391  "of strings, will use explicitly those selections. If left blank, "
392  "all selections attached to the container will be looked up.")
393  self.addOption ('postfix', '', type=str,
394  info="a postfix to apply in the naming of cutflow histograms. Set "
395  "it when defining multiple cutflows.")
396 
397  def makeAlgs (self, config) :
398 
399  postfix = self.postfix
400  if postfix != '' and postfix[0] != '_' :
401  postfix = '_' + postfix
402 
403  alg = config.createAlgorithm( 'CP::EventCutFlowHistAlg', 'CutFlowDumperAlg_' + self.containerName + '_' + self.selectionName + postfix )
404  alg.histPattern = 'cflow_' + self.containerName + "_" + self.selectionName + postfix + '_%SYS%'
405  # find out which selection decorations to use
406  if isinstance(self.customSelections, str):
407  # user provides a dynamic reference to selections, corresponding to an EventSelection alg
408  alg.selections = config.getEventCutFlow(self.customSelections)
409  elif len(self.customSelections) > 0:
410  # user provides a list of hardcoded selections
411  alg.selections = self.customSelections
412  else:
413  # user provides nothing: get all available selections from EventInfo directly
414  alg.selections = config.getSelectionCutFlow (self.containerName, self.selectionName)
415  alg.selections = [sel+',as_char' for sel in alg.selections]
416  if self.selectionName:
417  alg.preselection = self.selectionName + '_%SYS%'
418  alg.eventInfo = config.readName (self.containerName)
419  alg.histTitle = "Event Cutflow: " + self.containerName + "." + self.selectionName
420 
421 
422 class OutputThinningBlock (ConfigBlock):
423  """the ConfigBlock for output thinning"""
424 
425  def __init__ (self, containerName='', configName='') :
426  # configName is not used. To be removed.
427  super (OutputThinningBlock, self).__init__ ()
428  self.addOption ('containerName', containerName, type=str,
429  noneAction='error',
430  info="the name of the input container.")
431  self.addOption ('postfix', '', type=str,
432  info="a postfix to apply to decorations and algorithm names. "
433  "Typically not needed here.")
434  self.addOption ('selection', '', type=str,
435  info="the name of an optional selection decoration to use.")
436  self.addOption ('selectionName', '', type=str,
437  info="the name of the selection to append this to. The default is "
438  "'' (empty string), meaning that the cuts are applied to every "
439  "object within the container. Specifying a name (e.g. loose) "
440  "applies the cut only to those object who also pass that selection.")
441  self.addOption ('outputName', None, type=str,
442  info="an optional name for the output container.")
443  # TODO: add info string
444  self.addOption ('deepCopy', False, type=bool,
445  info="")
446  self.addOption ('sortPt', False, type=bool,
447  info="whether to sort objects in pt")
448  # TODO: add info string
449  self.addOption ('noUniformSelection', False, type=bool,
450  info="")
451 
452  def makeAlgs (self, config) :
453 
454  postfix = self.postfix
455  if postfix != '' and postfix[0] != '_' :
456  postfix = '_' + postfix
457 
458  selection = config.getFullSelection (self.containerName, self.selectionName)
459  if selection == '' :
460  selection = self.selection
461  elif self.selection != '' :
462  selection = selection + '&&' + self.selection
463 
464  if selection != '' and not self.noUniformSelection :
465  alg = config.createAlgorithm( 'CP::AsgUnionSelectionAlg', 'UnionSelectionAlg' + self.containerName + postfix)
466  alg.preselection = selection
467  alg.particles = config.readName (self.containerName)
468  alg.selectionDecoration = 'outputSelect' + postfix
469  selection = 'outputSelect' + postfix
470 
471  alg = config.createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'DeepCopyAlg' + self.containerName + postfix )
472  alg.input = config.readName (self.containerName)
473  if self.outputName is not None :
474  alg.output = self.outputName + '_%SYS%'
475  config.addOutputContainer (self.containerName, self.outputName)
476  else :
477  alg.output = config.copyName (self.containerName)
478  if selection != '' :
479  alg.selection = [selection]
480  else :
481  alg.selection = []
482  alg.deepCopy = self.deepCopy
483  if self.sortPt and not config.noSystematics() :
484  raise ValueError ("Sorting by pt is not supported with systematics")
485  alg.sortPt = self.sortPt
486 
487 
488 class IFFLeptonDecorationBlock (ConfigBlock):
489  """the ConfigBlock for the IFF classification of leptons"""
490 
491  def __init__ (self, containerName='') :
492  super (IFFLeptonDecorationBlock, self).__init__()
493  self.addOption ('containerName', containerName, type=str,
494  noneAction='error',
495  info="the name of the input electron or muon container.")
496  self.addOption ('separateChargeFlipElectrons', True, type=bool,
497  info="whether to consider charged-flip electrons as a separate class. "
498  "The default is True (recommended).")
499  self.addOption ('decoration', 'IFFClass_%SYS%', type=str,
500  info="the name (str) of the decoration set by the IFF "
501  "TruthClassificationTool. The default is 'IFFClass_%SYS%'.")
502 
503  def makeAlgs (self, config) :
504  # the classification is only for MC
505  if config.dataType() is DataType.Data: return
506 
507  particles = config.readName(self.containerName)
508 
509  alg = config.createAlgorithm( 'CP::AsgClassificationDecorationAlg', 'IFFClassifierAlg' + self.containerName )
510  # the IFF classification tool
511  config.addPrivateTool( 'tool', 'TruthClassificationTool')
512  # label charge-flipped electrons as such
513  alg.tool.separateChargeFlipElectrons = self.separateChargeFlipElectrons
514  alg.decoration = self.decoration
515  alg.particles = particles
516 
517  # write the decoration only once to the output
518  config.addOutputVar(self.containerName, alg.decoration, alg.decoration.split("_%SYS%")[0], noSys=True)
519 
520 
521 class PerEventSFBlock (ConfigBlock):
522  """the ConfigBlock for the AsgEventScaleFactorAlg"""
523 
524  def __init__ (self, algoName=''):
525  super(PerEventSFBlock, self).__init__()
526  self.addOption('algoName', algoName, type=str,
527  noneAction='error',
528  info="unique name given to the underlying algorithm computing the "
529  "per-event scale factors")
530  self.addOption('particles', '', type=str,
531  info="the input object container, with a possible selection, in the "
532  "format container or container.selection.")
533  self.addOption('objectSF', '', type=str,
534  info="the name of the per-object SF decoration to be used.")
535  self.addOption('eventSF', '', type=str,
536  info="the name of the per-event SF decoration.")
537 
538  def makeAlgs(self, config):
539  if config.dataType() is DataType.Data:
540  return
541  particles, selection = config.readNameAndSelection(self.particles)
542  alg = config.createAlgorithm('CP::AsgEventScaleFactorAlg', self.algoName)
543  alg.particles = particles
544  alg.preselection = selection
545  alg.scaleFactorInputDecoration = self.objectSF
546  alg.scaleFactorOutputDecoration = self.eventSF
547 
548  config.addOutputVar('EventInfo', alg.scaleFactorOutputDecoration,
549  alg.scaleFactorOutputDecoration.split("_%SYS%")[0])
550 
551 
552 class SelectionDecorationBlock (ConfigBlock):
553  """the ConfigBlock to add selection decoration to a container"""
554 
555  def __init__ (self, containers='') :
556  super (SelectionDecorationBlock, self).__init__ ()
557  # TODO: add info string
558  self.addOption('containers', containers, type=list,
559  noneAction='error',
560  info="")
561 
562  def makeAlgs(self, config):
563  for container in self.containers:
564  originContainerName = config.getOutputContainerOrigin(container)
565  selectionNames = config.getSelectionNames(originContainerName)
566  for selectionName in selectionNames:
567  # skip default selection
568  if selectionName == '':
569  continue
570  alg = config.createAlgorithm(
571  'CP::AsgSelectionAlg',
572  f'SelectionDecoration_{originContainerName}_{selectionName}')
573  selectionDecoration = f'baselineSelection_{selectionName}_%SYS%'
574  alg.selectionDecoration = f'{selectionDecoration},as_char'
575  alg.particles = config.readName (originContainerName)
576  alg.preselection = config.getFullSelection (originContainerName,
577  selectionName)
578  config.addOutputVar(
579  originContainerName, selectionDecoration, selectionName)
580 
581 
583  """Create the common services config"""
584 
585  seq.append (CommonServicesConfig ())
586 
587 
588 
589 def makePileupReweightingConfig( seq, campaign=None, files=None, useDefaultConfig=None, userLumicalcFiles=None, userPileupConfigs=None ):
590  """Create a PRW analysis config
591 
592  Keyword arguments:
593  """
594  # TO DO: add explanation of the keyword arguments, left to experts
595 
596  config = PileupReweightingBlock ()
597  config.setOptionValue ('campaign', campaign)
598  config.setOptionValue ('files', files)
599  config.setOptionValue ('useDefaultConfig', useDefaultConfig)
600  config.setOptionValue ('userLumicalcFiles', userLumicalcFiles)
601  config.setOptionValue ('userPileupConfigs', userPileupConfigs)
602  seq.append (config)
603 
604 
605 
607  saveCutBookkeepers=None,
608  runNumber=None,
609  cutBookkeepersSystematics=None ):
610  """Create a generator analysis algorithm sequence
611 
612  Keyword arguments:
613  saveCutBookkeepers -- save cut bokkeepers information into output file
614  runNumber -- MC run number
615  cutBookkeepersSystematics -- store CutBookkeepers systematics
616  """
617 
618  config = GeneratorAnalysisBlock ()
619  config.setOptionValue ('saveCutBookkeepers', saveCutBookkeepers)
620  config.setOptionValue ('runNumber', runNumber)
621  config.setOptionValue ('cutBookkeepersSystematics', cutBookkeepersSystematics)
622  seq.append (config)
623 
624 
625 
626 def makePtEtaSelectionConfig( seq, containerName,
627  *, postfix = None, minPt = None, maxEta = None,
628  useClusterEta = None,
629  selectionDecoration = None, selectionName = ''):
630  """Create a pt-eta kinematic selection config
631 
632  Keyword arguments:
633  containerName -- name of the container
634  postfix -- a postfix to apply to decorations and algorithm
635  names. this is mostly used/needed when using this
636  sequence with multiple working points to ensure all
637  names are unique.
638  minPt -- minimum pt value
639  maxEta -- maximum eta value
640  useClusterEta -- use cluster eta (for electrons/photons) instead of track eta
641  selectionDecoration -- the name of the decoration to set
642  selectionName -- the name of the selection to append this to
643  """
644 
645  config = PtEtaSelectionBlock (containerName, selectionName)
646  config.setOptionValue ('postfix',postfix)
647  config.setOptionValue ('minPt',minPt)
648  config.setOptionValue ('maxEta',maxEta)
649  config.setOptionValue ('selectionDecoration',selectionDecoration)
650  config.setOptionValue ('useClusterEta',useClusterEta)
651  seq.append (config)
652 
653 
654 
655 def makeObjectCutFlowConfig( seq, containerName,
656  *, postfix = None, selectionName):
657  """Create a pt-eta kinematic selection config
658 
659  Keyword arguments:
660  containerName -- name of the container
661  postfix -- a postfix to apply to decorations and algorithm
662  names. this is mostly used/needed when using this
663  sequence with multiple working points to ensure all
664  names are unique.
665  selectionName -- the name of the selection to do the cutflow for
666  """
667 
668  config = ObjectCutFlowBlock (containerName, selectionName)
669  config.setOptionValue ('postfix',postfix)
670  seq.append (config)
671 
672 
673 def makeEventCutFlowConfig( seq, containerName,
674  *, postfix = None, selectionName, customSelections = None):
675  """Create an event-level cutflow config
676 
677  Keyword arguments:
678  containerName -- name of the container
679  postfix -- a postfix to apply to decorations and algorithm names.
680  selectionName -- the name of the selection to do the cutflow for
681  customSelections -- a list of decorations to use in the cutflow, to override the retrieval of all decorations
682  """
683 
684  config = EventCutFlowBlock (containerName, selectionName)
685  config.setOptionValue ('postfix', postfix)
686  config.setOptionValue ('customSelections', customSelections)
687  seq.append (config)
688 
689 
690 def makeOutputThinningConfig( seq, containerName,
691  *, postfix = None, selection = None, selectionName = None, outputName = None, configName='Thinning'):
692  """Create an output thinning config
693 
694  This will do a consistent selection of output containers (if there
695  is a preselection or a selection specified) and then creates a set
696  of view containers (or deep copies) based on that selection.
697 
698  Keyword arguments:
699  containerName -- name of the container
700  postfix -- a postfix to apply to decorations and algorithm
701  names. this is mostly used/needed when using this
702  sequence with multiple working points to ensure all
703  names are unique.
704  selection -- the name of an optional selection decoration to use
705  outputName -- an optional name for the output container
706 
707  """
708 
709  config = OutputThinningBlock (containerName, configName)
710  config.setOptionValue ('postfix', postfix)
711  config.setOptionValue ('selection', selection)
712  config.setOptionValue ('selectionName', selectionName)
713  config.setOptionValue ('outputName', outputName)
714  seq.append (config)
python.AsgAnalysisConfig.GeneratorAnalysisBlock
Definition: AsgAnalysisConfig.py:250
python.AsgAnalysisConfig.PileupReweightingBlock
Definition: AsgAnalysisConfig.py:98
python.AsgAnalysisConfig.IOStatsBlock
Definition: AsgAnalysisConfig.py:85
python.AsgAnalysisConfig.PtEtaSelectionBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:324
python.AsgAnalysisConfig.ObjectCutFlowBlock.__init__
def __init__(self, containerName='', selectionName='')
Definition: AsgAnalysisConfig.py:347
python.AsgAnalysisConfig.makeEventCutFlowConfig
def makeEventCutFlowConfig(seq, containerName, *postfix=None, selectionName, customSelections=None)
Definition: AsgAnalysisConfig.py:673
python.AsgAnalysisConfig.SelectionDecorationBlock.__init__
def __init__(self, containers='')
Definition: AsgAnalysisConfig.py:555
python.AsgAnalysisConfig.ObjectCutFlowBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:363
python.AsgAnalysisConfig.SelectionDecorationBlock
Definition: AsgAnalysisConfig.py:552
python.AsgAnalysisConfig.EventCutFlowBlock
Definition: AsgAnalysisConfig.py:376
python.AsgAnalysisConfig.PerEventSFBlock
Definition: AsgAnalysisConfig.py:521
python.AsgAnalysisConfig.CommonServicesConfig.runSystematics
runSystematics
Definition: AsgAnalysisConfig.py:56
python.AsgAnalysisConfig.IFFLeptonDecorationBlock.__init__
def __init__(self, containerName='')
Definition: AsgAnalysisConfig.py:491
python.AsgAnalysisConfig.makePtEtaSelectionConfig
def makePtEtaSelectionConfig(seq, containerName, *postfix=None, minPt=None, maxEta=None, useClusterEta=None, selectionDecoration=None, selectionName='')
Definition: AsgAnalysisConfig.py:626
python.AsgAnalysisConfig.IOStatsBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:93
python.AsgAnalysisConfig.SystematicsCategories
Definition: AsgAnalysisConfig.py:9
python.AsgAnalysisConfig.EventCutFlowBlock.__init__
def __init__(self, containerName='', selectionName='')
Definition: AsgAnalysisConfig.py:379
python.AsgAnalysisConfig.OutputThinningBlock
Definition: AsgAnalysisConfig.py:422
python.AsgAnalysisConfig.makeOutputThinningConfig
def makeOutputThinningConfig(seq, containerName, *postfix=None, selection=None, selectionName=None, outputName=None, configName='Thinning')
Definition: AsgAnalysisConfig.py:690
python.AsgAnalysisConfig.GeneratorAnalysisBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:266
python.AsgAnalysisConfig.OutputThinningBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:452
python.AsgAnalysisConfig.PileupReweightingBlock.files
files
Definition: AsgAnalysisConfig.py:148
python.AsgAnalysisConfig.CommonServicesConfig.__init__
def __init__(self)
Definition: AsgAnalysisConfig.py:27
python.AutoconfigurePRW.getConfigurationFiles
def getConfigurationFiles(campaign=None, dsid=None, data_type=None, files=None, useDefaultConfig=False)
Definition: AutoconfigurePRW.py:116
python.AsgAnalysisConfig.PerEventSFBlock.__init__
def __init__(self, algoName='')
Definition: AsgAnalysisConfig.py:524
python.AsgAnalysisConfig.PerEventSFBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:538
python.AsgAnalysisConfig.PtEtaSelectionBlock.__init__
def __init__(self, containerName='', selectionName='')
Definition: AsgAnalysisConfig.py:298
python.AsgAnalysisConfig.makeGeneratorAnalysisConfig
def makeGeneratorAnalysisConfig(seq, saveCutBookkeepers=None, runNumber=None, cutBookkeepersSystematics=None)
Definition: AsgAnalysisConfig.py:606
python.AsgAnalysisConfig.GeneratorAnalysisBlock.__init__
def __init__(self)
Definition: AsgAnalysisConfig.py:253
python.AsgAnalysisConfig.PileupReweightingBlock.__init__
def __init__(self)
Definition: AsgAnalysisConfig.py:101
python.AsgAnalysisConfig.ObjectCutFlowBlock
Definition: AsgAnalysisConfig.py:344
python.AsgAnalysisConfig.OutputThinningBlock.__init__
def __init__(self, containerName='', configName='')
Definition: AsgAnalysisConfig.py:425
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.AsgAnalysisConfig.makeObjectCutFlowConfig
def makeObjectCutFlowConfig(seq, containerName, *postfix=None, selectionName)
Definition: AsgAnalysisConfig.py:655
python.AsgAnalysisConfig.makeCommonServicesConfig
def makeCommonServicesConfig(seq)
Definition: AsgAnalysisConfig.py:582
python.AsgAnalysisConfig.makePileupReweightingConfig
def makePileupReweightingConfig(seq, campaign=None, files=None, useDefaultConfig=None, userLumicalcFiles=None, userPileupConfigs=None)
Definition: AsgAnalysisConfig.py:589
python.AsgAnalysisConfig.CommonServicesConfig
Definition: AsgAnalysisConfig.py:19
python.AsgAnalysisConfig.IOStatsBlock.__init__
def __init__(self)
Definition: AsgAnalysisConfig.py:88
python.AsgAnalysisConfig.CommonServicesConfig.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:46
python.AsgAnalysisConfig.EventCutFlowBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:397
python.AsgAnalysisConfig.IFFLeptonDecorationBlock
Definition: AsgAnalysisConfig.py:488
python.AsgAnalysisConfig.IFFLeptonDecorationBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:503
str
Definition: BTagTrackIpAccessor.cxx:11
python.AsgAnalysisConfig.GeneratorAnalysisBlock.runNumber
runNumber
Definition: AsgAnalysisConfig.py:273
python.AutoconfigurePRW.getLumicalcFiles
def getLumicalcFiles(campaign)
Definition: AutoconfigurePRW.py:6
python.AsgAnalysisConfig.PileupReweightingBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:124
python.AsgAnalysisConfig.SelectionDecorationBlock.makeAlgs
def makeAlgs(self, config)
Definition: AsgAnalysisConfig.py:562
python.Utils.getMCCampaign
def getMCCampaign(files)
Definition: Tools/Campaigns/python/Utils.py:27
python.AsgAnalysisConfig.PtEtaSelectionBlock
Definition: AsgAnalysisConfig.py:295