From 8109a406879932f1cbf9484821fe002b3b3b7fad Mon Sep 17 00:00:00 2001 From: Nils Krumnack <nils.erik.krumnack@cern.ch> Date: Wed, 7 Feb 2024 08:11:24 -0600 Subject: [PATCH] introduce a mechanism to exclude specific cuts from subsequent use The main usage here is that if OR is run before MET we don't want to use the OR selections with MET. A similar issue is expected to come up with fakes/fakeable objects, i.e. some specific baseline cuts should not be applied (in fact they are inverted), but only for very specific users. The mechanism chosen here is to mark the cuts when they are registered and then exclude by name when requesting the selection. --- .../python/ConfigAccumulator.py | 24 ++++++++++++------- .../python/OverlapAnalysisConfig.py | 24 +++++++++---------- .../python/MetAnalysisConfig.py | 8 +++---- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py index fac5deb24953..f8ef2213acb7 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py @@ -29,13 +29,14 @@ class SelectionConfig : removed in the future.""" def __init__ (self, selectionName, decoration, - *, bits=0, preselection=None) : + *, bits=0, preselection=None, comesFrom = '') : self.name = selectionName self.decoration = decoration if preselection is not None : self.preselection = preselection else : self.preselection = (selectionName == '') + self.comesFrom = comesFrom @@ -388,7 +389,7 @@ class ConfigAccumulator : return self._containerConfig[containerName].isMet - def readNameAndSelection (self, containerName) : + def readNameAndSelection (self, containerName, *, excludeFrom = None) : """get the name of the "current copy" of the given container, and the selection string @@ -405,7 +406,7 @@ class ConfigAccumulator : selectionName = split[1] else : raise Exception ('invalid object selection name: ' + containerName) - return self.readName (objectName), self.getFullSelection (objectName, selectionName) + return self.readName (objectName), self.getFullSelection (objectName, selectionName, excludeFrom=excludeFrom) def nextPass (self) : @@ -445,7 +446,7 @@ class ConfigAccumulator : def getFullSelection (self, containerName, selectionName, - *, skipBase = False) : + *, skipBase = False, excludeFrom = None) : """get the selection string for the given selection on the given container @@ -460,10 +461,16 @@ class ConfigAccumulator : expression based on multiple named selections skipBase --- will avoid the base selection, and should normally not be used by the end-user. - + excludeFrom --- a set of string names of selection sources to exclude + e.g. to exclude OR selections from MET """ if containerName not in self._containerConfig : return "" + + if excludeFrom is None : + excludeFrom = {} + elif not isinstance(excludeFrom, set) : + raise ValueError ('invalid excludeFrom argument (need set of strings): ' + str(excludeFrom)) # Check if this is actually a selection expression, # e.g. `A||B` and if so translate it into a complex expression @@ -480,13 +487,13 @@ class ConfigAccumulator : selectionName = selectionName[1:] else : subname = match.group(0) - subresult = self.getFullSelection (containerName, subname, skipBase = True) + subresult = self.getFullSelection (containerName, subname, skipBase = True, excludeFrom=excludeFrom) if subresult != '' : result += '(' + subresult + ')' else : result += 'true' selectionName = selectionName[len(subname):] - subresult = self.getFullSelection (containerName, '') + subresult = self.getFullSelection (containerName, '', excludeFrom=excludeFrom) if subresult != '' : result = subresult + '&&(' + result + ')' return result @@ -494,8 +501,7 @@ class ConfigAccumulator : config = self._containerConfig[containerName] decorations = [] for selection in config.selections : - if ((selection.name == '' and not skipBase) or - selection.name == selectionName) : + if ((selection.name == '' and not skipBase) or selection.name == selectionName) and (selection.comesFrom not in excludeFrom) : decorations += [selection.decoration] return '&&'.join (decorations) diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OverlapAnalysisConfig.py b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OverlapAnalysisConfig.py index 80c4f9e3ae6c..8a3b5d14a0c2 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OverlapAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/OverlapAnalysisConfig.py @@ -152,27 +152,27 @@ class OverlapAnalysisConfig (ConfigBlock): if electrons : alg.electrons = electrons alg.electronsDecoration = self.outputLabel + '_%SYS%,as_char' - config.addSelection (self.electrons.split('.')[0], electronsSelectionName, alg.electronsDecoration, preselection=False) + config.addSelection (self.electrons.split('.')[0], electronsSelectionName, alg.electronsDecoration, preselection=False, comesFrom='or') if muons : alg.muons = muons alg.muonsDecoration = self.outputLabel + '_%SYS%,as_char' - config.addSelection (self.muons.split('.')[0], muonsSelectionName, alg.muonsDecoration, preselection=False) + config.addSelection (self.muons.split('.')[0], muonsSelectionName, alg.muonsDecoration, preselection=False, comesFrom='or') if taus : alg.taus = taus alg.tausDecoration = self.outputLabel + '_%SYS%,as_char' - config.addSelection (self.taus.split('.')[0], tausSelectionName, alg.tausDecoration, preselection=False) + config.addSelection (self.taus.split('.')[0], tausSelectionName, alg.tausDecoration, preselection=False, comesFrom='or') if jets : alg.jets = jets alg.jetsDecoration = self.outputLabel + '_%SYS%,as_char' - config.addSelection (self.jets.split('.')[0], jetsSelectionName, alg.jetsDecoration, preselection=False) + config.addSelection (self.jets.split('.')[0], jetsSelectionName, alg.jetsDecoration, preselection=False, comesFrom='or') if photons : alg.photons = photons alg.photonsDecoration = self.outputLabel + '_%SYS%,as_char' - config.addSelection (self.photons.split('.')[0], photonsSelectionName, alg.photonsDecoration, preselection=False) + config.addSelection (self.photons.split('.')[0], photonsSelectionName, alg.photonsDecoration, preselection=False, comesFrom='or') if fatJets : alg.fatJets = fatJets alg.fatJetsDecoration = self.outputLabel + '_%SYS%,as_char' - config.addSelection (self.fatJets.split('.')[0], fatJetsSelectionName, alg.fatJetsDecoration, preselection=False) + config.addSelection (self.fatJets.split('.')[0], fatJetsSelectionName, alg.fatJetsDecoration, preselection=False, comesFrom='or') # Create its main tool, and set its basic properties: config.addPrivateTool( 'overlapTool', 'ORUtils::OverlapRemovalTool' ) @@ -354,42 +354,42 @@ class OverlapAnalysisConfig (ConfigBlock): alg.preselection = '&&'.join (config.getPreselection (self.electrons.split('.')[0], electronsSelectionName, asList=True) + [self.outputLabel + '_%SYS%,as_char']) alg.selectionDecoration = preselectLabel - config.addSelection (self.electrons.split('.')[0], electronsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True) + config.addSelection (self.electrons.split('.')[0], electronsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True, comesFrom='or') if muons : alg = config.createAlgorithm( 'CP::AsgUnionPreselectionAlg','ORMuonsPreselectionAlg' + postfix ) alg.particles = muons alg.preselection = '&&'.join (config.getPreselection (self.muons.split('.')[0], muonsSelectionName, asList=True) + [self.outputLabel + '_%SYS%,as_char']) alg.selectionDecoration = preselectLabel - config.addSelection (self.muons.split('.')[0], muonsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True) + config.addSelection (self.muons.split('.')[0], muonsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True, comesFrom='or') if taus : alg = config.createAlgorithm( 'CP::AsgUnionPreselectionAlg','ORTausPreselectionAlg' + postfix ) alg.particles = taus alg.preselection = '&&'.join (config.getPreselection (self.taus.split('.')[0], tausSelectionName, asList=True) + [self.outputLabel + '_%SYS%,as_char']) alg.selectionDecoration = preselectLabel - config.addSelection (self.taus.split('.')[0], tausSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True) + config.addSelection (self.taus.split('.')[0], tausSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True, comesFrom='or') if jets : alg = config.createAlgorithm( 'CP::AsgUnionPreselectionAlg','ORJetsPreselectionAlg' + postfix ) alg.particles = jets alg.preselection = '&&'.join (config.getPreselection (self.jets.split('.')[0], jetsSelectionName, asList=True) + [self.outputLabel + '_%SYS%,as_char']) alg.selectionDecoration = preselectLabel - config.addSelection (self.jets.split('.')[0], jetsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True) + config.addSelection (self.jets.split('.')[0], jetsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True, comesFrom='or') if photons : alg = config.createAlgorithm( 'CP::AsgUnionPreselectionAlg','ORPhotonsPreselectionAlg' + postfix ) alg.particles = photons alg.preselection = '&&'.join (config.getPreselection (self.photons.split('.')[0], photonsSelectionName, asList=True) + [self.outputLabel + '_%SYS%,as_char']) alg.selectionDecoration = preselectLabel - config.addSelection (self.photons.split('.')[0], photonsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True) + config.addSelection (self.photons.split('.')[0], photonsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True, comesFrom='or') if fatJets : alg = config.createAlgorithm( 'CP::AsgUnionPreselectionAlg','ORFatJetsPreselectionAlg' + postfix ) alg.particles = fatJets alg.preselection = '&&'.join (config.getPreselection (self.fatJets.split('.')[0], fatJetsSelectionName, asList=True) + [self.outputLabel + '_%SYS%,as_char']) alg.selectionDecoration = preselectLabel - config.addSelection (self.fatJets.split('.')[0], fatJetsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True) + config.addSelection (self.fatJets.split('.')[0], fatJetsSelectionName, alg.selectionDecoration+',as_char', bits=1, preselection=True, comesFrom='or') diff --git a/PhysicsAnalysis/Algorithms/MetAnalysisAlgorithms/python/MetAnalysisConfig.py b/PhysicsAnalysis/Algorithms/MetAnalysisAlgorithms/python/MetAnalysisConfig.py index 897ea8a2c2a0..9f677322e874 100644 --- a/PhysicsAnalysis/Algorithms/MetAnalysisAlgorithms/python/MetAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/MetAnalysisAlgorithms/python/MetAnalysisConfig.py @@ -57,13 +57,13 @@ class MetAnalysisConfig (ConfigBlock): alg.metAssociation = 'METAssoc_' + metSuffix alg.jets = config.readName (self.jets) if self.muons != "" : - alg.muons, alg.muonsSelection = config.readNameAndSelection (self.muons) + alg.muons, alg.muonsSelection = config.readNameAndSelection (self.muons, excludeFrom={'or'}) if self.electrons != "" : - alg.electrons, alg.electronsSelection = config.readNameAndSelection (self.electrons) + alg.electrons, alg.electronsSelection = config.readNameAndSelection (self.electrons, excludeFrom={'or'}) if self.photons != "" : - alg.photons, alg.photonsSelection = config.readNameAndSelection (self.photons) + alg.photons, alg.photonsSelection = config.readNameAndSelection (self.photons, excludeFrom={'or'}) if self.taus != "" : - alg.taus, alg.tausSelection = config.readNameAndSelection (self.taus) + alg.taus, alg.tausSelection = config.readNameAndSelection (self.taus, excludeFrom={'or'}) if self.invisible != "" : alg.invisible = config.readName (self.invisible) alg.met = config.writeName (self.containerName, isMet = True) -- GitLab