diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml index ca760e13c85faa1a57a0550710ecbab83da2a9b9..b540243fa0ac8710e1a7cb522fccd670e158a138 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/example_config.yaml @@ -130,14 +130,6 @@ 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 eb37e6564a802871c65a26c86a3d99568a8f78c5..4b70df0c497fdfd928839caae8b5507bb2a3bd9c 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml @@ -102,14 +102,6 @@ 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 be096ae78ac2d39f87c9a27bc97594c5717b42c7..b8e0c841342832fa16328bf20fe5fc744fbad47f 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigFactory.py @@ -314,11 +314,6 @@ 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 d04bf3d04b627e21181a073da7ec15c7fa57fc35..44d222cf537d3c0e94c1e767879d057db44d7cef 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py @@ -987,9 +987,6 @@ 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 a51e07ad47ea96a6a1428fa0ee6db46ad2c72a83..4850238dfd75e7f6006bb469bba408b49575578d 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisConfig.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration # AnaAlgorithm import(s): from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock @@ -415,35 +415,6 @@ 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 880499c3e15e50444c00806df4cf160db1b9affe..e8d38b9e582d7a870b97474ce5a0b1ac5482908f 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OutputAnalysisConfig.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration # AnaAlgorithm import(s): from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock @@ -18,6 +18,8 @@ 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") @@ -31,6 +33,9 @@ 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] @@ -111,3 +116,39 @@ 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)