From 91a9b3b85d52532fcdcab1b0cc02375f9b3d8b28 Mon Sep 17 00:00:00 2001 From: Nils Krumnack <krumnack@iastate.edu> Date: Fri, 3 Apr 2020 13:37:27 -0500 Subject: [PATCH 1/5] update to use the algorithm meta-configuration for jet selection Not sure I got it completely correct, there was some more extensive logic in here, but at least the tests work out. --- .../python/JetAnalysisSequence.py | 45 ++++++++----------- .../python/JetJvtAnalysisSequence.py | 33 +++++++------- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisSequence.py b/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisSequence.py index 454aed27c2c0..a0f35f04f039 100644 --- a/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisSequence.py @@ -85,45 +85,45 @@ def makeJetAnalysisSequence( dataType, jetCollection, postfix = '', seq.append( alg, inputPropName = 'jets', outputPropName = 'jetsOut', stageName = 'calibration' ) # record all the selections each subfunction makes - cutlist = [] - cutlength = [] + seq.addMetaConfigDefault ("selectionDecorNames", []) + seq.addMetaConfigDefault ("selectionDecorCount", []) if radius == 4: - makeSmallRJetAnalysisSequence(seq, cutlist, cutlength, + makeSmallRJetAnalysisSequence(seq, dataType, jetCollection, jetInput=jetInput, postfix=postfix, **kwargs) elif radius in [2, 6]: - makeRScanJetAnalysisSequence(seq, cutlist, cutlength, + makeRScanJetAnalysisSequence(seq, dataType, jetCollection, jetInput=jetInput, radius=radius, postfix=postfix, **kwargs) else: trim = match.group(3) if trim == "": raise ValueError("Untrimmed large-R jets are not supported!") - makeLargeRJetAnalysisSequence(seq, cutlist, cutlength, + makeLargeRJetAnalysisSequence(seq, dataType, jetCollection, jetInput=jetInput, postfix=postfix, **kwargs) # Set up an algorithm used to create jet selection cutflow: if enableCutflow: alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'JetCutFlowDumperAlg'+postfix ) alg.histPattern = 'jet_cflow_%SYS%'+postfix - alg.selection = cutlist - alg.selectionNCuts = cutlength - seq.append( alg, inputPropName = 'input', stageName = 'selection' ) + seq.append( alg, inputPropName = 'input', stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"][:]} ) # Set up an algorithm dumping the kinematic properties of the jets: if enableKinematicHistograms: alg = createAlgorithm( 'CP::KinematicHistAlg', 'JetKinematicDumperAlg'+postfix ) - alg.preselection = "&&".join (cutlist) alg.histPattern = 'jet_%VAR%_%SYS%'+postfix - seq.append( alg, inputPropName = 'input', stageName = 'selection' ) + seq.append( alg, inputPropName = 'input', stageName = 'selection', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) if shallowViewOutput: # Set up an algorithm that makes a view container using the selections # performed previously: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'JetViewFromSelectionAlg'+postfix ) - alg.selection = cutlist seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:]} ) # Set up a final deep copy making algorithm if requested: if deepCopyOutput: @@ -134,7 +134,7 @@ def makeJetAnalysisSequence( dataType, jetCollection, postfix = '', return seq -def makeSmallRJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollection, +def makeSmallRJetAnalysisSequence( seq, dataType, jetCollection, jetInput, postfix = '', runJvtUpdate = False, runFJvtUpdate = False, runJvtSelection = True, runFJvtSelection = False, @@ -144,8 +144,6 @@ def makeSmallRJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollect Keyword arguments seq -- The sequence to add the algorithms to - cutlist -- Insert any cuts into this - cutlength -- Insert the lengths of any cuts into this dataType -- The data type to run on ("data", "mc" or "afii") jetCollection -- The jet container to run on. jetInput -- The type of input used, read from the collection name. @@ -282,16 +280,14 @@ def makeSmallRJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollect stageName = 'selection') # Return the sequence: - return seq, cutlist, cutlength + return seq -def makeRScanJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollection, +def makeRScanJetAnalysisSequence( seq, dataType, jetCollection, jetInput, radius, postfix = '' ): """Add algorithms for the R-scan jets. Keyword arguments seq -- The sequence to add the algorithms to - cutlist -- Insert any cuts into this - cutlength -- Insert the lengths of any cuts into this dataType -- The data type to run on ("data", "mc" or "afii") jetCollection -- The jet container to run on. jetInput -- The type of input used, read from the collection name. @@ -316,14 +312,12 @@ def makeRScanJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollecti # Logging would be good print("WARNING: uncertainties for R-Scan jets are not yet released!") -def makeLargeRJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollection, +def makeLargeRJetAnalysisSequence( seq, dataType, jetCollection, jetInput, postfix = '', largeRMass = "Comb"): """Add algorithms for the R=1.0 jets. Keyword arguments seq -- The sequence to add the algorithms to - cutlist -- Insert any cuts into this - cutlength -- Insert the lengths of any cuts into this dataType -- The data type to run on ("data", "mc" or "afii") jetCollection -- The jet container to run on. jetInput -- The type of input used, read from the collection name. @@ -373,7 +367,6 @@ def makeLargeRJetAnalysisSequence( seq, cutlist, cutlength, dataType, jetCollect alg.uncertaintiesTool.MCType = "MC16a" alg.uncertaintiesTool.IsData = (dataType == "data") seq.append( alg, inputPropName = 'jets', outputPropName = 'jetsOut', - stageName = 'calibration' ) - - cutlist.append('outOfValidity') - cutlength.append(1) + stageName = 'calibration', + metaConfig = {'selectionDecorNames' : ['outOfValidity'], + 'selectionDecorCount' : [1]} ) diff --git a/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetJvtAnalysisSequence.py b/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetJvtAnalysisSequence.py index 61eb02c74e99..71758fcd513d 100644 --- a/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetJvtAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetJvtAnalysisSequence.py @@ -5,7 +5,6 @@ from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence from AnaAlgorithm.DualUseConfig import createAlgorithm def makeJetJvtAnalysisSequence( dataType, jetCollection, - preselection = '', enableFJvt = False, globalSF = True, runSelection = True, @@ -32,52 +31,50 @@ def makeJetJvtAnalysisSequence( dataType, jetCollection, # Define a list of cuts to apply later on and the # number of bits in the corresponding TAccept - cutlist = [] - cutlength = [] + seq.addMetaConfigDefault ("selectionDecorNames", []) + seq.addMetaConfigDefault ("selectionDecorCount", []) # Set up the per-event jet efficiency scale factor calculation algorithm if dataType != 'data' and globalSF: alg = createAlgorithm( 'CP::AsgEventScaleFactorAlg', 'JvtEventScaleFactorAlg' ) - alg.preselection = preselection + '&&no_jvt' if preselection else 'no_jvt' alg.scaleFactorInputDecoration = 'jvt_effSF_%SYS%' alg.scaleFactorOutputDecoration = 'jvt_effSF_%SYS%' seq.append( alg, inputPropName = { 'jets' : 'particles', - 'eventInfo' : 'eventInfo' } ) + 'eventInfo' : 'eventInfo' }, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) if enableFJvt: alg = createAlgorithm( 'CP::AsgEventScaleFactorAlg', 'ForwardJvtEventScaleFactorAlg' ) - alg.preselection = preselection + '&&no_fjvt' if preselection else 'no_fjvt' alg.scaleFactorInputDecoration = 'fjvt_effSF_%SYS%' alg.scaleFactorOutputDecoration = 'fjvt_effSF_%SYS%' seq.append( alg, inputPropName = { 'jets' : 'particles', - 'eventInfo' : 'eventInfo' } ) + 'eventInfo' : 'eventInfo' }, + metaConfig = {'selectionDecorNames' : ['fjvt_selection'] if runSelection else [], + 'selectionDecorCount' : [1] if runSelection else [] }, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"] + ['no_fjvt'])} ) if runSelection: - cutlist.append('jvt_selection') - cutlength.append(1) - - if enableFJvt: - cutlist.append('fjvt_selection') - cutlength.append(1) + seq.addMetaConfigDefault ("selectionDecorNames", ['jvt_selection']) + seq.addMetaConfigDefault ("selectionDecorCount", [1]) # Set up an algorithm used to create jet JVT selection cutflow: if enableCutflow: alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'JetJvtCutFlowDumperAlg' ) alg.histPattern = 'jet_cflow_jvt_%SYS%' - alg.selection = cutlist - alg.selectionNCuts = cutlength - seq.append( alg, inputPropName = { 'jets' : 'input' }) + seq.append( alg, inputPropName = { 'jets' : 'input' }, + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"][:]}) # Set up an algorithm that makes a view container using the selections # performed previously: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'JetJvtViewFromSelectionAlg' ) - alg.selection = cutlist seq.append( alg, inputPropName = { 'jets' : 'input' }, - outputPropName = { 'jets' : 'output' } ) + outputPropName = { 'jets' : 'output' }, + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:]} ) # Return the sequence: return seq -- GitLab From 22bbaaf609f1eed4fe2d227100fbe1be55ae7c18 Mon Sep 17 00:00:00 2001 From: Nils Krumnack <krumnack@iastate.edu> Date: Fri, 3 Apr 2020 12:19:53 -0500 Subject: [PATCH 2/5] make copies of python lists from meta-configuration Just for safety, since the lists may be subsequently updated. --- .../python/MuonAnalysisSequence.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py b/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py index 1464a60cc58b..2b79d744c5e5 100644 --- a/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisSequence.py @@ -167,15 +167,15 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg.selectionDecoration = 'baselineSelection' + postfix + ',as_char' seq.append( alg, inputPropName = 'particles', stageName = 'selection', - dynConfig = {'selectionTool.selectionFlags' : lambda meta : meta["selectionDecorNames"]}) + dynConfig = {'selectionTool.selectionFlags' : lambda meta : meta["selectionDecorNames"][:]}) # Set up an algorithm used to create muon selection cutflow: if enableCutflow: alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'MuonCutFlowDumperAlg' + postfix ) alg.histPattern = 'muon' + postfix + '_cflow_%SYS%' seq.append( alg, inputPropName = 'input', stageName = 'selection', - dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"], - 'selectionNCuts' : lambda meta : meta["selectionDecorCount"]} ) + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"][:]} ) # Set up an algorithm that makes a view container using the selections # performed previously: @@ -184,7 +184,7 @@ def makeMuonAnalysisSequence( dataType, workingPoint, 'MuonViewFromSelectionAlg' + postfix ) seq.append( alg, inputPropName = 'input', outputPropName = 'output', stageName = 'selection', - dynConfig = {'selection' : lambda meta : meta["selectionDecorNamesOutput"]} ) + dynConfig = {'selection' : lambda meta : meta["selectionDecorNamesOutput"][:]} ) # Set up the efficiency scale factor calculation algorithm: alg = createAlgorithm( 'CP::MuonEfficiencyScaleFactorAlg', @@ -214,7 +214,7 @@ def makeMuonAnalysisSequence( dataType, workingPoint, alg.deepCopy = True seq.append( alg, inputPropName = 'input', outputPropName = 'output', stageName = 'selection', - dynConfig = {'selection' : lambda meta : meta["selectionDecorNamesOutput"]} ) + dynConfig = {'selection' : lambda meta : meta["selectionDecorNamesOutput"][:]} ) pass # Return the sequence: -- GitLab From fadc54b64e680ce2b089fb464da3aa13f485df1c Mon Sep 17 00:00:00 2001 From: Nils Krumnack <krumnack@iastate.edu> Date: Fri, 3 Apr 2020 12:20:35 -0500 Subject: [PATCH 3/5] switch selection accounting to use algorithm meta-configuration Just to allow easier sequence modification. --- .../python/ElectronAnalysisSequence.py | 121 +++++++++--------- .../python/PhotonAnalysisSequence.py | 49 +++---- 2 files changed, 84 insertions(+), 86 deletions(-) diff --git a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisSequence.py b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisSequence.py index 185c986e6e6d..468ffc3f37ab 100644 --- a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisSequence.py @@ -66,12 +66,12 @@ def makeElectronAnalysisSequence( dataType, workingPoint, seq = AnaAlgSequence( "ElectronAnalysisSequence" + postfix ) # Variables keeping track of the selections being applied. - selectionDecorNames = [] - selectionDecorCount = [] + seq.addMetaConfigDefault ("selectionDecorNames", []) + seq.addMetaConfigDefault ("selectionDecorNamesOutput", []) + seq.addMetaConfigDefault ("selectionDecorCount", []) # Set up the eta-cut on all electrons prior to everything else alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronEtaCutAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'selectEta' + postfix + ',as_bits' addPrivateTool( alg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' ) alg.selectionTool.maxEta = 2.47 @@ -81,76 +81,76 @@ def makeElectronAnalysisSequence( dataType, workingPoint, alg.selectionTool.useClusterEta = True seq.append( alg, inputPropName = 'particles', outputPropName = 'particlesOut', - stageName = 'calibration' ) - selectionDecorNames.append( alg.selectionDecoration ) - if crackVeto : - selectionDecorCount.append( 5 ) - else : - selectionDecorCount.append( 4 ) + stageName = 'calibration', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration], + 'selectionDecorCount' : [5 if crackVeto else 4]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up the track selection algorithm: alg = createAlgorithm( 'CP::AsgLeptonTrackSelectionAlg', 'ElectronTrackSelectionAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'trackSelection' + postfix + ',as_bits' alg.maxD0Significance = 5 alg.maxDeltaZ0SinTheta = 0.5 seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 3 ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration], + 'selectionDecorCount' : [3]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) if 'LH' in likelihoodWP: # Set up the likelihood ID selection algorithm # It is safe to do this before calibration, as the cluster E is used alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronLikelihoodAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'selectLikelihood' + postfix + ',as_bits' - selectionDecorNames.append( alg.selectionDecoration ) if recomputeLikelihood: # Rerun the likelihood ID addPrivateTool( alg, 'selectionTool', 'AsgElectronLikelihoodTool' ) alg.selectionTool.primaryVertexContainer = 'PrimaryVertices' alg.selectionTool.WorkingPoint = likelihoodWP - selectionDecorCount.append( 7 ) + algDecorCount = 7 else: # Select from Derivation Framework flags addPrivateTool( alg, 'selectionTool', 'CP::AsgFlagSelectionTool' ) dfFlag = "DFCommonElectronsLH" + likelihoodWP.split('LH')[0] alg.selectionTool.selectionFlags = [dfFlag] - selectionDecorCount.append( 1 ) + algDecorCount = 1 else: # Set up the DNN ID selection algorithm alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronDNNAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'selectDNN' + postfix + ',as_bits' - selectionDecorNames.append( alg.selectionDecoration ) if recomputeLikelihood: # Rerun the DNN ID addPrivateTool( alg, 'selectionTool', 'AsgElectronSelectorTool' ) alg.selectionTool.WorkingPoint = likelihoodWP - selectionDecorCount.append( 6 ) + algDecorCount = 6 else: # Select from Derivation Framework flags raise ValueError ( "DNN working points are not available in derivations yet.") seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration], + 'selectionDecorCount' : [algDecorCount]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Select electrons only with good object quality. alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronObjectQualityAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'goodOQ' + postfix + ',as_bits' addPrivateTool( alg, 'selectionTool', 'CP::EgammaIsGoodOQSelectionTool' ) alg.selectionTool.Mask = xAOD.EgammaParameters.BADCLUSELECTRON seq.append( alg, inputPropName = 'particles', - stageName = 'calibration' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 1 ) + stageName = 'calibration', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration], + 'selectionDecorCount' : [1]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up the calibration and smearing algorithm: alg = createAlgorithm( 'CP::EgammaCalibrationAndSmearingAlg', 'ElectronCalibrationAndSmearingAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) addPrivateTool( alg, 'calibrationAndSmearingTool', 'CP::EgammaCalibrationAndSmearingTool' ) alg.calibrationAndSmearingTool.ESModel = 'es2018_R21_v0' @@ -161,25 +161,25 @@ def makeElectronAnalysisSequence( dataType, workingPoint, alg.calibrationAndSmearingTool.useAFII = 0 pass seq.append( alg, inputPropName = 'egammas', outputPropName = 'egammasOut', - stageName = 'calibration' ) + stageName = 'calibration', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up the the pt selection - ptSelectionDecoration = 'selectPt' + postfix + ',as_bits' alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronPtCutAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) - alg.selectionDecoration = ptSelectionDecoration + alg.selectionDecoration = 'selectPt' + postfix + ',as_bits' addPrivateTool( alg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' ) alg.selectionTool.minPt = 4.5e3 seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 2 ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration] if ptSelectionOutput else [], + 'selectionDecorCount' : [2]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up the isolation correction algorithm: if isolationCorrection: alg = createAlgorithm( 'CP::EgammaIsolationCorrectionAlg', 'ElectronIsolationCorrectionAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) addPrivateTool( alg, 'isolationCorrectionTool', 'CP::IsolationCorrectionTool' ) if dataType == 'data': @@ -188,26 +188,27 @@ def makeElectronAnalysisSequence( dataType, workingPoint, alg.isolationCorrectionTool.IsMC = 1 pass seq.append( alg, inputPropName = 'egammas', outputPropName = 'egammasOut', - stageName = 'calibration' ) + stageName = 'calibration', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up the isolation selection algorithm: if isolationWP != 'NonIso' : alg = createAlgorithm( 'CP::EgammaIsolationSelectionAlg', 'ElectronIsolationSelectionAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'isolated' + postfix + ',as_bits' addPrivateTool( alg, 'selectionTool', 'CP::IsolationSelectionTool' ) alg.selectionTool.ElectronWP = isolationWP seq.append( alg, inputPropName = 'egammas', - stageName = 'selection' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 1 ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration], + 'selectionDecorCount' : [1]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Select electrons only if they don't appear to have flipped their charge. if chargeIDSelection: alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronChargeIDSelectionAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.selectionDecoration = 'chargeID' + postfix + ',as_bits' addPrivateTool( alg, 'selectionTool', 'AsgElectronChargeIDSelectorTool' ) @@ -216,55 +217,50 @@ def makeElectronAnalysisSequence( dataType, workingPoint, alg.selectionTool.WorkingPoint = 'Loose' alg.selectionTool.CutOnBDT = -0.337671 # Loose 97% seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 1 ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorNamesOutput' : [alg.selectionDecoration], + 'selectionDecorCount' : [1]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) pass # Set up an algorithm used for decorating baseline electron selection: alg = createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronSelectionSummary' + postfix ) addPrivateTool( alg, 'selectionTool', 'CP::AsgFlagSelectionTool' ) - alg.selectionTool.selectionFlags = selectionDecorNames[ : ] alg.selectionDecoration = 'baselineSelection' + postfix + ',as_char' seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selectionTool.selectionFlags' : lambda meta : meta["selectionDecorNames"] [ : ]} ) # Set up an algorithm used to create electron selection cutflow: if enableCutflow: alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'ElectronCutFlowDumperAlg' + postfix ) alg.histPattern = 'electron_cflow_%SYS%' + postfix - alg.selection = selectionDecorNames[ : ] - alg.selectionNCuts = selectionDecorCount[ : ] - seq.append( alg, inputPropName = 'input', stageName = 'selection' ) + seq.append( alg, inputPropName = 'input', stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"][:]} ) # Set up an algorithm dumping the kinematic properties of the electrons: if enableKinematicHistograms: alg = createAlgorithm( 'CP::KinematicHistAlg', 'ElectronKinematicDumperAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.histPattern = 'electron_%VAR%_%SYS%' + postfix - seq.append( alg, inputPropName = 'input', stageName = 'selection' ) - - # Set up the output selection - if shallowViewOutput or deepCopyOutput: - selectionDecorNamesOutput = selectionDecorNames[ : ] - if not ptSelectionOutput: - selectionDecorNamesOutput.remove(ptSelectionDecoration) + seq.append( alg, inputPropName = 'input', stageName = 'selection', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up an algorithm that makes a view container using the selections # performed previously: if shallowViewOutput: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'ElectronViewFromSelectionAlg' + postfix ) - alg.selection = selectionDecorNamesOutput[ : ] seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNamesOutput"][:]} ) pass # Set up the electron efficiency correction algorithm: alg = createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg', 'ElectronEfficiencyCorrectionAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) addPrivateTool( alg, 'efficiencyCorrectionTool', 'AsgElectronEfficiencyCorrectionTool' ) alg.scaleFactorDecoration = 'effSF' + postfix + '_%SYS%' @@ -281,17 +277,18 @@ def makeElectronAnalysisSequence( dataType, workingPoint, alg.outOfValidityDeco = 'bad_eff' + postfix if dataType != 'data': seq.append( alg, inputPropName = 'electrons', - stageName = 'efficiency' ) + stageName = 'efficiency', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) pass # Set up a final deep copy making algorithm if requested: if deepCopyOutput: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'ElectronDeepCopyMaker' + postfix ) - alg.selection = selectionDecorNamesOutput[:] alg.deepCopy = True seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNamesOutput"][:]} ) pass # Return the sequence: diff --git a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisSequence.py b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisSequence.py index 0e1325e6c63c..7ba200c2d023 100644 --- a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisSequence.py @@ -63,30 +63,30 @@ def makePhotonAnalysisSequence( dataType, workingPoint, seq = AnaAlgSequence( "PhotonAnalysisSequence" + postfix ) # Variables keeping track of the selections being applied. - selectionDecorNames = [] - selectionDecorCount = [] + seq.addMetaConfigDefault ("selectionDecorNames", []) + seq.addMetaConfigDefault ("selectionDecorCount", []) # Set up the photon selection algorithm: alg = createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonIsEMSelectorAlg' + postfix ) alg.selectionDecoration = 'selectEM' - selectionDecorNames.append( alg.selectionDecoration ) if recomputeIsEM: # Rerun the cut-based ID addPrivateTool( alg, 'selectionTool', 'AsgPhotonIsEMSelector' ) alg.selectionTool.isEMMask = quality alg.selectionTool.ConfigFile = \ 'ElectronPhotonSelectorTools/offline/20180116/PhotonIsEMTightSelectorCutDefs.conf' - selectionDecorCount.append( 32 ) else: # Select from Derivation Framework flags addPrivateTool( alg, 'selectionTool', 'CP::AsgFlagSelectionTool' ) dfFlag = 'DFCommonPhotonsIsEM' + qualityWP alg.selectionTool.selectionFlags = [ dfFlag ] - selectionDecorCount.append( 1 ) pass seq.append( alg, inputPropName = 'particles', outputPropName = 'particlesOut', - stageName = 'calibration' ) + stageName = 'calibration', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [32 if recomputeIsEM else 1]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Select electrons only with good object quality. alg = createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonObjectQualityAlg' + postfix ) @@ -95,18 +95,19 @@ def makePhotonAnalysisSequence( dataType, workingPoint, alg.selectionTool.Mask = xAOD.EgammaParameters.BADCLUSPHOTON seq.append( alg, inputPropName = 'particles', outputPropName = 'particlesOut', - stageName = 'calibration' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 1 ) + stageName = 'calibration', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [1]}, + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Only run subsequent processing on the objects passing all of these cuts. # Since these are independent of the photon calibration, and this speeds # up the job. alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'PhotonPreSelViewFromSelectionAlg' + postfix ) - alg.selection = selectionDecorNames[ : ] seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'calibration' ) + stageName = 'calibration', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"] [:]} ) # Set up the calibration ans smearing algorithm. alg = createAlgorithm( 'CP::EgammaCalibrationAndSmearingAlg', @@ -154,9 +155,9 @@ def makePhotonAnalysisSequence( dataType, workingPoint, addPrivateTool( alg, 'selectionTool', 'CP::IsolationSelectionTool' ) alg.selectionTool.PhotonWP = isolationWP seq.append( alg, inputPropName = 'egammas', outputPropName = 'egammasOut', - stageName = 'selection' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 1 ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [1]} ) # Set up the photon efficiency correction algorithm. alg = createAlgorithm( 'CP::PhotonEfficiencyCorrectionAlg', @@ -176,9 +177,9 @@ def makePhotonAnalysisSequence( dataType, workingPoint, if dataType != 'data': seq.append( alg, inputPropName = 'photons', outputPropName = 'photonsOut', - stageName = 'efficiency' ) - selectionDecorNames.append( alg.outOfValidityDeco ) - selectionDecorCount.append( 1 ) + stageName = 'efficiency', + metaConfig = {'selectionDecorNames' : [alg.outOfValidityDeco], + 'selectionDecorCount' : [1]} ) pass # Set up an algorithm used to create photon selection cutflow: @@ -186,26 +187,26 @@ def makePhotonAnalysisSequence( dataType, workingPoint, alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'PhotonCutFlowDumperAlg' + postfix ) alg.histPattern = 'photon_cflow_%SYS%' + postfix - alg.selection = selectionDecorNames[ : ] - alg.selectionNCuts = selectionDecorCount[ : ] seq.append( alg, inputPropName = 'input', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"][:]} ) # Set up an algorithm that makes a view container using the selections # performed previously: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'PhotonViewFromSelectionAlg' + postfix ) - alg.selection = selectionDecorNames[ : ] seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"] [:]} ) # Set up an algorithm dumping the kinematic properties of the photons: if enableKinematicHistograms: alg = createAlgorithm( 'CP::KinematicHistAlg', 'PhotonKinematicDumperAlg' + postfix ) - alg.preselection = "&&".join (selectionDecorNames) alg.histPattern = 'photon_%VAR%_%SYS%' + postfix seq.append( alg, inputPropName = 'input', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up a final deep copy making algorithm if requested: if deepCopyOutput: -- GitLab From 01f2eae9c4a2ff679d871c9caf5cb98169b28874 Mon Sep 17 00:00:00 2001 From: Nils Krumnack <krumnack@iastate.edu> Date: Fri, 3 Apr 2020 12:22:15 -0500 Subject: [PATCH 4/5] switch to using meta-configuration for selection accounting Just to make modifications to analysis sequences more easy to do for the user. --- .../python/TauAnalysisSequence.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisSequence.py b/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisSequence.py index c3860c70cd49..29817be83509 100644 --- a/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisSequence.py @@ -59,8 +59,8 @@ def makeTauAnalysisSequence( dataType, workingPoint, postfix = '', seq = AnaAlgSequence( "TauAnalysisSequence" + postfix ) # Variables keeping track of the selections being applied. - selectionDecorNames = [] - selectionDecorCount = [] + seq.addMetaConfigDefault ("selectionDecorNames", []) + seq.addMetaConfigDefault ("selectionDecorCount", []) # Setup the tau selection tool selectionTool = createPublicTool( 'TauAnalysisTools::TauSelectionTool', @@ -91,9 +91,9 @@ def makeTauAnalysisSequence( dataType, workingPoint, postfix = '', alg.selectionTool.ConfigPath = inputfile alg.selectionDecoration = 'selected_tau' + postfix + ',as_bits' seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) - selectionDecorNames.append( alg.selectionDecoration ) - selectionDecorCount.append( 6 ) + stageName = 'selection', + metaConfig = {'selectionDecorNames' : [alg.selectionDecoration], + 'selectionDecorCount' : [6]} ) # Set up the algorithm calculating the efficiency scale factors for the # taus: @@ -114,43 +114,43 @@ def makeTauAnalysisSequence( dataType, workingPoint, postfix = '', if enableCutflow: alg = createAlgorithm( 'CP::ObjectCutFlowHistAlg', 'TauCutFlowDumperAlg' + postfix ) alg.histPattern = 'tau_cflow_%SYS%' - alg.selection = selectionDecorNames[ : ] - alg.selectionNCuts = selectionDecorCount[ : ] - seq.append( alg, inputPropName = 'input', stageName = 'selection' ) + seq.append( alg, inputPropName = 'input', stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:], + 'selectionNCuts' : lambda meta : meta["selectionDecorCount"][:]} ) # Set up an algorithm used for decorating baseline tau selection: alg = createAlgorithm( 'CP::AsgSelectionAlg', 'TauSelectionSummary' + postfix ) addPrivateTool( alg, 'selectionTool', 'CP::AsgFlagSelectionTool' ) - alg.selectionTool.selectionFlags = selectionDecorNames[ : ] alg.selectionDecoration = 'baselineSelection' + postfix + ',as_char' seq.append( alg, inputPropName = 'particles', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selectionTool.selectionFlags' : lambda meta : meta["selectionDecorNames"][:]} ) # Set up an algorithm that makes a view container using the selections # performed previously: if shallowViewOutput: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'TauViewFromSelectionAlg' + postfix ) - alg.selection = selectionDecorNames[ : ] seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"][:]} ) # Set up an algorithm dumping the kinematic properties of the taus: if enableKinematicHistograms: alg = createAlgorithm( 'CP::KinematicHistAlg', 'TauKinematicDumperAlg' + postfix ) - alg.preselection = '&&'.join (selectionDecorNames) alg.histPattern = 'tau_%VAR%_%SYS%' - seq.append( alg, inputPropName = 'input', stageName = 'selection' ) + seq.append( alg, inputPropName = 'input', stageName = 'selection', + dynConfig = {'preselection' : lambda meta : "&&".join (meta["selectionDecorNames"])} ) # Set up a final deep copy making algorithm if requested: if deepCopyOutput: alg = createAlgorithm( 'CP::AsgViewFromSelectionAlg', 'TauDeepCopyMaker' + postfix ) alg.deepCopy = True - alg.selection = selectionDecorNames[ : ] seq.append( alg, inputPropName = 'input', outputPropName = 'output', - stageName = 'selection' ) + stageName = 'selection', + dynConfig = {'selection' : lambda meta : meta["selectionDecorNames"] [:]} ) pass # Return the sequence: -- GitLab From 450ddb46daae9c4b8527f4b2977a455c1a001611 Mon Sep 17 00:00:00 2001 From: Nils Krumnack <krumnack@iastate.edu> Date: Wed, 30 Sep 2020 15:23:23 -0500 Subject: [PATCH 5/5] move call to xAOD::LoadDictionaries() earlier It needs to happen as early as possible in the job, so I added a separate point in the setup to call it. This may still not fully work for the legacy EL::Algorithm, just due to the fact that it gets instantiated too early. --- .../D3PDTools/EventLoop/EventLoop/Module.h | 20 ++++++++++++++----- .../EventLoop/EventLoop/StopwatchModule.h | 2 +- .../D3PDTools/EventLoop/Root/Module.cxx | 8 +++++++- .../EventLoop/Root/StopwatchModule.cxx | 2 +- .../D3PDTools/EventLoop/Root/Worker.cxx | 8 ++++++-- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Module.h b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Module.h index 47ee245888bf..96e09b45ca77 100644 --- a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Module.h +++ b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Module.h @@ -43,14 +43,24 @@ namespace EL virtual ~Module () noexcept = default; - /// \brief action at the beginning of worker job + /// \brief action at the the very beginning of the worker job /// /// This gets called as early as possible in the worker - /// initialization. The main purpose is to start any benchmarks - /// that are meant to capture the initialization process as - /// well. + /// initialization. Essentially all that should happen before + /// this is to load all the modules. The main purpose is to + /// start any benchmarks that are meant to capture the + /// initialization process as well. public: - virtual ::StatusCode preInitialize (ModuleData& data); + virtual ::StatusCode firstInitialize (ModuleData& data); + + + /// \brief action before opening the first file in the worker + /// job + /// + /// This is mostly meant to allow loading the dictionaries + /// before any files and associated information is loaded. + public: + virtual ::StatusCode preFileInitialize (ModuleData& data); /// \brief action just before algorithms are initialized diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StopwatchModule.h b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StopwatchModule.h index ff51b0a35933..830d87d36841 100644 --- a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StopwatchModule.h +++ b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StopwatchModule.h @@ -28,7 +28,7 @@ namespace EL // public: - virtual ::StatusCode preInitialize (ModuleData& data) override; + virtual ::StatusCode firstInitialize (ModuleData& data) override; public: virtual ::StatusCode onFileExecute (ModuleData& data) override; diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Module.cxx b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Module.cxx index 12d6011d0e10..89aa5b70c327 100644 --- a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Module.cxx +++ b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Module.cxx @@ -23,7 +23,13 @@ namespace EL namespace Detail { ::StatusCode Module :: - preInitialize (ModuleData& /*data*/) + firstInitialize (ModuleData& /*data*/) + { + return ::StatusCode::SUCCESS; + } + + ::StatusCode Module :: + preFileInitialize (ModuleData& /*data*/) { return ::StatusCode::SUCCESS; } diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/Root/StopwatchModule.cxx b/PhysicsAnalysis/D3PDTools/EventLoop/Root/StopwatchModule.cxx index 471460d36bfe..f12dc3a9a50d 100644 --- a/PhysicsAnalysis/D3PDTools/EventLoop/Root/StopwatchModule.cxx +++ b/PhysicsAnalysis/D3PDTools/EventLoop/Root/StopwatchModule.cxx @@ -26,7 +26,7 @@ namespace EL namespace Detail { ::StatusCode StopwatchModule :: - preInitialize (ModuleData& /*data*/) + firstInitialize (ModuleData& /*data*/) { m_stopwatch = std::make_unique<TStopwatch> (); diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx index b5226174b7d0..21da6aa14aec 100644 --- a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx +++ b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx @@ -400,9 +400,13 @@ namespace EL ("EventLoop_JobStats", "EventLoop job statistics"); m_jobStats->SetDirectory (nullptr); + ANA_MSG_INFO ("calling firstInitialize on all modules"); for (auto& module : m_modules) - ANA_CHECK (module->preInitialize (*this)); - + ANA_CHECK (module->firstInitialize (*this)); + ANA_MSG_INFO ("calling preFileInitialize on all modules"); + for (auto& module : m_modules) + ANA_CHECK (module->preFileInitialize (*this)); + return ::StatusCode::SUCCESS; } -- GitLab