4 from AnalysisAlgorithmsConfig.ConfigBlock
import ConfigBlock
5 from AthenaConfiguration.Enums
import LHCPeriod
6 from AnalysisAlgorithmsConfig.ConfigAccumulator
import DataType
12 ELECTRONS = [
'EG_',
'EL_']
14 PHOTONS = [
'EG_',
'PH_']
17 EVENT = [
'GEN_',
'PRW_']
21 """the ConfigBlock for common services
23 The idea here is that all algorithms need some common services, and I should
24 provide configuration blocks for those. For now there is just a single
25 block, but in the future I might break out e.g. the systematics service.
29 super (CommonServicesConfig, self).__init__ ()
30 self.addOption (
'runSystematics',
None, type=bool,
31 info=
"whether to turn on the computation of systematic variations. "
32 "The default is to run them on MC.")
33 self.addOption (
'filterSystematics',
None, type=str,
34 info=
"a regexp string against which the systematics names will be "
35 "matched. Only positive matches are retained and used in the evaluation "
36 "of the various algorithms.")
37 self.addOption (
'onlySystematicsCategories',
None, type=list,
38 info=
"a list of strings defining categories of systematics to enable "
39 "(only recommended for studies / partial ntuple productions). Choose amongst: "
40 "jets, electrons, muons, photons, taus, met, ftag, event. This option is overridden "
41 "by 'filterSystematics'.")
42 self.addOption (
'systematicsHistogram',
None , type=str,
43 info=
"the name (string) of the histogram to which a list of executed "
44 "systematics will be printed. The default is None (don't write out "
49 sysService = config.createService(
'CP::SystematicsSvc',
'SystematicsSvc' )
53 elif config.noSystematics()
is not None :
62 sysService.sigmaRecommended = 1
63 if config.dataType()
is DataType.Data:
68 requested_categories = []
71 category_enum = SystematicsCategories[category_str.upper()]
72 requested_categories += category_enum.value
74 raise ValueError(f
"Invalid systematics category passed to option 'onlySystematicsCategories': {category_str}. Must be one of {', '.join(category.name for category in SystematicsCategories)}")
76 if len(requested_categories):
77 sysService.systematicsRegex =
"^(?=.*(" +
"|".
join(requested_categories) +
")|$).*"
78 if self.filterSystematics
is not None:
79 sysService.systematicsRegex = self.filterSystematics
80 config.createService(
'CP::SelectionNameSvc',
'SelectionNameSvc')
82 if self.systematicsHistogram
is not None:
83 sysDumper = config.createAlgorithm(
'CP::SysListDumperAlg',
'SystematicsPrinter' )
84 sysDumper.histogramName = self.systematicsHistogram
88 """Print what branches are used in analysis"""
92 self.addOption(
"printOption",
"Summary", type=str,
93 info=
'option to pass the standard ROOT printing function. Can be "Summary", "ByEntries" or "ByBytes".')
96 alg = config.createAlgorithm(
'CP::IOStatsAlg',
'IOStatsAlg')
97 alg.printOption = self.printOption
101 """the ConfigBlock for pileup reweighting"""
104 super (PileupReweightingBlock, self).__init__ ()
105 self.addOption (
'campaign',
None, type=
None,
106 info=
"the MC campaign for the PRW auto-configuration.")
107 self.addOption (
'files',
None, type=
None,
108 info=
"the input files being processed (list of strings). "
109 "Alternative to auto-configuration.")
110 self.addOption (
'useDefaultConfig',
True, type=bool,
111 info=
"whether to use the central PRW files. The default is True.")
112 self.addOption (
'userLumicalcFiles',
None, type=
None,
113 info=
"user-provided lumicalc files (list of strings). Alternative "
114 "to auto-configuration.")
115 self.addOption (
'userLumicalcFilesPerCampaign',
None, type=
None,
116 info=
"user-provided lumicalc files (dictionary of list of strings, "
117 "with MC campaigns as the keys). Alternative to auto-configuration.")
118 self.addOption (
'userPileupConfigs',
None, type=
None,
119 info=
"user-provided PRW files (list of strings). Alternative to "
120 "auto-configuration. Alternative to auto-configuration.")
121 self.addOption (
'userPileupConfigsPerCampaign',
None, type=
None,
122 info=
"user-provided PRW files (dictionary of list of strings, with "
123 "MC campaigns as the keys)")
124 self.addOption (
'postfix',
'', type=str,
125 info=
"a postfix to apply to decorations and algorithm names. "
126 "Typically not needed unless several instances of PileupReweighting are scheduled.")
127 self.addOption (
'alternativeConfig',
False, type=bool,
128 info=
"whether this is used as an additional alternative config for PileupReweighting. "
129 "Will only store the alternative pile up weight in that case.")
134 from Campaigns.Utils
import Campaign
137 from AthenaCommon.Logging
import logging
140 log = logging.getLogger(
'makePileupAnalysisSequence')
142 eventInfoVar = [
'runNumber',
'eventNumber',
'actualInteractionsPerCrossing',
'averageInteractionsPerCrossing']
143 if config.dataType()
is not DataType.Data:
144 eventInfoVar += [
'mcChannelNumber']
146 if config.isPhyslite()
and not self.alternativeConfig:
148 log.info(f
'Physlite does not need pileup reweighting. Variables will be copied from input instead. {config.isPhyslite}')
149 for var
in eventInfoVar:
150 config.addOutputVar (
'EventInfo', var, var, noSys=
True)
152 if config.dataType()
is not DataType.Data:
153 config.addOutputVar (
'EventInfo',
'PileupWeight_%SYS%',
'weight_pileup')
154 if config.geometry()
is LHCPeriod.Run2:
155 config.addOutputVar (
'EventInfo',
'beamSpotWeight',
'weight_beamspot', noSys=
True)
159 if self.
files is None and config.autoconfigFlags()
is not None:
160 self.
files = config.autoconfigFlags().Input.Files
162 campaign = self.campaign
165 if config.dataType()
is not DataType.Data
and self.campaign
is None:
167 if config.campaign()
is not None and config.campaign()
is not Campaign.Unknown:
168 campaign = config.campaign()
169 log.info(f
'Auto-configuring campaign for PRW from flags: {campaign.value}')
172 if self.
files is not None:
173 from Campaigns.Utils
import getMCCampaign
175 if campaign
and campaign
is not Campaign.Unknown:
176 log.info(f
'Auto-configuring campaign for PRW from files: {campaign.value}')
178 log.info(
'Campaign could not be determined.')
182 toolLumicalcFiles = []
186 if (config.dataType()
is not DataType.Data
and
187 config.geometry()
is not LHCPeriod.Run4):
189 if self.userPileupConfigs
is not None and self.userPileupConfigsPerCampaign
is not None:
190 raise ValueError(
'Both userPileupConfigs and userPileupConfigsPerCampaign specified, '
191 'use only one of the options!')
192 if self.userPileupConfigsPerCampaign
is not None:
194 raise Exception(
'userPileupConfigsPerCampaign requires campaign to be configured!')
195 if campaign
is Campaign.Unknown:
196 raise Exception(
'userPileupConfigsPerCampaign used, but campaign = Unknown!')
198 toolConfigFiles = self.userPileupConfigsPerCampaign[campaign.value][:]
199 log.info(
'Using user provided per-campaign PRW configuration')
200 except KeyError
as e:
201 raise KeyError(f
'Unconfigured campaign {e} for userPileupConfigsPerCampaign!')
203 elif self.userPileupConfigs
is not None:
204 toolConfigFiles = self.userPileupConfigs[:]
205 log.info(
'Using user provided PRW configuration')
208 if self.useDefaultConfig
and self.
files is None:
209 raise ValueError(
'useDefaultConfig requires files to be configured! '
210 'Either pass them as an option or use flags.')
212 from PileupReweighting.AutoconfigurePRW
import getConfigurationFiles
213 if campaign
and campaign
is not Campaign.Unknown:
216 useDefaultConfig=self.useDefaultConfig,
217 data_type=config.dataType())
218 if self.useDefaultConfig:
219 log.info(
'Auto-configuring universal/default PRW config')
221 log.info(
'Auto-configuring per-sample PRW config files based on input files')
223 log.info(
'No campaign specified, no PRW config files configured')
226 if self.userLumicalcFilesPerCampaign
is not None and self.userLumicalcFiles
is not None:
227 raise ValueError(
'Both userLumicalcFiles and userLumicalcFilesYear specified, '
228 'use only one of the options!')
229 if self.userLumicalcFilesPerCampaign
is not None:
231 toolLumicalcFiles = self.userLumicalcFilesPerCampaign[campaign.value][:]
232 log.info(
'Using user-provided per-campaign lumicalc files')
233 except KeyError
as e:
234 raise KeyError(f
'Unconfigured campaign {e} for userLumicalcFilesPerCampaign!')
235 elif self.userLumicalcFiles
is not None:
236 toolLumicalcFiles = self.userLumicalcFiles[:]
237 log.info(
'Using user-provided lumicalc files')
239 if campaign
and campaign
is not Campaign.Unknown:
240 from PileupReweighting.AutoconfigurePRW
import getLumicalcFiles
242 log.info(
'Using auto-configured lumicalc files')
244 log.info(
'No campaign specified, no lumicalc files configured for PRW')
246 log.info(
'Data needs no lumicalc and PRW configuration files')
249 if config.geometry()
is LHCPeriod.Run4:
250 log.warning (
'Pileup reweighting is not yet supported for Run 4 geometry')
251 alg = config.createAlgorithm(
'CP::EventDecoratorAlg',
'EventDecoratorAlg'+self.postfix )
252 alg.uint32Decorations = {
'RandomRunNumber' :
253 config.autoconfigFlags().Input.RunNumbers[0] }
256 alg = config.createAlgorithm(
'CP::PileupReweightingAlg',
257 'PileupReweightingAlg'+self.postfix )
258 config.addPrivateTool(
'pileupReweightingTool',
'CP::PileupReweightingTool' )
259 alg.pileupReweightingTool.ConfigFiles = toolConfigFiles
260 if not toolConfigFiles
and config.dataType()
is not DataType.Data:
261 log.info(
"No PRW config files provided. Disabling reweighting")
263 alg.pileupWeightDecoration =
""
265 alg.pileupWeightDecoration =
"PileupWeight" + self.postfix +
"_%SYS%"
266 alg.pileupReweightingTool.LumiCalcFiles = toolLumicalcFiles
268 if not self.alternativeConfig:
269 for var
in eventInfoVar:
270 config.addOutputVar (
'EventInfo', var, var, noSys=
True)
272 if config.dataType()
is not DataType.Data
and config.geometry()
is LHCPeriod.Run2:
273 config.addOutputVar (
'EventInfo',
'beamSpotWeight',
'weight_beamspot', noSys=
True)
275 if config.dataType()
is not DataType.Data
and toolConfigFiles:
276 config.addOutputVar (
'EventInfo',
'PileupWeight' + self.postfix +
'_%SYS%',
277 'weight_pileup'+self.postfix)
281 """the ConfigBlock for generator algorithms"""
284 super (GeneratorAnalysisBlock, self).__init__ ()
285 self.addOption (
'saveCutBookkeepers',
True, type=bool,
286 info=
"whether to save the cut bookkeepers information into the "
287 "output file. The default is True.")
288 self.addOption (
'runNumber',
None, type=int,
289 info=
"the MC runNumber (int). The default is None (autoconfigure "
291 self.addOption (
'cutBookkeepersSystematics',
None, type=bool,
292 info=
"whether to also save the cut bookkeepers systematics. The "
293 "default is None (follows the global systematics flag). Set to "
294 "False or True to override.")
295 self.addOption (
'histPattern',
None, type=str,
296 info=
"the histogram name pattern for the cut-bookkeeper histogram names")
297 self.addOption (
'streamName',
'ANALYSIS', type=str,
298 info=
"name of the output stream to save the cut bookkeeper in. "
299 "The default is ANALYSIS.")
303 if config.dataType()
is DataType.Data:
310 if self.saveCutBookkeepers
and not self.
runNumber:
311 raise ValueError (
"invalid run number: " +
str(self.
runNumber))
314 if self.saveCutBookkeepers:
315 alg = config.createAlgorithm(
'CP::AsgCutBookkeeperAlg',
'CutBookkeeperAlg' + self.streamName)
316 alg.RootStreamName = self.streamName
318 if self.cutBookkeepersSystematics:
319 alg.enableSystematics = self.cutBookkeepersSystematics
321 alg.enableSystematics =
not config.noSystematics()
323 alg.histPattern = self.histPattern
324 config.addPrivateTool(
'truthWeightTool',
'PMGTools::PMGTruthWeightTool' )
327 alg = config.createAlgorithm(
'CP::PMGTruthWeightAlg',
'PMGTruthWeightAlg' + self.streamName )
328 config.addPrivateTool(
'truthWeightTool',
'PMGTools::PMGTruthWeightTool' )
329 alg.decoration =
'generatorWeight_%SYS%'
330 config.addOutputVar (
'EventInfo',
'generatorWeight_%SYS%',
'weight_mc')
334 """the ConfigBlock for a pt-eta selection"""
336 def __init__ (self, containerName='', selectionName='') :
337 super (PtEtaSelectionBlock, self).__init__ ()
338 self.addOption (
'containerName', containerName, type=str,
340 info=
"the name of the input container.")
341 self.addOption (
'selectionName', selectionName, type=str,
343 info=
"the name of the selection to append this to. The default is "
344 "'' (empty string), meaning that the cuts are applied to every "
345 "object within the container. Specifying a name (e.g. loose) "
346 "applies the cut only to those object who also pass that selection.")
347 self.addOption (
'minPt',
None, type=float,
348 info=
"minimum pT value to cut on, in MeV. No default value.")
349 self.addOption (
'maxPt',
None, type=float,
350 info=
"maximum pT value to cut on, in MeV. No default value.")
351 self.addOption (
'minEta',
None, type=float,
352 info=
"minimum |eta| value to cut on. No default value.")
353 self.addOption (
'maxEta',
None, type=float,
354 info=
"maximum |eta| value to cut on. No default value.")
355 self.addOption (
'etaGapLow',
None, type=float,
356 info=
"low end of the |eta| gap. No default value.")
357 self.addOption (
'etaGapHigh',
None, type=float,
358 info=
"high end of the |eta| gap. No default value.")
359 self.addOption (
'selectionDecoration',
None, type=str,
360 info=
"the name of the decoration to set. If 'None', will be set "
361 "to 'selectPtEta' followed by the selection name.")
362 self.addOption (
'useClusterEta',
False, type=bool,
363 info=
"whether to use the cluster eta (etaBE(2)) instead of the object "
364 "eta (for electrons and photons). The default is False.")
365 self.addOption (
'useDressedProperties',
False, type=bool,
366 info=
"whether to use the dressed kinematic properties "
367 "(for truth particles only). The default is False.")
372 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'PtEtaSelectionAlg' + self.containerName + self.selectionName )
373 config.addPrivateTool(
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
374 if self.minPt
is not None :
375 alg.selectionTool.minPt = self.minPt
376 if self.maxPt
is not None:
377 alg.selectionTool.maxPt = self.maxPt
378 if self.minEta
is not None:
379 alg.selectionTool.minEta = self.minEta
380 if self.maxEta
is not None :
381 alg.selectionTool.maxEta = self.maxEta
382 if self.etaGapLow
is not None:
383 alg.selectionTool.etaGapLow = self.etaGapLow
384 if self.etaGapHigh
is not None:
385 alg.selectionTool.etaGapHigh = self.etaGapHigh
388 alg.selectionTool.useClusterEta = self.useClusterEta
389 alg.selectionTool.useDressedProperties = self.useDressedProperties
391 alg.particles = config.readName (self.containerName)
392 alg.preselection = config.getPreselection (self.containerName,
'')
393 config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration)
398 """the ConfigBlock for an object cutflow"""
400 def __init__ (self, containerName='', selectionName='') :
401 super (ObjectCutFlowBlock, self).__init__ ()
402 self.addOption (
'containerName', containerName, type=str,
404 info=
"the name of the input container.")
405 self.addOption (
'selectionName', selectionName, type=str,
407 info=
"the name of the selection to perform the cutflow for. The "
408 "default is '' (empty string), meaning that the cutflow is "
409 "performed for every object within the container. Specifying a "
410 "name (e.g. loose) generates the cutflow only for those object "
411 "that also pass that selection.")
415 alg = config.createAlgorithm(
'CP::ObjectCutFlowHistAlg',
'CutFlowDumperAlg_' + self.containerName +
'_' + self.selectionName )
416 alg.histPattern =
'cflow_' + self.containerName +
"_" + self.selectionName +
'_%SYS%'
417 alg.selections = config.getSelectionCutFlow (self.containerName, self.selectionName)
418 alg.input = config.readName (self.containerName)
419 alg.histTitle =
"Object Cutflow: " + self.containerName +
"." + self.selectionName
423 """the ConfigBlock for an event-level cutflow"""
425 def __init__ (self, containerName='', selectionName='') :
426 super (EventCutFlowBlock, self).__init__ ()
427 self.addOption (
'containerName', containerName, type=str,
429 info=
"the name of the input container, typically EventInfo.")
430 self.addOption (
'selectionName', selectionName, type=str,
432 info=
"the name of an optional selection decoration to use.")
433 self.addOption (
'customSelections', [], type=
None,
434 info=
"the selections for which to generate cutflow histograms. If "
435 "a single string, corresponding to a particular event selection, "
436 "the event cutflow for that selection will be looked up. If a list "
437 "of strings, will use explicitly those selections. If left blank, "
438 "all selections attached to the container will be looked up.")
439 self.addOption (
'postfix',
'', type=str,
440 info=
"a postfix to apply in the naming of cutflow histograms. Set "
441 "it when defining multiple cutflows.")
445 postfix = self.postfix
446 if postfix !=
'' and postfix[0] !=
'_' :
447 postfix =
'_' + postfix
449 alg = config.createAlgorithm(
'CP::EventCutFlowHistAlg',
'CutFlowDumperAlg_' + self.containerName +
'_' + self.selectionName + postfix )
450 alg.histPattern =
'cflow_' + self.containerName +
"_" + self.selectionName + postfix +
'_%SYS%'
452 if isinstance(self.customSelections, str):
454 alg.selections = config.getEventCutFlow(self.customSelections)
455 elif len(self.customSelections) > 0:
457 alg.selections = self.customSelections
460 alg.selections = config.getSelectionCutFlow (self.containerName, self.selectionName)
461 alg.selections = [sel+
',as_char' for sel
in alg.selections]
462 if self.selectionName:
463 alg.preselection = self.selectionName +
'_%SYS%'
464 alg.eventInfo = config.readName (self.containerName)
465 alg.histTitle =
"Event Cutflow: " + self.containerName +
"." + self.selectionName
469 """the ConfigBlock for output thinning"""
471 def __init__ (self, containerName='', configName='') :
473 super (OutputThinningBlock, self).__init__ ()
474 self.addOption (
'containerName', containerName, type=str,
476 info=
"the name of the input container.")
477 self.addOption (
'postfix',
'', type=str,
478 info=
"a postfix to apply to decorations and algorithm names. "
479 "Typically not needed here.")
480 self.addOption (
'selection',
'', type=str,
481 info=
"the name of an optional selection decoration to use.")
482 self.addOption (
'selectionName',
'', type=str,
483 info=
"the name of the selection to append this to. The default is "
484 "'' (empty string), meaning that the cuts are applied to every "
485 "object within the container. Specifying a name (e.g. loose) "
486 "applies the cut only to those object who also pass that selection.")
487 self.addOption (
'outputName',
None, type=str,
488 info=
"an optional name for the output container.")
490 self.addOption (
'deepCopy',
False, type=bool,
492 self.addOption (
'sortPt',
False, type=bool,
493 info=
"whether to sort objects in pt")
495 self.addOption (
'noUniformSelection',
False, type=bool,
500 postfix = self.postfix
501 if postfix !=
'' and postfix[0] !=
'_' :
502 postfix =
'_' + postfix
504 selection = config.getFullSelection (self.containerName, self.selectionName)
506 selection = self.selection
507 elif self.selection !=
'' :
508 selection = selection +
'&&' + self.selection
510 if selection !=
'' and not self.noUniformSelection :
511 alg = config.createAlgorithm(
'CP::AsgUnionSelectionAlg',
'UnionSelectionAlg' + self.containerName + postfix)
512 alg.preselection = selection
513 alg.particles = config.readName (self.containerName)
514 alg.selectionDecoration =
'outputSelect' + postfix
515 selection =
'outputSelect' + postfix
517 alg = config.createAlgorithm(
'CP::AsgViewFromSelectionAlg',
'DeepCopyAlg' + self.containerName + postfix )
518 alg.input = config.readName (self.containerName)
519 if self.outputName
is not None :
520 alg.output = self.outputName +
'_%SYS%'
521 config.addOutputContainer (self.containerName, self.outputName)
523 alg.output = config.copyName (self.containerName)
525 alg.selection = [selection]
528 alg.deepCopy = self.deepCopy
529 if self.sortPt
and not config.noSystematics() :
530 raise ValueError (
"Sorting by pt is not supported with systematics")
531 alg.sortPt = self.sortPt
535 """the ConfigBlock for the IFF classification of leptons"""
538 super (IFFLeptonDecorationBlock, self).
__init__()
539 self.addOption (
'containerName', containerName, type=str,
541 info=
"the name of the input electron or muon container.")
542 self.addOption (
'separateChargeFlipElectrons',
True, type=bool,
543 info=
"whether to consider charged-flip electrons as a separate class. "
544 "The default is True (recommended).")
545 self.addOption (
'decoration',
'IFFClass_%SYS%', type=str,
546 info=
"the name (str) of the decoration set by the IFF "
547 "TruthClassificationTool. The default is 'IFFClass_%SYS%'.")
549 self.setOptionValue(
'skipOnData',
True)
552 particles = config.readName(self.containerName)
554 alg = config.createAlgorithm(
'CP::AsgClassificationDecorationAlg',
'IFFClassifierAlg' + self.containerName )
556 config.addPrivateTool(
'tool',
'TruthClassificationTool')
558 alg.tool.separateChargeFlipElectrons = self.separateChargeFlipElectrons
559 alg.decoration = self.decoration
560 alg.particles = particles
563 config.addOutputVar(self.containerName, alg.decoration, alg.decoration.split(
"_%SYS%")[0], noSys=
True)
569 super (MCTCLeptonDecorationBlock, self).__init__ ()
571 self.addOption (
"containerName", containerName, type=str,
573 info=
"the input lepton container, with a possible selection, "
574 "in the format container or container.selection.")
575 self.addOption (
"prefix",
'MCTC_', type=str,
576 info=
"the prefix (str) of the decorations based on the MCTC "
577 "classification. The default is 'MCTC_'.")
579 self.setOptionValue(
'skipOnData',
True)
582 particles, selection = config.readNameAndSelection(self.containerName)
584 alg = config.createAlgorithm (
"CP::MCTCDecorationAlg", f
"MCTCDecorationAlg{self.containerName}")
585 alg.particles = particles
586 alg.preselection = selection
587 alg.affectingSystematicsFilter =
'.*'
588 config.addOutputVar (self.containerName,
"MCTC_isPrompt", f
"{self.prefix}isPrompt", noSys=
True)
589 config.addOutputVar (self.containerName,
"MCTC_fromHadron", f
"{self.prefix}fromHadron", noSys=
True)
590 config.addOutputVar (self.containerName,
"MCTC_fromBSM", f
"{self.prefix}fromBSM", noSys=
True)
591 config.addOutputVar (self.containerName,
"MCTC_fromTau", f
"{self.prefix}fromTau", noSys=
True)
595 """the ConfigBlock for the AsgEventScaleFactorAlg"""
598 super(PerEventSFBlock, self).
__init__()
599 self.addOption(
'algoName', algoName, type=str,
601 info=
"unique name given to the underlying algorithm computing the "
602 "per-event scale factors")
603 self.addOption(
'particles',
'', type=str,
604 info=
"the input object container, with a possible selection, in the "
605 "format container or container.selection.")
606 self.addOption(
'objectSF',
'', type=str,
607 info=
"the name of the per-object SF decoration to be used.")
608 self.addOption(
'eventSF',
'', type=str,
609 info=
"the name of the per-event SF decoration.")
612 if config.dataType()
is DataType.Data:
614 particles, selection = config.readNameAndSelection(self.particles)
615 alg = config.createAlgorithm(
'CP::AsgEventScaleFactorAlg', self.algoName)
616 alg.particles = particles
617 alg.preselection = selection
618 alg.scaleFactorInputDecoration = self.objectSF
619 alg.scaleFactorOutputDecoration = self.eventSF
621 config.addOutputVar(
'EventInfo', alg.scaleFactorOutputDecoration,
622 alg.scaleFactorOutputDecoration.split(
"_%SYS%")[0])
626 """the ConfigBlock to add selection decoration to a container"""
629 super (SelectionDecorationBlock, self).__init__ ()
631 self.addOption(
'containers', containers, type=list,
636 for container
in self.containers:
637 originContainerName = config.getOutputContainerOrigin(container)
638 selectionNames = config.getSelectionNames(originContainerName)
639 for selectionName
in selectionNames:
641 if selectionName ==
'':
643 alg = config.createAlgorithm(
644 'CP::AsgSelectionAlg',
645 f
'SelectionDecoration_{originContainerName}_{selectionName}')
646 selectionDecoration = f
'baselineSelection_{selectionName}_%SYS%'
647 alg.selectionDecoration = f
'{selectionDecoration},as_char'
648 alg.particles = config.readName (originContainerName)
649 alg.preselection = config.getFullSelection (originContainerName,
652 originContainerName, selectionDecoration, selectionName)
656 """Create the common services config"""
658 seq.append (CommonServicesConfig ())
663 """Create a PRW analysis config
669 config = PileupReweightingBlock ()
670 config.setOptionValue (
'campaign', campaign)
671 config.setOptionValue (
'files', files)
672 config.setOptionValue (
'useDefaultConfig', useDefaultConfig)
673 config.setOptionValue (
'userLumicalcFiles', userLumicalcFiles)
674 config.setOptionValue (
'userPileupConfigs', userPileupConfigs)
680 saveCutBookkeepers=None,
682 cutBookkeepersSystematics=None ):
683 """Create a generator analysis algorithm sequence
686 saveCutBookkeepers -- save cut bokkeepers information into output file
687 runNumber -- MC run number
688 cutBookkeepersSystematics -- store CutBookkeepers systematics
691 config = GeneratorAnalysisBlock ()
692 config.setOptionValue (
'saveCutBookkeepers', saveCutBookkeepers)
693 config.setOptionValue (
'runNumber', runNumber)
694 config.setOptionValue (
'cutBookkeepersSystematics', cutBookkeepersSystematics)
700 *, postfix = None, selectionName, customSelections = None):
701 """Create an event-level cutflow config
704 containerName -- name of the container
705 postfix -- a postfix to apply to decorations and algorithm names.
706 selectionName -- the name of the selection to do the cutflow for
707 customSelections -- a list of decorations to use in the cutflow, to override the retrieval of all decorations
710 config = EventCutFlowBlock (containerName, selectionName)
711 config.setOptionValue (
'postfix', postfix)
712 config.setOptionValue (
'customSelections', customSelections)
717 *, postfix = None, selection = None, selectionName = None, outputName = None, configName='Thinning'):
718 """Create an output thinning config
720 This will do a consistent selection of output containers (if there
721 is a preselection or a selection specified) and then creates a set
722 of view containers (or deep copies) based on that selection.
725 containerName -- name of the container
726 postfix -- a postfix to apply to decorations and algorithm
727 names. this is mostly used/needed when using this
728 sequence with multiple working points to ensure all
730 selection -- the name of an optional selection decoration to use
731 outputName -- an optional name for the output container
735 config = OutputThinningBlock (containerName, configName)
736 config.setOptionValue (
'postfix', postfix)
737 config.setOptionValue (
'selection', selection)
738 config.setOptionValue (
'selectionName', selectionName)
739 config.setOptionValue (
'outputName', outputName)