diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml index b540243fa0ac8710e1a7cb522fccd670e158a138..ca760e13c85faa1a57a0550710ecbab83da2a9b9 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml @@ -130,6 +130,14 @@ Trigger: photons: 'AnaPhotons' muons: 'AnaMuons' +SelectionDecoration: + containers: + - 'OutMuons' + - 'OutElectrons' + - 'OutPhotons' + - 'OutTauJets' + - 'OutJets' + # After configuring each container, many variables will be saved automatically. Output: treeName: 'analysis' diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml index 4b70df0c497fdfd928839caae8b5507bb2a3bd9c..eb37e6564a802871c65a26c86a3d99568a8f78c5 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml @@ -102,6 +102,14 @@ Thinning: outputName: 'OutTauJets' selectionName: 'tight' +SelectionDecoration: + containers: + - 'OutMuons' + - 'OutElectrons' + - 'OutPhotons' + - 'OutTauJets' + - 'OutJets' + # After configuring each container, many variables will be saved automatically. Output: treeName: 'analysis' diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py index b8e0c841342832fa16328bf20fe5fc744fbad47f..be096ae78ac2d39f87c9a27bc97594c5717b42c7 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py @@ -314,6 +314,11 @@ class ConfigFactory(): self.addAlgConfigBlock(algName="Thinning", alg=OutputThinningBlock, defaults={'configName': 'Thinning'}) + # selection decorations + from AsgAnalysisAlgorithms.AsgAnalysisConfig import SelectionDecorationBlock + self.addAlgConfigBlock(algName='SelectionDecoration', + alg=SelectionDecorationBlock) + # output from AsgAnalysisAlgorithms.OutputAnalysisConfig import OutputAnalysisConfig self.addAlgConfigBlock(algName="Output", alg=OutputAnalysisConfig, diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py index 44d222cf537d3c0e94c1e767879d057db44d7cef..d04bf3d04b627e21181a073da7ec15c7fa57fc35 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py @@ -987,6 +987,9 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, configSeq.setOptionValue ('.nReplicas', 2000 ) configSeq.setOptionValue ('.runOnMC', True ) + configSeq += config.makeConfig ('SelectionDecoration', containers = [ + 'OutMuons', 'OutElectrons', 'OutPhotons', 'OutTauJets', 'OutJets']) + configSeq += config.makeConfig ('Output') configSeq.setOptionValue ('.treeName', 'analysis') configSeq.setOptionValue ('.vars', vars) diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisConfig.py b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisConfig.py index 4850238dfd75e7f6006bb469bba408b49575578d..a51e07ad47ea96a6a1428fa0ee6db46ad2c72a83 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisConfig.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration # AnaAlgorithm import(s): from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock @@ -415,6 +415,35 @@ class PerEventSFBlock (ConfigBlock): alg.scaleFactorOutputDecoration.split("_%SYS%")[0]) +class SelectionDecorationBlock (ConfigBlock): + """the ConfigBlock to add selection decoration to a container""" + + def __init__ (self, containers) : + super (SelectionDecorationBlock, self).__init__ () + self.containers = containers + self.addOption ('selectionFlagPrefix', 'select', type=str) + + def makeAlgs(self, config): + for container in self.containers: + originContainerName = config.getOutputContainerOrigin(container) + selectionNames = config.getSelectionNames(originContainerName) + for selectionName in selectionNames: + # skip default selection + if selectionName == '': + continue + alg = config.createAlgorithm( + 'CP::AsgSelectionAlg', + f'SelectionDecoration_{originContainerName}_{selectionName}') + selectionDecoration = f'baselineSelection_{selectionName}_%SYS%' + alg.selectionDecoration = f'{selectionDecoration},as_char' + alg.particles = config.readName (originContainerName) + alg.preselection = config.getFullSelection (originContainerName, + selectionName) + config.addOutputVar( + originContainerName, selectionDecoration, + self.selectionFlagPrefix + '_' + selectionName) + + def makeCommonServicesConfig( seq ): """Create the common services config""" diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py index e8d38b9e582d7a870b97474ce5a0b1ac5482908f..880499c3e15e50444c00806df4cf160db1b9affe 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration # AnaAlgorithm import(s): from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock @@ -18,8 +18,6 @@ class OutputAnalysisConfig (ConfigBlock): self.addOption ('containersOnlyForMC', [], type=None) self.addOption ('treeName', 'analysis', type=str) self.addOption ('metTermName', 'Final', type=str) - self.addOption ('storeSelectionFlags', True, type=bool) - self.addOption ('selectionFlagPrefix', 'select', type=str) self.addOption ('commands', [], type=None, info="a list of commands for branch selection/configuration") @@ -33,9 +31,6 @@ class OutputAnalysisConfig (ConfigBlock): self.vars |= self.varsOnlyForMC self.containers.update(self.containersOnlyForMC) - if self.storeSelectionFlags: - self.createSelectionFlagBranches(config) - outputConfigs = {} for prefix in self.containers.keys() : containerName = self.containers[prefix] @@ -116,39 +111,3 @@ class OutputAnalysisConfig (ConfigBlock): treeFiller = config.createAlgorithm( 'CP::TreeFillerAlg', 'TreeFiller' + postfix ) treeFiller.TreeName = self.treeName - - - def createSelectionFlagBranches(self, config): - """ - For each container and for each selection, create a single pass variable in output NTuple, - which aggregates all the selections flag of the given selection. For example, this can include - pT, eta selections, some object ID selection, overlap removal, etc. - The goal is to have only one flag per object and working point in the output NTuple. - """ - for prefix in self.containers.keys() : - outputContainerName = self.containers[prefix] - containerName = config.getOutputContainerOrigin(outputContainerName) - - # EventInfo is one obvious example of a container that has no object selections - if containerName == 'EventInfo': - continue - - selectionNames = config.getSelectionNames(containerName) - for selectionName in selectionNames: - # skip default selection - if selectionName == '': - continue - self.makeSelectionSummaryAlg(config, containerName, selectionName) - - def makeSelectionSummaryAlg(self, config, containerName, selectionName): - """ - Schedule an algorithm to pick up all cut flags for a given selectionName. - The summary selection flag is written to output as selectionFlagPrefix_selectionName. - """ - alg = config.createAlgorithm( 'CP::AsgSelectionAlg', - f'ObjectSelectionSummary_{containerName}_{selectionName}') - selectionDecoration = f'baselineSelection_{selectionName}_%SYS%' - alg.selectionDecoration = f'{selectionDecoration},as_char' - alg.particles = config.readName (containerName) - alg.preselection = config.getFullSelection (containerName, selectionName) - config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix + '_' + selectionName)