diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f45a1b58d692de8eeb9db4addb63324f876907a9..6cc19476cccd672bc63a5e6c30a629a889cf3e67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ # For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages # get an ath analysis image -image: registry.cern.ch/docker.io/atlas/athanalysis:22.2.78 +image: registry.cern.ch/docker.io/atlas/athanalysis:22.2.81 stages: - linting diff --git a/HH4bAnalysis/CMakeLists.txt b/HH4bAnalysis/CMakeLists.txt index 72402cf6389fa4c965a4e716c00b28009768d59e..70e889123ba0814c6614642b4dc16536513b8f08 100644 --- a/HH4bAnalysis/CMakeLists.txt +++ b/HH4bAnalysis/CMakeLists.txt @@ -31,6 +31,10 @@ atlas_add_component( HH4bAnalysis xAODEgamma SystematicsHandlesLib FTagAnalysisInterfacesLib + TrigDecisionInterface + EventBookkeeperToolsLib + TriggerAnalysisAlgorithmsLib + PRIVATE_LINK_LIBRARIES RootCoreUtils ) # Install python modules, joboptions, and share content diff --git a/HH4bAnalysis/share/TriggerAnalysisSequence.py b/HH4bAnalysis/share/TriggerAnalysisSequence.py new file mode 100644 index 0000000000000000000000000000000000000000..31fb7dbfebeafac7069aafece57a1d7a2d1a985d --- /dev/null +++ b/HH4bAnalysis/share/TriggerAnalysisSequence.py @@ -0,0 +1,60 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +# AnaAlgorithm import(s): +from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence +from AnaAlgorithm.DualUseConfig import addPrivateTool, createAlgorithm, createPublicTool + + +def makeTriggerAnalysisSequence( dataType, + triggerChains = [], + prescaleLumiCalcFiles = []): + """Create a basic trigger analysis algorithm sequence + + Keyword arguments: + dataType -- The data type to run on ("data", "mc" or "afii") + triggerChains -- a list of trigger chains + prescaleLumiCalcFiles -- a list of lumicalc files to calculate trigger prescales + """ + + if dataType not in ["data", "mc", "afii"] : + raise ValueError ("invalid data type: " + dataType) + + # Create the analysis algorithm sequence object: + seq = AnaAlgSequence( "TriggerAnalysisSequence" ) + + # Create public trigger tools + xAODConfTool = createPublicTool( 'TrigConf::xAODConfigTool', 'xAODConfigTool' ) + decisionTool = createPublicTool( 'Trig::TrigDecisionTool', 'TrigDecisionTool') + decisionTool.ConfigTool = '%s/%s' % \ + ( xAODConfTool.getType(), xAODConfTool.getName() ) + + seq.addPublicTool( xAODConfTool ) + seq.addPublicTool( decisionTool ) + + if triggerChains: + # Set up the trigger selection: + alg = createAlgorithm( 'HH4B::TrigEventSelectionAlg', 'TrigEventSelectorAlg' ) + alg.tool = '%s/%s' % \ + ( decisionTool.getType(), decisionTool.getName() ) + alg.triggers = list(triggerChains) + alg.selectionDecoration = 'trigPassed' + + seq.append( alg, inputPropName = "input", outputPropName = 'output', stageName = 'selection' ) + print("SEQ_MEMBERS") + print(seq.Members) + + # Calculate trigger prescales + if dataType == 'data' and prescaleLumiCalcFiles: + alg = createAlgorithm( 'CP::TrigPrescalesAlg', 'TrigPrescalesAlg' ) + addPrivateTool( alg, 'pileupReweightingTool', 'CP::PileupReweightingTool' ) + alg.pileupReweightingTool.LumiCalcFiles = prescaleLumiCalcFiles + alg.pileupReweightingTool.TrigDecisionTool = '%s/%s' % \ + ( decisionTool.getType(), decisionTool.getName() ) + alg.triggers = [lumicalc.split(':')[-1] for lumicalc in prescaleLumiCalcFiles if ':' in lumicalc] + alg.triggersAll = list(triggerChains) + alg.prescaleDecoration = 'prescale' + + seq.append( alg, inputPropName = None ) + + # Return the sequence: + return seq diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 7cea8401647fdedc79f69460bce1dc0b32ba3be9..c102d0e5e943a64e2f6326547577358a70a8eb7e 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -46,7 +46,7 @@ def pileupConfigFiles(dataType): # Generate the algorithm to do the dumping. # AthAlgSequence does not respect filter decisions, # so we will need to add a new sequence to the CA -def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): +def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps, trigger_chains): dataType = "mc" if flags.Input.isMC else "data" reco4JetContainerName = getContainerName("Reco4PFlowJets", is_daod_physlite) @@ -73,308 +73,341 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): # Create SystematicsSvc explicitly: cfg.addService(CompFactory.getComp("CP::SystematicsSvc")("SystematicsSvc")) - # Include, and then set up the pileup analysis sequence: - prwFiles, lumicalcFiles = pileupConfigFiles(dataType) - # Create a pile-up analysis sequence - from AsgAnalysisAlgorithms.PileupAnalysisSequence import makePileupAnalysisSequence - - pileupSequence = makePileupAnalysisSequence( - dataType, - userPileupConfigs=prwFiles, - userLumicalcFiles=lumicalcFiles, - autoConfig=False, - ) - pileupSequence.configure(inputName={}, outputName={}) - # print(pileupSequence) # For debugging - # Convert to new configurables - pileupSequenceCnv, algsCnv = convertSequenceAndGetAlgs(CompFactory, pileupSequence) - cfg.addSequence(pileupSequenceCnv) - for alg in algsCnv: - cfg.addEventAlgo(alg, pileupSequenceCnv.getName()) - - # Include, and then set up the electron analysis sequence: - from EgammaAnalysisAlgorithms.ElectronAnalysisSequence import ( - makeElectronAnalysisSequence, - ) - - electronSequence = makeElectronAnalysisSequence( - dataType, - workingPoint="LooseLHElectron.NonIso", - postfix="loose", - deepCopyOutput=False, - shallowViewOutput=True, - recomputeLikelihood=False, - chargeIDSelection=False, - isolationCorrection=False, - crackVeto=False, - ptSelectionOutput=False, - enableCutflow=False, - enableKinematicHistograms=False, - ) - electronSequence.configure( - inputName=electronsContainerName, outputName="AnalysisElectrons_%SYS%" - ) - # print(electronSequence) # For debugging - # Convert to new configurables - electronSequenceCnv, electronAlgsCnv = convertSequenceAndGetAlgs( - CompFactory, electronSequence - ) - cfg.addSequence(electronSequenceCnv) - for electronAlg in electronAlgsCnv: - cfg.addEventAlgo(electronAlg, electronSequenceCnv.getName()) - - # Include, and then set up the photon analysis sequence: - from EgammaAnalysisAlgorithms.PhotonAnalysisSequence import ( - makePhotonAnalysisSequence, - ) - - photonSequence = makePhotonAnalysisSequence( - dataType, - workingPoint="Loose.Undefined", - postfix="loose", - deepCopyOutput=False, - shallowViewOutput=True, - crackVeto=False, - enableCleaning=True, - cleaningAllowLate=False, - recomputeIsEM=False, - ptSelectionOutput=False, - enableCutflow=False, - enableKinematicHistograms=False, - ) - photonSequence.configure( - inputName=photonsContainerName, outputName="AnalysisPhotons_%SYS%" - ) - # print(photonSequence) # For debugging - # Convert to new configurables - photonSequenceCnv, photonAlgsCnv = convertSequenceAndGetAlgs( - CompFactory, photonSequence - ) - cfg.addSequence(photonSequenceCnv) - for photonAlg in photonAlgsCnv: - cfg.addEventAlgo(photonAlg, photonSequenceCnv.getName()) - - # Include, and then set up the muon analysis algorithm sequence: - from MuonAnalysisAlgorithms.MuonAnalysisSequence import makeMuonAnalysisSequence - - muonSequence = makeMuonAnalysisSequence( - dataType, - workingPoint="Loose.NonIso", - postfix="loose", - deepCopyOutput=False, - shallowViewOutput=True, - ptSelectionOutput=False, - qualitySelectionOutput=True, - enableCutflow=False, - enableKinematicHistograms=False, - ) - muonSequence.configure( - inputName=muonsContainerName, outputName="AnalysisMuons_%SYS%" - ) - # print(muonLooseSequence) # For debugging - # Convert to new configurables - muonSequenceCnv, muonAlgsCnv = convertSequenceAndGetAlgs(CompFactory, muonSequence) - cfg.addSequence(muonSequenceCnv) - for muonAlg in muonAlgsCnv: - cfg.addEventAlgo(muonAlg, muonSequenceCnv.getName()) - - from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence - - jetSequence = makeJetAnalysisSequence( - dataType, - jetCollection=reco4JetContainerName, - postfix="smallR", - deepCopyOutput=False, - shallowViewOutput=True, - runGhostMuonAssociation=True, - enableCutflow=False, - enableKinematicHistograms=False, - runFJvtUpdate=False, - runFJvtSelection=False, - runJvtSelection=False, - ) - - from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence - - bTagCalibFile = ( - "xAODBTaggingEfficiency/13TeV/2021-22-13TeV-MC16-CDI-2021-12-02_v2.root" - ) - for tagger_wp in btag_wps: - tagger, btag_wp = tagger_wp.split("_", 1) - ftagSeq = makeFTagAnalysisSequence( - jetSequence, - dataType, - jetCollection=reco4JetContainerName, - btagWP=btag_wp, - btagger=tagger, - generator="Pythia8", - minPt=20000, - postfix="", - preselection=None, - kinematicSelection=False, - noEfficiency=False, - legacyRecommendations=False, - enableCutflow=False, - ) - # Hack until this is merged: - # https://gitlab.cern.ch/atlas/athena/-/merge_requests/54939] - for ftagAlg in ftagSeq: - if "FTagSelectionAlg" in ftagAlg.getName(): - ftagAlg.selectionTool.FlvTagCutDefinitionsFileName = bTagCalibFile - if "FTagEfficiencyScaleFactorAlg" in ftagAlg.getName(): - ftagAlg.efficiencyTool.ScaleFactorFileName = bTagCalibFile - - jetSequence.configure( - inputName=reco4JetContainerName, - outputName="AnalysisJets_%SYS%", + from TrigDecisionTool.TrigDecisionToolConfig import TrigDecisionToolCfg + tdt = cfg.getPrimaryAndMerge(TrigDecisionToolCfg(flags)) + trigSelAlg = CompFactory.CP.TrigEventSelectionAlg( + tool=tdt, + triggers=list(trigger_chains), + selectionDecoration="trigPassed" ) - # print(jetSequence) # For debugging - # Convert to new configurables - jetSequenceCnv, jetAlgsCnv = convertSequenceAndGetAlgs(CompFactory, jetSequence) - cfg.addSequence(jetSequenceCnv) - for jetAlg in jetAlgsCnv: - cfg.addEventAlgo(jetAlg, jetSequenceCnv.getName()) - - from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence - - largeRrecojetSequence = makeJetAnalysisSequence( - dataType, - reco10JetContainerName, - postfix="largeR", - deepCopyOutput=False, - shallowViewOutput=True, - runGhostMuonAssociation=False, - enableCutflow=False, - enableKinematicHistograms=False, - largeRMass="Comb", - ) - largeRrecojetSequence.configure( - inputName=reco10JetContainerName, outputName="AnalysisLargeRRecoJets_%SYS%" - ) - # print(largeRrecojetSequence) # For debugging - # Convert to new configurables - largeRrecojetSequenceCnv, largeJetAlgsCnv = convertSequenceAndGetAlgs( - CompFactory, largeRrecojetSequence - ) - cfg.addSequence(largeRrecojetSequenceCnv) - for largeJetAlg in largeJetAlgsCnv: - cfg.addEventAlgo(largeJetAlg, largeRrecojetSequenceCnv.getName()) - - # Include, and then set up the overlap analysis algorithm sequence: - from AsgAnalysisAlgorithms.OverlapAnalysisSequence import ( - makeOverlapAnalysisSequence, - ) - - overlapSequence = makeOverlapAnalysisSequence( - dataType, - inputLabel="", - outputLabel="passesOR", - linkOverlapObjects=False, - doEleEleOR=False, - doMuPFJetOR=True, - doTaus=False, - doElectrons=True, - doMuons=True, - doJets=True, - doPhotons=True, - doFatJets=True, - enableUserPriority=False, - bJetLabel="", - boostedLeptons=False, - postfix="", - shallowViewOutput=True, - enableCutflow=False, - ) - overlapSequence.configure( - inputName={ - "electrons": "AnalysisElectrons_%SYS%", - "photons": "AnalysisPhotons_%SYS%", - "muons": "AnalysisMuons_%SYS%", - "jets": "AnalysisJets_%SYS%", - "fatJets": "AnalysisLargeRRecoJets_%SYS%", - # 'taus' : 'AnalysisTauJets_%SYS%' - }, - outputName={ - "electrons": "AnalysisElectronsOR_%SYS%", - "photons": "AnalysisPhotonsOR_%SYS%", - "muons": "AnalysisMuonsOR_%SYS%", - "jets": "AnalysisJetsOR_%SYS%", - "fatJets": "AnalysisLargeRRecoJetsOR_%SYS%", - # 'taus' : 'AnalysisTauJetsOR_%SYS%' - }, - ) - # print(overlapSequence) # For debugging - # Convert to new configurables - overlapSequenceCnv, overlapAlgsCnv = convertSequenceAndGetAlgs( - CompFactory, overlapSequence - ) - cfg.addSequence(overlapSequenceCnv) - for overlapAlg in overlapAlgsCnv: - cfg.addEventAlgo(overlapAlg, overlapSequenceCnv.getName()) - - cfg.addEventAlgo( - CompFactory.HH4B.VariableDumperAlg( - "VariableDumper", - EventInfoKey="EventInfo", - RootStreamName="ANALYSIS", - applyJetCleaning=True, - ) - ) - - # Create analysis mini-ntuple + cfg.addEventAlgo(trigSelAlg) + + + + # # Include, and then set up the pileup analysis sequence: + # prwFiles, lumicalcFiles = pileupConfigFiles(dataType) + + # # Create a pile-up analysis sequence + # from AsgAnalysisAlgorithms.PileupAnalysisSequence import makePileupAnalysisSequence + + # pileupSequence = makePileupAnalysisSequence( + # dataType, + # userPileupConfigs=prwFiles, + # userLumicalcFiles=lumicalcFiles, + # autoConfig=False, + # ) + # pileupSequence.configure(inputName={}, outputName={}) + # # print(pileupSequence) # For debugging + # # Convert to new configurables + # pileupSequenceCnv, algsCnv = convertSequenceAndGetAlgs(CompFactory, pileupSequence) + # cfg.addSequence(pileupSequenceCnv) + # for alg in algsCnv: + # cfg.addEventAlgo(alg, pileupSequenceCnv.getName()) + + # # Include, and then set up the electron analysis sequence: + # from EgammaAnalysisAlgorithms.ElectronAnalysisSequence import ( + # makeElectronAnalysisSequence, + # ) + + # electronSequence = makeElectronAnalysisSequence( + # dataType, + # workingPoint="LooseLHElectron.NonIso", + # postfix="loose", + # deepCopyOutput=False, + # shallowViewOutput=True, + # recomputeLikelihood=False, + # chargeIDSelection=False, + # isolationCorrection=False, + # crackVeto=False, + # ptSelectionOutput=False, + # enableCutflow=False, + # enableKinematicHistograms=False, + # ) + # electronSequence.configure( + # inputName=electronsContainerName, outputName="AnalysisElectrons_%SYS%" + # ) + # # print(electronSequence) # For debugging + # # Convert to new configurables + # electronSequenceCnv, electronAlgsCnv = convertSequenceAndGetAlgs( + # CompFactory, electronSequence + # ) + # cfg.addSequence(electronSequenceCnv) + # for electronAlg in electronAlgsCnv: + # print("ELECTRON_ALG_MEMBERS") + # print(electronAlg.name) + # cfg.addEventAlgo(electronAlg, electronSequenceCnv.getName()) + + # # Include, and then set up the photon analysis sequence: + # from EgammaAnalysisAlgorithms.PhotonAnalysisSequence import ( + # makePhotonAnalysisSequence, + # ) + + # photonSequence = makePhotonAnalysisSequence( + # dataType, + # workingPoint="Loose.Undefined", + # postfix="loose", + # deepCopyOutput=False, + # shallowViewOutput=True, + # crackVeto=False, + # enableCleaning=True, + # cleaningAllowLate=False, + # recomputeIsEM=False, + # ptSelectionOutput=False, + # enableCutflow=False, + # enableKinematicHistograms=False, + # ) + # photonSequence.configure( + # inputName=photonsContainerName, outputName="AnalysisPhotons_%SYS%" + # ) + # # print(photonSequence) # For debugging + # # Convert to new configurables + # photonSequenceCnv, photonAlgsCnv = convertSequenceAndGetAlgs( + # CompFactory, photonSequence + # ) + # cfg.addSequence(photonSequenceCnv) + # for photonAlg in photonAlgsCnv: + # cfg.addEventAlgo(photonAlg, photonSequenceCnv.getName()) + + # # Include, and then set up the muon analysis algorithm sequence: + # from MuonAnalysisAlgorithms.MuonAnalysisSequence import makeMuonAnalysisSequence + + # muonSequence = makeMuonAnalysisSequence( + # dataType, + # workingPoint="Loose.NonIso", + # postfix="loose", + # deepCopyOutput=False, + # shallowViewOutput=True, + # ptSelectionOutput=False, + # qualitySelectionOutput=True, + # enableCutflow=False, + # enableKinematicHistograms=False, + # ) + # muonSequence.configure( + # inputName=muonsContainerName, outputName="AnalysisMuons_%SYS%" + # ) + # # print(muonLooseSequence) # For debugging + # # Convert to new configurables + # muonSequenceCnv, muonAlgsCnv = convertSequenceAndGetAlgs(CompFactory, muonSequence) + # cfg.addSequence(muonSequenceCnv) + # for muonAlg in muonAlgsCnv: + # cfg.addEventAlgo(muonAlg, muonSequenceCnv.getName()) + + # from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence + + # jetSequence = makeJetAnalysisSequence( + # dataType, + # jetCollection=reco4JetContainerName, + # postfix="smallR", + # deepCopyOutput=False, + # shallowViewOutput=True, + # runGhostMuonAssociation=True, + # enableCutflow=False, + # enableKinematicHistograms=False, + # runFJvtUpdate=False, + # runFJvtSelection=False, + # runJvtSelection=False, + # ) + + # from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence + + # bTagCalibFile = ( + # "xAODBTaggingEfficiency/13TeV/2021-22-13TeV-MC16-CDI-2021-12-02_v2.root" + # ) + # for tagger_wp in btag_wps: + # tagger, btag_wp = tagger_wp.split("_", 1) + # ftagSeq = makeFTagAnalysisSequence( + # jetSequence, + # dataType, + # jetCollection=reco4JetContainerName, + # btagWP=btag_wp, + # btagger=tagger, + # generator="Pythia8", + # minPt=20000, + # postfix="", + # preselection=None, + # kinematicSelection=False, + # noEfficiency=False, + # legacyRecommendations=False, + # enableCutflow=False, + # ) + # # Hack until this is merged: + # # https://gitlab.cern.ch/atlas/athena/-/merge_requests/54939] + # for ftagAlg in ftagSeq: + # if "FTagSelectionAlg" in ftagAlg.getName(): + # ftagAlg.selectionTool.FlvTagCutDefinitionsFileName = bTagCalibFile + # if "FTagEfficiencyScaleFactorAlg" in ftagAlg.getName(): + # ftagAlg.efficiencyTool.ScaleFactorFileName = bTagCalibFile + + # jetSequence.configure( + # inputName=reco4JetContainerName, + # outputName="AnalysisJets_%SYS%", + # ) + # # print(jetSequence) # For debugging + # # Convert to new configurables + # jetSequenceCnv, jetAlgsCnv = convertSequenceAndGetAlgs(CompFactory, jetSequence) + # cfg.addSequence(jetSequenceCnv) + # for jetAlg in jetAlgsCnv: + # print("JET_SEQUENCE_MEMBER") + # print(jetAlg.name) + # cfg.addEventAlgo(jetAlg, jetSequenceCnv.getName()) + + # from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence + + # largeRrecojetSequence = makeJetAnalysisSequence( + # dataType, + # reco10JetContainerName, + # postfix="largeR", + # deepCopyOutput=False, + # shallowViewOutput=True, + # runGhostMuonAssociation=False, + # enableCutflow=False, + # enableKinematicHistograms=False, + # largeRMass="Comb", + # ) + # largeRrecojetSequence.configure( + # inputName=reco10JetContainerName, outputName="AnalysisLargeRRecoJets_%SYS%" + # ) + # # print(largeRrecojetSequence) # For debugging + # # Convert to new configurables + # largeRrecojetSequenceCnv, largeJetAlgsCnv = convertSequenceAndGetAlgs( + # CompFactory, largeRrecojetSequence + # ) + # cfg.addSequence(largeRrecojetSequenceCnv) + # for largeJetAlg in largeJetAlgsCnv: + # cfg.addEventAlgo(largeJetAlg, largeRrecojetSequenceCnv.getName()) + + # # Include, and then set up the MET analysis sequence: + # from MetAnalysisAlgorithms.MetAnalysisSequence import makeMetAnalysisSequence + + # metSequence = makeMetAnalysisSequence(dataType, metSuffix="AntiKt4EMPFlow") + # metSequence.configure( + # inputName={"jets": "AnalysisJets_%SYS%", "muons": "AnalysisMuons_%SYS%"}, + # outputName="AnalysisMET_%SYS%", + # ) + # # print(metSequence) # For debugging + # # Convert to new configurables + # metSequenceCnv, algsCnv = convertSequenceAndGetAlgs(CompFactory, metSequence) + # cfg.addSequence(metSequenceCnv) + # for alg in algsCnv: + # cfg.addEventAlgo(alg, metSequenceCnv.getName()) + + # # Include, and then set up the overlap analysis algorithm sequence: + # from AsgAnalysisAlgorithms.OverlapAnalysisSequence import ( + # makeOverlapAnalysisSequence, + # ) + + # overlapSequence = makeOverlapAnalysisSequence( + # dataType, + # inputLabel="", + # outputLabel="passesOR", + # linkOverlapObjects=False, + # doEleEleOR=False, + # doMuPFJetOR=True, + # doTaus=False, + # doElectrons=True, + # doMuons=True, + # doJets=True, + # doPhotons=True, + # doFatJets=True, + # enableUserPriority=False, + # bJetLabel="", + # boostedLeptons=False, + # postfix="", + # shallowViewOutput=True, + # enableCutflow=False, + # ) + # overlapSequence.configure( + # inputName={ + # "electrons": "AnalysisElectrons_%SYS%", + # "photons": "AnalysisPhotons_%SYS%", + # "muons": "AnalysisMuons_%SYS%", + # "jets": "AnalysisJets_%SYS%", + # "fatJets": "AnalysisLargeRRecoJets_%SYS%", + # # 'taus' : 'AnalysisTauJets_%SYS%' + # }, + # outputName={ + # "electrons": "AnalysisElectronsOR_%SYS%", + # "photons": "AnalysisPhotonsOR_%SYS%", + # "muons": "AnalysisMuonsOR_%SYS%", + # "jets": "AnalysisJetsOR_%SYS%", + # "fatJets": "AnalysisLargeRRecoJetsOR_%SYS%", + # # 'taus' : 'AnalysisTauJetsOR_%SYS%' + # }, + # ) + # # print(overlapSequence) # For debugging + # # Convert to new configurables + # overlapSequenceCnv, overlapAlgsCnv = convertSequenceAndGetAlgs( + # CompFactory, overlapSequence + # ) + # cfg.addSequence(overlapSequenceCnv) + # for overlapAlg in overlapAlgsCnv: + # cfg.addEventAlgo(overlapAlg, overlapSequenceCnv.getName()) + + # cfg.addEventAlgo( + # CompFactory.HH4B.VariableDumperAlg( + # "VariableDumper", + # EventInfoKey="EventInfo", + # RootStreamName="ANALYSIS", + # applyJetCleaning=True, + # ) + # ) + + # Create analysis ntuple treeMaker = CompFactory.getComp("CP::TreeMakerAlg")("TreeMaker") treeMaker.TreeName = "AnalysisMiniTree" - - # Add event info cfg.addEventAlgo(treeMaker) ntupleMaker = CompFactory.getComp("CP::AsgxAODNTupleMakerAlg")("NTupleMaker") ntupleMaker.TreeName = "AnalysisMiniTree" ntupleMaker.Branches = [ "EventInfo.runNumber -> runNumber", - "EventInfo.eventNumber -> eventNumber", - # we currently don't have any pileup calib files setup - # 'EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%', - "EventInfo.mcEventWeights -> mcEventWeights", - "AnalysisElectrons_%SYS%.pt -> el_%SYS%_pt", - "AnalysisElectrons_%SYS%.eta -> el_%SYS%_eta", - "AnalysisElectrons_%SYS%.phi -> el_%SYS%_phi", - "AnalysisElectronsOR_%SYS%.eta -> el_OR_%SYS%_eta", - "AnalysisElectronsOR_%SYS%.phi -> el_OR_%SYS%_phi", - "AnalysisElectronsOR_%SYS%.pt -> el_OR_%SYS%_pt", - "AnalysisPhotons_%SYS%.pt -> ph_%SYS%_pt", - "AnalysisPhotons_%SYS%.eta -> ph_%SYS%_eta", - "AnalysisPhotons_%SYS%.phi -> ph_%SYS%_phi", - "AnalysisPhotonsOR_%SYS%.eta -> ph_OR_%SYS%_eta", - "AnalysisPhotonsOR_%SYS%.phi -> ph_OR_%SYS%_phi", - "AnalysisPhotonsOR_%SYS%.pt -> ph_OR_%SYS%_pt", - "AnalysisMuons_%SYS%.pt -> mu_%SYS%_pt", - "AnalysisMuons_%SYS%.eta -> mu_%SYS%_eta", - "AnalysisMuons_%SYS%.phi -> mu_%SYS%_phi", - "AnalysisMuonsOR_%SYS%.eta -> mu_OR_%SYS%_eta", - "AnalysisMuonsOR_%SYS%.phi -> mu_OR_%SYS%_phi", - "AnalysisMuonsOR_%SYS%.pt -> mu_OR_%SYS%_pt", - "AnalysisJets_%SYS%.m -> recojet_antikt4_%SYS%_m", - "AnalysisJets_%SYS%.pt -> recojet_antikt4_%SYS%_pt", - "AnalysisJets_%SYS%.eta -> recojet_antikt4_%SYS%_eta", - "AnalysisJets_%SYS%.phi -> recojet_antikt4_%SYS%_phi", - "AnalysisJetsOR_%SYS%.m -> recojet_antikt4_OR_%SYS%_m", - "AnalysisJetsOR_%SYS%.pt -> recojet_antikt4_OR_%SYS%_pt", - "AnalysisJetsOR_%SYS%.eta -> recojet_antikt4_OR_%SYS%_eta", - "AnalysisJetsOR_%SYS%.phi -> recojet_antikt4_OR_%SYS%_phi", - "AnalysisLargeRRecoJets_%SYS%.m -> recojet_antikt10_%SYS%_m", - "AnalysisLargeRRecoJets_%SYS%.pt -> recojet_antikt10_%SYS%_pt", - "AnalysisLargeRRecoJets_%SYS%.eta -> recojet_antikt10_%SYS%_eta", - "AnalysisLargeRRecoJets_%SYS%.phi -> recojet_antikt10_%SYS%_phi", - "AnalysisLargeRRecoJetsOR_%SYS%.m -> recojet_antikt10_OR_%SYS%_m", - "AnalysisLargeRRecoJetsOR_%SYS%.pt -> recojet_antikt10_OR_%SYS%_pt", - "AnalysisLargeRRecoJetsOR_%SYS%.eta -> recojet_antikt10_OR_%SYS%_eta", - "AnalysisLargeRRecoJetsOR_%SYS%.phi -> recojet_antikt10_OR_%SYS%_phi", + # "EventInfo.eventNumber -> eventNumber", + # # we currently don't have any pileup calib files setup + # # 'EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%', + # "EventInfo.mcEventWeights -> mcEventWeights", + # "AnalysisElectrons_%SYS%.pt -> el_%SYS%_pt", + # "AnalysisElectrons_%SYS%.eta -> el_%SYS%_eta", + # "AnalysisElectrons_%SYS%.phi -> el_%SYS%_phi", + # "AnalysisElectronsOR_%SYS%.eta -> el_OR_%SYS%_eta", + # "AnalysisElectronsOR_%SYS%.phi -> el_OR_%SYS%_phi", + # "AnalysisElectronsOR_%SYS%.pt -> el_OR_%SYS%_pt", + # "AnalysisPhotons_%SYS%.pt -> ph_%SYS%_pt", + # "AnalysisPhotons_%SYS%.eta -> ph_%SYS%_eta", + # "AnalysisPhotons_%SYS%.phi -> ph_%SYS%_phi", + # "AnalysisPhotonsOR_%SYS%.eta -> ph_OR_%SYS%_eta", + # "AnalysisPhotonsOR_%SYS%.phi -> ph_OR_%SYS%_phi", + # "AnalysisPhotonsOR_%SYS%.pt -> ph_OR_%SYS%_pt", + # "AnalysisMuons_%SYS%.pt -> mu_%SYS%_pt", + # "AnalysisMuons_%SYS%.eta -> mu_%SYS%_eta", + # "AnalysisMuons_%SYS%.phi -> mu_%SYS%_phi", + # "AnalysisMuonsOR_%SYS%.eta -> mu_OR_%SYS%_eta", + # "AnalysisMuonsOR_%SYS%.phi -> mu_OR_%SYS%_phi", + # "AnalysisMuonsOR_%SYS%.pt -> mu_OR_%SYS%_pt", + # "AnalysisJets_%SYS%.m -> recojet_antikt4_%SYS%_m", + # "AnalysisJets_%SYS%.pt -> recojet_antikt4_%SYS%_pt", + # "AnalysisJets_%SYS%.eta -> recojet_antikt4_%SYS%_eta", + # "AnalysisJets_%SYS%.phi -> recojet_antikt4_%SYS%_phi", + # "AnalysisJetsOR_%SYS%.m -> recojet_antikt4_OR_%SYS%_m", + # "AnalysisJetsOR_%SYS%.pt -> recojet_antikt4_OR_%SYS%_pt", + # "AnalysisJetsOR_%SYS%.eta -> recojet_antikt4_OR_%SYS%_eta", + # "AnalysisJetsOR_%SYS%.phi -> recojet_antikt4_OR_%SYS%_phi", + # "AnalysisLargeRRecoJets_%SYS%.m -> recojet_antikt10_%SYS%_m", + # "AnalysisLargeRRecoJets_%SYS%.pt -> recojet_antikt10_%SYS%_pt", + # "AnalysisLargeRRecoJets_%SYS%.eta -> recojet_antikt10_%SYS%_eta", + # "AnalysisLargeRRecoJets_%SYS%.phi -> recojet_antikt10_%SYS%_phi", + # "AnalysisLargeRRecoJetsOR_%SYS%.m -> recojet_antikt10_OR_%SYS%_m", + # "AnalysisLargeRRecoJetsOR_%SYS%.pt -> recojet_antikt10_OR_%SYS%_pt", + # "AnalysisLargeRRecoJetsOR_%SYS%.eta -> recojet_antikt10_OR_%SYS%_eta", + # "AnalysisLargeRRecoJetsOR_%SYS%.phi -> recojet_antikt10_OR_%SYS%_phi", ] + # ntupleMaker.Branches += [ + # f"AnalysisJets_%SYS%.ftag_select_{wp} -> recojet_antikt4_%SYS%_{wp}" + # for wp in btag_wps + # ] ntupleMaker.Branches += [ - f"AnalysisJets_%SYS%.ftag_select_{btag_wp} -> recojet_antikt4_%SYS%_{btag_wp}" - for btag_wp in btag_wps + f"EventInfo.trigPassed_{tc} -> trigPassed_{tc}" for tc in trigger_chains ] + cfg.addEventAlgo(ntupleMaker) # Fill tree @@ -427,6 +460,16 @@ def main(): ], help="btag working points default %(default)s", ) + parser.add_argument( + "--trigger-chains", + type=str, + nargs="+", + default=[ + "HLT_j420", + "HLT_j460", + ], + help="trigger chains default %(default)s", + ) args = ConfigFlags.fillFromArgs([], parser) # Lock the flags so that the configuration of job subcomponents cannot # modify them silently/unpredictably. @@ -462,6 +505,7 @@ def main(): outfname=args.outFile, is_daod_physlite=args.daod_physlite, btag_wps=args.btag_wps, + trigger_chains=args.trigger_chains, ) ) diff --git a/HH4bAnalysis/src/TrigEventSelectionAlg.h b/HH4bAnalysis/src/TrigEventSelectionAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..e640cfc37eafe397913c65d46fb3cda2a477f930 --- /dev/null +++ b/HH4bAnalysis/src/TrigEventSelectionAlg.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/// @author Tadej Novak + +#ifndef HH4BANALYSIS_TRIG_EVENT_SELECTION_ALG_H +#define HH4BANALYSIS_TRIG_EVENT_SELECTION_ALG_H + +#include <AnaAlgorithm/AnaAlgorithm.h> +#include <AsgTools/ToolHandle.h> +#include <AthContainers/AuxElement.h> +#include <EventBookkeeperTools/FilterReporterParams.h> +#include <TrigDecisionInterface/ITrigDecisionTool.h> + +namespace HH4B +{ + class TrigEventSelectionAlg : public EL::AnaAlgorithm + { + public: + TrigEventSelectionAlg(const std::string &name, + ISvcLocator *svcLoc = nullptr); + + virtual StatusCode initialize() final; + virtual StatusCode execute() final; + virtual StatusCode finalize() final; + + private: + /// \brief trigger decision tool handle + ToolHandle<Trig::ITrigDecisionTool> m_trigDecisionTool; + + /// \brief list of triggers or trigger chains + std::vector<std::string> m_trigList; + + /// \brief the decoration for trigger selection + std::string m_selectionDecoration; + + /// \brief the accessors for \ref m_selectionDecoration and \ref m_trigList combination + std::vector<SG::AuxElement::Decorator<bool>> m_selectionAccessors; + + /// \brief the filter reporter params + FilterReporterParams m_filterParams {this, "TriggerEventSelection", "trigger event selection"}; + }; +} + +#endif diff --git a/HH4bAnalysis/src/TrigEventSelectorAlg.cxx b/HH4bAnalysis/src/TrigEventSelectorAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..254786c39e7475eeab9d5411d246274f260ff6c8 --- /dev/null +++ b/HH4bAnalysis/src/TrigEventSelectorAlg.cxx @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/// @author Tadej Novak + +#include <EventBookkeeperTools/FilterReporter.h> +#include <RootCoreUtils/StringUtil.h> +#include <TriggerAnalysisAlgorithms/TrigEventSelectionAlg.h> +#include <xAODEventInfo/EventInfo.h> + +// Class definition +#include "TrigEventSelectionAlg.h" + +namespace HH4B +{ + TrigEventSelectionAlg::TrigEventSelectionAlg(const std::string &name, + ISvcLocator *svcLoc) + : EL::AnaAlgorithm(name, svcLoc), + m_trigDecisionTool("Trig::TrigDecisionTool/TrigDecisionTool", this) + { + declareProperty("tool", m_trigDecisionTool, "trigger decision tool"); + declareProperty("triggers", m_trigList, "trigger selection list"); + declareProperty("selectionDecoration", m_selectionDecoration, "the decoration the trigger pass status"); + } + + StatusCode TrigEventSelectionAlg::initialize() + { + if (m_trigList.empty()) { + ATH_MSG_ERROR("A list of triggers needs to be provided"); + return StatusCode::FAILURE; + } + ATH_MSG_INFO ("TRIGGER_EVENT_SELECTION_ALG"); + + ANA_CHECK(m_trigDecisionTool.retrieve()); + + if (!m_selectionDecoration.empty()) { + for (const std::string &chain : m_trigList) { + m_selectionAccessors.emplace_back(m_selectionDecoration + "_" + RCU::substitute (chain, "-", "_")); + } + } + ANA_CHECK (m_filterParams.initialize()); + + return StatusCode::SUCCESS; + } + + StatusCode TrigEventSelectionAlg::execute() + { + FilterReporter filter (m_filterParams, false); + + if (m_trigList.empty()) { + filter.setPassed(true); + return StatusCode::SUCCESS; + } + + const xAOD::EventInfo *evtInfo = 0; + ANA_CHECK(evtStore()->retrieve(evtInfo, "EventInfo")); + + for (size_t i = 0; i < m_trigList.size(); i++) { + bool trigPassed = m_trigDecisionTool->isPassed(m_trigList[i]); + if (!m_selectionDecoration.empty()) { + m_selectionAccessors[i](*evtInfo) = trigPassed; + } + if (trigPassed) + filter.setPassed (true); + } + + return StatusCode::SUCCESS; + } + + StatusCode TrigEventSelectionAlg::finalize() + { + ANA_MSG_INFO (m_filterParams.summary()); + + return StatusCode::SUCCESS; + } +} + diff --git a/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx b/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx index b2c66a6b4374a3cd72e02b4d9926b96c7326ba57..106290207f535c935060dddccd4b620fdc04d2b7 100644 --- a/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx +++ b/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx @@ -2,6 +2,7 @@ #include "../VariableDumperAlg.h" #include "../VariablePlotterAlg.h" #include "../tools/NTrkVertexCounter.h" +#include "../TrigEventSelectionAlg.h" using namespace HH4B; @@ -9,3 +10,4 @@ DECLARE_COMPONENT(NTrkVertexCounter) DECLARE_COMPONENT(PileupPlotterAlg) DECLARE_COMPONENT(VariablePlotterAlg) DECLARE_COMPONENT(VariableDumperAlg) +DECLARE_COMPONENT(TrigEventSelectionAlg) diff --git a/README.md b/README.md index 4b587b6eef2ef9bfad8e17ebbe253cef86fda9d2..8a1d14b7776525fac477a64624e2b78d4abead09 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Now, compile the package mkdir build cd build setupATLAS -asetup AthAnalysis,22.2.78 +asetup AthAnalysis,22.2.81 cmake ../hh4b-analysis/ make source */setup.sh @@ -57,8 +57,8 @@ If you would rather work on a local computer, numbered `AthAnalysis` releases ar Preferably, do this in `$WORKDIR`. ``` -docker pull atlas/athanalysis:22.2.78 -docker run -t -i -v $PWD:/workarea:delegated -v $HOME:$HOME:delegated atlas/athanalysis:22.2.78 +docker pull atlas/athanalysis:22.2.81 +docker run -t -i -v $PWD:/workarea:delegated -v $HOME:$HOME:delegated atlas/athanalysis:22.2.81 ``` This will start up an interactive terminal inside the container, which has read/write access to the following paths: