diff --git a/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisConfig.py b/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisConfig.py index b7c7d3c58b83f98fb56a395a247ac8a992176606..d88564d4721ec266b2cdaa9eb0ed07ee021f8c2a 100644 --- a/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisConfig.py +++ b/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisConfig.py @@ -19,6 +19,12 @@ class TriggerAnalysisBlock (ConfigBlock): "to enforce an OR of triggers without looking up the individual " "triggers. Used for both trigger selection and SFs. " "The default is {} (empty dictionary).") + self.addOption ('multiTriggerChainsPerYear', {}, type=None, + info="a dictionary with key (string) a trigger set name and value a " + "triggerChainsPerYear dictionary, following the previous convention. " + "Relevant for analyses using different triggers in different categories, " + "where the trigger global scale factors shouldn't be combined. " + "The default is {} (empty dictionary).") self.addOption ('triggerChainsForSelection', [], type=None, info="a list of trigger chains (list of strings) to be used for " "trigger selection. Only set it if you need a different setup " @@ -77,16 +83,25 @@ class TriggerAnalysisBlock (ConfigBlock): def makeAlgs (self, config) : + + if (self.multiTriggerChainsPerYear and self.triggerChainsPerYear and + self.triggerChainsPerYear is not self.multiTriggerChainsPerYear.get('')): + raise Exception('multiTriggerChainsPerYear and triggerChainsPerYear cannot be configured at the same time!') + + if self.triggerChainsPerYear and not self.multiTriggerChainsPerYear: + self.multiTriggerChainsPerYear = {'': self.triggerChainsPerYear} + # if we are only given the trigger dictionary, we fill the selection list automatically if self.triggerChainsPerYear and not self.triggerChainsForSelection: triggers = set() - for chain_list in self.triggerChainsPerYear.values(): - for chain in chain_list: - if '||' in chain: - chains = chain.split('||') - triggers.update(map(str.strip, chains)) - else: - triggers.add(chain.strip()) + for trigger_chains in self.multiTriggerChainsPerYear.values(): + for chain_list in self.triggerChainsPerYear.values(): + for chain in chain_list: + if '||' in chain: + chains = chain.split('||') + triggers.update(map(str.strip, chains)) + else: + triggers.add(chain.strip()) self.triggerChainsForSelection = list(triggers) # Create the decision algorithm, keeping track of the decision tool for later diff --git a/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisSFConfig.py b/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisSFConfig.py index a8871392ca850b171481effcc7a165e1f23c17b9..4cae0c54c70761a8d97ff2bf4f667cdfb9d5664f 100644 --- a/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisSFConfig.py +++ b/PhysicsAnalysis/Algorithms/TriggerAnalysisAlgorithms/python/TriggerAnalysisSFConfig.py @@ -23,6 +23,12 @@ class TriggerAnalysisSFBlock (ConfigBlock): "to enforce an OR of triggers without looking up the individual " "triggers. Used for both trigger selection and SFs. " "The default is {} (empty dictionary).") + self.addOption ('multiTriggerChainsPerYear', {}, type=None, + info="a dictionary with key (string) a trigger set name and value a " + "triggerChainsPerYear dictionary, following the previous convention. " + "Relevant for analyses using different triggers in different categories, " + "where the trigger global scale factors shouldn't be combined. " + "The default is {} (empty dictionary).") self.addOption ('noFilter', False, type=bool, info="do not apply an event filter. The default is False, i.e. " "remove events not passing trigger selection and matching.") @@ -88,7 +94,8 @@ class TriggerAnalysisSFBlock (ConfigBlock): return matchingTool - def makeTriggerGlobalEffCorrAlg(self, config, matchingTool, noSF): + def makeTriggerGlobalEffCorrAlg(self, config, matchingTool, noSF, + triggerSuffix=''): alg = config.createAlgorithm( 'CP::TrigGlobalEfficiencyAlg', 'TrigGlobalSFAlg' ) if config.geometry() == LHCPeriod.Run3: @@ -119,9 +126,9 @@ class TriggerAnalysisSFBlock (ConfigBlock): alg.matchingTool = '%s/%s' % ( matchingTool.getType(), matchingTool.getName() ) alg.isRun3Geo = config.geometry() == LHCPeriod.Run3 - alg.scaleFactorDecoration = 'globalTriggerEffSF_%SYS%' - alg.matchingDecoration = 'globalTriggerMatch_%SYS%' - alg.eventDecisionOutputDecoration = 'globalTriggerMatch_dontsave_%SYS%' + alg.scaleFactorDecoration = 'globalTriggerEffSF'+triggerSuffix+'_%SYS%' + alg.matchingDecoration = 'globalTriggerMatch'+triggerSuffix+'_%SYS%' + alg.eventDecisionOutputDecoration = 'globalTriggerMatch'+triggerSuffix+'_dontsave_%SYS%' alg.doMatchingOnly = config.dataType() is DataType.Data or noSF alg.noFilter = self.noFilter alg.electronID = self.electronID @@ -138,8 +145,8 @@ class TriggerAnalysisSFBlock (ConfigBlock): raise ValueError ('TriggerAnalysisConfig: at least one object collection must be provided! (electrons, muons, photons)' ) if config.dataType() != DataType.Data and not alg.doMatchingOnly: - config.addOutputVar ('EventInfo', alg.scaleFactorDecoration, 'globalTriggerEffSF') - config.addOutputVar ('EventInfo', alg.matchingDecoration, 'globalTriggerMatch', noSys=True) + config.addOutputVar ('EventInfo', alg.scaleFactorDecoration, 'globalTriggerEffSF'+triggerSuffix) + config.addOutputVar ('EventInfo', alg.matchingDecoration, 'globalTriggerMatch'+triggerSuffix, noSys=False) return @@ -152,7 +159,9 @@ class TriggerAnalysisSFBlock (ConfigBlock): matchingTool = self.makeTriggerMatchingTool(config, decisionTool) # Calculate multi-lepton (electron/muon/photon) trigger efficiencies and SFs - if self.triggerChainsPerYear and not self.noGlobalTriggerEff: - self.makeTriggerGlobalEffCorrAlg(config, matchingTool, self.noEffSF) + if self.multiTriggerChainsPerYear and not self.noGlobalTriggerEff: + for suffix, trigger_chains in self.multiTriggerChainsPerYear: + self.triggerChainsPerYear = trigger_chains + self.makeTriggerGlobalEffCorrAlg(config, matchingTool, self.noEffSF, suffix) return