diff --git a/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py b/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py index 6e34250a3e89ed5599489c709bd967165a84feb7..bdd92c37f4c7dc19afce87d42b944abc934f91d7 100644 --- a/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py @@ -80,6 +80,9 @@ def makeMuonAnalysisSequence( dataType, workingPoint, # Create the analysis algorithm sequence object: seq = AnaAlgSequence( "MuonAnalysisSequence" + postfix ) + seq.addMetaConfigDefault ("selectionDecorNames", []) + seq.addMetaConfigDefault ("selectionDecorCount", []) + # Set up the eta-cut on all muons prior to everything else alg = createAlgorithm( 'CP::AsgSelectionAlg', 'MuonEtaCutAlg' + postfix ) @@ -89,9 +92,9 @@ def makeMuonAnalysisSequence( dataType, workingPoint, seq.append( alg, inputPropName = 'particles', outputPropName = 'particlesOut', stageName = 'selection', - selectionDecorNames = [alg.selectionDecoration], - selectionDecorCount = [2], - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [2]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Set up the track selection algorithm: alg = createAlgorithm( 'CP::AsgLeptonTrackSelectionAlg', @@ -101,9 +104,9 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg.maxDeltaZ0SinTheta = 0.5 seq.append( alg, inputPropName = 'particles', stageName = 'selection', - selectionDecorNames = [alg.selectionDecoration], - selectionDecorCount = [3], - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [3]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Set up the muon calibration and smearing algorithm: alg = createAlgorithm( 'CP::MuonCalibrationAndSmearingAlg', @@ -113,7 +116,7 @@ def makeMuonAnalysisSequence( dataType, workingPoint, seq.append( alg, inputPropName = 'muons', outputPropName = 'muonsOut', affectingSystematics = '(^MUON_ID$)|(^MUON_MS$)|(^MUON_SAGITTA_.*)|(^MUON_SCALE$)', stageName = 'calibration', - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Set up the the pt selection ptSelectionDecoration = 'selectPt' + postfix + ',as_bits' @@ -123,9 +126,9 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg.selectionTool.minPt = 3e3 seq.append( alg, inputPropName = 'particles', stageName = 'selection', - selectionDecorNames = [alg.selectionDecoration], - selectionDecorCount = [2], - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [2]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Setup the muon quality selection qualitySelectionDecoration = 'good_muon' + postfix + ',as_bits' @@ -138,9 +141,9 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg.badMuonVetoDecoration = badMuonVetoDecoration seq.append( alg, inputPropName = 'muons', stageName = 'selection', - selectionDecorNames = [alg.selectionDecoration], - selectionDecorCount = [4], - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [4]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Set up the isolation calculation algorithm: if splitWP[1] != 'NonIso' : @@ -150,16 +153,16 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg.isolationDecoration = 'isolated_muon' + postfix + ',as_bits' seq.append( alg, inputPropName = 'muons', outputPropName = 'muonsOut', stageName = 'selection', - selectionDecorNames = [alg.isolationDecoration], - selectionDecorCount = [1], - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + metaConfig = {'selectionDecorNames' : [alg.isolationDecoration], + 'selectionDecorCount' : [1]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) pass # Set up an algorithm used for decorating baseline muon selection: alg = createAlgorithm( 'CP::AsgSelectionAlg', 'MuonSelectionSummary' + postfix ) addPrivateTool( alg, 'selectionTool', 'CP::AsgFlagSelectionTool' ) - alg.selectionTool.selectionFlags = seq.selectionDecorNames() + alg.selectionTool.selectionFlags = seq.getMetaConfig ("selectionDecorNames") alg.selectionDecoration = 'baselineSelection' + postfix + ',as_char' seq.append( alg, inputPropName = 'particles', stageName = 'selection' ) @@ -169,12 +172,12 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'MuonCutFlowDumperAlg' + postfix ) alg.histPattern = 'muon' + postfix + '_cflow_%SYS%' seq.append( alg, inputPropName = 'input', stageName = 'selection', - dynConfig = {'selection' : lambda seq, index : seq.selectionDecorNames (index), - 'selectionNCuts' : lambda seq, index : seq.selectionDecorCount (index)} ) + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"]} ) # Set up the output selection if shallowViewOutput or deepCopyOutput: - selectionDecorNamesOutput = seq.selectionDecorNames() + selectionDecorNamesOutput = seq.getMetaConfig ("selectionDecorNames") if not ptSelectionOutput: selectionDecorNamesOutput.remove(ptSelectionDecoration) if not qualitySelectionOutput: @@ -185,7 +188,7 @@ def makeMuonAnalysisSequence( dataType, workingPoint, if shallowViewOutput: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'MuonViewFromSelectionAlg' + postfix ) - alg.selection = seq.selectionDecorNamesOutput() + alg.selection = selectionDecorNamesOutput seq.append( alg, inputPropName = 'input', outputPropName = 'output', stageName = 'selection' ) @@ -203,14 +206,14 @@ def makeMuonAnalysisSequence( dataType, workingPoint, seq.append( alg, inputPropName = 'muons', affectingSystematics = '(^MUON_EFF_RECO.*)', stageName = 'efficiency', - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Set up an algorithm dumping the kinematic properties of the muons: if enableKinematicHistograms: alg = createAlgorithm( 'CP::KinematicHistAlg', 'MuonKinematicDumperAlg' + postfix ) alg.histPattern = 'muon' + postfix + '_%VAR%_%SYS%' seq.append( alg, inputPropName = 'input', stageName = 'selection', - dynConfig = {'preselection' : lambda seq, index : "&&".join (seq.selectionDecorNames (index))}) + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])}) # Set up a final deep copy making algorithm if requested: if deepCopyOutput: diff --git a/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py b/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py index 35e6ae74813bf593f01868bb8f6d5a1781c80b02..7706b92ef212363a864db879882aca2552349d45 100644 --- a/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py +++ b/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py @@ -37,6 +37,7 @@ class AnaAlgSequence( AlgSequence ): # Set up the sequence's member variables: self._algorithmMeta = [] self._outputAffectingSystematics = None + self._metaConfigDefault = {} return @@ -99,12 +100,19 @@ class AnaAlgSequence( AlgSequence ): 'inconsistent state' ) # do the dynamic configuration based on meta-information - index = 0 + metaConfig = {} + for name, value in self._metaConfigDefault.items() : + metaConfig[name] = value[:] + pass for alg, meta in zip( self, self._algorithmMeta ): for var, func in meta.dynConfig.items() : - setattr (alg, var, func (self, index)) + setattr (alg, var, func (metaConfig)) + pass + for name, value in meta.metaConfig.items() : + if not name in metaConfig : + raise RuntimeError ("metaConfig value " + name + " for algorithm " + alg.name() + " not registered, did you forget to call addMetaConfigDefault?") + metaConfig[name] += value[:] pass - index += 1 pass # Make the inputs and outputs dictionaries. Allowing simple sequences to @@ -260,7 +268,7 @@ class AnaAlgSequence( AlgSequence ): def append( self, alg, inputPropName, outputPropName = None, affectingSystematics = None, stageName = 'undefined', - selectionDecorNames = [], selectionDecorCount = [], + metaConfig = {}, dynConfig = {}): """Add one analysis algorithm to the sequence @@ -280,14 +288,14 @@ class AnaAlgSequence( AlgSequence ): stageName -- name of the current processing stage [optional] """ - meta = AnaAlgorithmMeta( stageName=stageName, affectingSystematics=affectingSystematics, inputPropName=inputPropName, outputPropName=outputPropName, selectionDecorNames=selectionDecorNames, selectionDecorCount=selectionDecorCount, dynConfig=dynConfig ) + meta = AnaAlgorithmMeta( stageName=stageName, affectingSystematics=affectingSystematics, inputPropName=inputPropName, outputPropName=outputPropName, metaConfig=metaConfig, dynConfig=dynConfig ) self += alg self._algorithmMeta.append( meta ) return self def insert( self, index, alg, inputPropName, outputPropName = None, affectingSystematics = None, stageName = 'undefined', - selectionDecorNames = [], selectionDecorCount = [], + metaConfig = {}, dynConfig = {} ): """Insert one analysis algorithm into the sequence @@ -309,7 +317,7 @@ class AnaAlgSequence( AlgSequence ): stageName -- name of the current processing stage [optional] """ - meta = AnaAlgorithmMeta( stageName=stageName, affectingSystematics=affectingSystematics, inputPropName=inputPropName, outputPropName=outputPropName, selectionDecorNames=selectionDecorNames, selectionDecorCount=selectionDecorCount, dynConfig=dynConfig ) + meta = AnaAlgorithmMeta( stageName=stageName, affectingSystematics=affectingSystematics, inputPropName=inputPropName, outputPropName=outputPropName, metaConfig=metaConfig, dynConfig=dynConfig ) super( AnaAlgSequence, self ).insert( index, alg ) self._algorithmMeta.insert( index, meta ) return self @@ -406,20 +414,40 @@ class AnaAlgSequence( AlgSequence ): pass pass - def selectionDecorNames (self, index = None) : - result = [] - for meta in self._algorithmMeta [ 0 : index ] : - result += meta.selectionDecorNames + + + def addMetaConfigDefault (self, name, value) : + """add a default value for the given meta-configuration entry + + This will both register name as a valid meta-configuration + value and set its default value, or add to its default value, + if that name is already known.""" + + if name in self._metaConfigDefault : + self._metaConfigDefault[name] += value pass - return result + else : + self._metaConfigDefault[name] = value + pass + pass + + - def selectionDecorCount (self, index = None) : - result = [] - for meta in self._algorithmMeta [ 0 : index ] : - result += meta.selectionDecorCount + def getMetaConfig (self, name) : + """get the value for the given meta-configuration entry""" + + if not name in self._metaConfigDefault : + raise RuntimeError ("metaConfig value " + name + " not registered, did you forget to call addMetaConfigDefault?") + result = self._metaConfigDefault[name][:] + for meta in self._algorithmMeta : + if name in meta.metaConfig : + result += meta.metaConfig[name] + pass pass return result + + @staticmethod def allowedStageNames(): return AnaAlgorithmMeta.allowedStageNames () diff --git a/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgorithmMeta.py b/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgorithmMeta.py index 5e069b79a4946e6cb1e6657b418ed17a43d04cb1..f10d0a33cd9a8f55de44071d4d8ec0460fe399cc 100644 --- a/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgorithmMeta.py +++ b/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgorithmMeta.py @@ -13,17 +13,14 @@ class AnaAlgorithmMeta ( object ): a separate algorithm. """ - def __init__( self, stageName, affectingSystematics, inputPropName, outputPropName, selectionDecorNames, selectionDecorCount, dynConfig ): + def __init__( self, stageName, affectingSystematics, inputPropName, outputPropName, metaConfig, dynConfig ): if not stageName in self.allowedStageNames() : raise ValueError ('unknown stage name ' + stageName + ' allowed stage names are ' + ', '.join(self.allowedStageNames())) self.stageName = stageName - if len (selectionDecorNames) != len (selectionDecorCount) : - raise ValueError ("selectionDecorNames and selectionDecorCount don't have the same length: " + str (len (selectionDecorNames)) + " " + str (len (selectionDecorCount))); - self.selectionDecorNames = selectionDecorNames - self.selectionDecorCount = selectionDecorCount + self.metaConfig = metaConfig self.dynConfig = dynConfig if isinstance( inputPropName, dict ):