From 47adbf9afcf095ffb06030f626920f6f81c4a6b2 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Fri, 8 Jul 2022 11:57:01 +0200 Subject: [PATCH 01/33] added dRtoLargestPtJet --- HH4bAnalysis/share/VariableDumperConfig.py | 2 ++ HH4bAnalysis/src/VariableDumperAlg.cxx | 28 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 8e4aeba20..d17e481e2 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -358,6 +358,8 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): "AnalysisJetsBTAG_%SYS%.pt -> recojet_antikt4_%SYS%_pt", "AnalysisJetsBTAG_%SYS%.eta -> recojet_antikt4_%SYS%_eta", "AnalysisJetsBTAG_%SYS%.phi -> recojet_antikt4_%SYS%_phi", + "AnalysisJetsBTAG_%SYS%.dRtoLargestPtJet ->" + " recojet_antikt4_%SYS%_dRtoLargestPtJet", "AnalysisJetsBTAGOR_%SYS%.m -> recojet_antikt4_OR_%SYS%_m", "AnalysisJetsBTAGOR_%SYS%.pt -> recojet_antikt4_OR_%SYS%_pt", "AnalysisJetsBTAGOR_%SYS%.eta -> recojet_antikt4_OR_%SYS%_eta", diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index be9837d1c..bea8c58d6 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -70,6 +70,34 @@ namespace HH4B const xAOD::JetContainer *antiKt4RecoJets(nullptr); ANA_CHECK(m_jetsmallRHandle.retrieve(antiKt4RecoJets, sys)); // do something with antiKt4RecoJets + + // set defaults + double maxJetPt = -1; + double thisJetPt = -1; + int maxJetPtIndex = -1; + + // find jet index with largest pt + for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) + { + const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); + thisJetPt = thisJet->pt(); + if (thisJetPt > maxJetPt) + { + maxJetPt = thisJetPt; + maxJetPtIndex = jetIndex; + } + } + + // calculate dR to other jets + const xAOD::Jet *maxPtJet = antiKt4RecoJets->at(maxJetPtIndex); + + for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) + { + const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); + thisJet->auxdecor<double>("dRtoLargestPtJet") = + thisJet->p4().DeltaR(maxPtJet->p4()); + } + const xAOD::JetContainer *antiKt10RecoJets(nullptr); ANA_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); // do something with antiKt10RecoJets -- GitLab From 6c3d1e4aa823a7e2af08e0fd08198ba11d8d410b Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Tue, 12 Jul 2022 14:16:14 +0200 Subject: [PATCH 02/33] save VR sequence --- HH4bAnalysis/share/VariableDumperConfig.py | 35 ++++- .../share/utils/containerNameHelper.py | 3 + HH4bAnalysis/src/VariableDumperAlg.cxx | 141 ++++++++++++++---- HH4bAnalysis/src/VariableDumperAlg.h | 5 + .../src/tools/getBoostedHiggsCandidates.cxx | 21 +++ .../src/tools/getBoostedHiggsCandidates.h | 10 ++ HH4bAnalysis/src/tools/kLargestJets.cxx | 49 ++++++ HH4bAnalysis/src/tools/kLargestJets.h | 18 +++ 8 files changed, 248 insertions(+), 34 deletions(-) create mode 100644 HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx create mode 100644 HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h create mode 100644 HH4bAnalysis/src/tools/kLargestJets.cxx create mode 100644 HH4bAnalysis/src/tools/kLargestJets.h diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index c9a495f3f..0c6989a9c 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -51,6 +51,7 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): reco4JetContainerName = getContainerName("Reco4PFlowJets", isDaodPhyslite) reco10JetContainerName = getContainerName("Reco10PFlowJets", isDaodPhyslite) + recoVRJetContainerName = getContainerName("RecoVRPFlowJets", isDaodPhyslite) muonsContainerName = getContainerName("Muons", isDaodPhyslite) electronsContainerName = getContainerName("Electrons", isDaodPhyslite) photonsContainerName = getContainerName("Photons", isDaodPhyslite) @@ -206,7 +207,7 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): generator="default", # Pythia8 not available in makeFTagAnalysisSequence CDI postfix="", preselection=None, - kinematicSelection=False, + kinematicSelection=True, noEfficiency=False, legacyRecommendations=True, enableCutflow=False, @@ -261,6 +262,31 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): for largeJetAlg in largeJetAlgsCnv: cfg.addEventAlgo(largeJetAlg, largeRrecojetSequenceCnv.getName()) + from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence + + largeRrecojetSequence = makeJetAnalysisSequence( + dataType, + reco10JetContainerName, + postfix="VR", + deepCopyOutput=False, + shallowViewOutput=True, + runGhostMuonAssociation=False, + enableCutflow=False, + enableKinematicHistograms=False, + largeRMass="Comb", + ) + largeRrecojetSequence.configure( + inputName=recoVRJetContainerName, outputName="AnalysisVRRecoJets_%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, @@ -337,6 +363,11 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): # we currently don't have any pileup calib files setup # 'EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%', "EventInfo.mcEventWeights -> mcEventWeights", + "EventInfo.m_h1 -> m_h1", + "EventInfo.m_h2 -> m_h2", + "EventInfo.m_hh -> m_hh", + "EventInfo.dR_jets_in_h1 -> dR_jets_in_h1", + "EventInfo.dR_jets_in_h2 -> dR_jets_in_h2", "AnalysisElectrons_%SYS%.pt -> el_%SYS%_pt", "AnalysisElectrons_%SYS%.eta -> el_%SYS%_eta", "AnalysisElectrons_%SYS%.phi -> el_%SYS%_phi", @@ -359,8 +390,6 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): "AnalysisJetsBTAG_%SYS%.pt -> recojet_antikt4_%SYS%_pt", "AnalysisJetsBTAG_%SYS%.eta -> recojet_antikt4_%SYS%_eta", "AnalysisJetsBTAG_%SYS%.phi -> recojet_antikt4_%SYS%_phi", - "AnalysisJetsBTAG_%SYS%.dRtoLargestPtJet ->" - " recojet_antikt4_%SYS%_dRtoLargestPtJet", "AnalysisJetsBTAGOR_%SYS%.m -> recojet_antikt4_OR_%SYS%_m", "AnalysisJetsBTAGOR_%SYS%.pt -> recojet_antikt4_OR_%SYS%_pt", "AnalysisJetsBTAGOR_%SYS%.eta -> recojet_antikt4_OR_%SYS%_eta", diff --git a/HH4bAnalysis/share/utils/containerNameHelper.py b/HH4bAnalysis/share/utils/containerNameHelper.py index 121a76bde..359a74d88 100644 --- a/HH4bAnalysis/share/utils/containerNameHelper.py +++ b/HH4bAnalysis/share/utils/containerNameHelper.py @@ -3,6 +3,7 @@ # custom container names used in this framework RECO_4_PFLOW_JETS_KEY = "Reco4PFlowJets" RECO_10_PFLOW_JETS_KEY = "Reco10PFlowJets" +RECO_VR_TRACK_JETS_KEY = "RecoVRTrackJets" TRUTH_4_JETS_KEY = "Truth4Jets" TRUTH_10_JETS_KEY = "Truth10Jets" MUONS_KEY = "Muons" @@ -13,6 +14,7 @@ container_map = { "DAOD_PHYS": { RECO_4_PFLOW_JETS_KEY: "AntiKt4EMPFlowJets", RECO_10_PFLOW_JETS_KEY: "AntiKt10LCTopoTrimmedPtFrac5SmallR20Jets", + RECO_VR_TRACK_JETS_KEY: "AntiKtVR30Rmax4Rmin02PV0TrackJets", TRUTH_4_JETS_KEY: "AntiKt4TruthDressedWZJets", TRUTH_10_JETS_KEY: "AntiKt10TruthTrimmedPtFrac5SmallR20Jets", MUONS_KEY: "Muons", @@ -22,6 +24,7 @@ container_map = { "DAOD_PHYSLITE": { RECO_4_PFLOW_JETS_KEY: "AnalysisJets", RECO_10_PFLOW_JETS_KEY: "?", + RECO_VR_TRACK_JETS_KEY: "?", TRUTH_4_JETS_KEY: "AntiKt4TruthDressedWZJets", TRUTH_10_JETS_KEY: "?", MUONS_KEY: "AnalysisMuons", diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 676bf43a5..efe31cee0 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -7,6 +7,8 @@ // Class definition #include "VariableDumperAlg.h" +// #include "tools/getBoostedHiggsCandidates.h" +// #include "tools/kLargestJets.h" // // method implementations @@ -18,7 +20,10 @@ namespace HH4B ISvcLocator *pSvcLocator) : AthHistogramAlgorithm(name, pSvcLocator), m_acc_DFCommonJets_eventClean_LooseBad( - "DFCommonJets_eventClean_LooseBad") + "DFCommonJets_eventClean_LooseBad") m_acc_VRTrackJets + + SG::AuxElement::ConstAccessor<char> m_acc_VRTrackJets; + AntiKtVR30Rmax4Rmin02PV0TrackJets(DataVector<xAOD::Jet_v1>)[Jet] { declareProperty("applyJetCleaning", m_applyJetCleaning); } @@ -38,6 +43,7 @@ namespace HH4B ATH_CHECK(m_systematicsList.addHandle(m_muonHandle)); ATH_CHECK(m_systematicsList.addHandle(m_jetsmallRHandle)); ATH_CHECK(m_systematicsList.addHandle(m_jetlargeRHandle)); + ATH_CHECK(m_btagSelTool.retrieve()); ATH_CHECK(m_EventInfoKey.initialize()); ATH_CHECK(m_systematicsList.initialize()); @@ -79,39 +85,112 @@ namespace HH4B ATH_CHECK(m_muonHandle.retrieve(muons, sys)); // do something with muons const xAOD::JetContainer *antiKt4RecoJets(nullptr); - ANA_CHECK(m_jetsmallRHandle.retrieve(antiKt4RecoJets, sys)); + ATH_CHECK(m_jetsmallRHandle.retrieve(antiKt4RecoJets, sys)); // do something with antiKt4RecoJets - - // set defaults - double maxJetPt = -1; - double thisJetPt = -1; - int maxJetPtIndex = -1; - - // find jet index with largest pt - for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) - { - const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); - thisJetPt = thisJet->pt(); - if (thisJetPt > maxJetPt) - { - maxJetPt = thisJetPt; - maxJetPtIndex = jetIndex; - } - } - - // calculate dR to other jets - const xAOD::Jet *maxPtJet = antiKt4RecoJets->at(maxJetPtIndex); - - for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) - { - const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); - thisJet->auxdecor<double>("dRtoLargestPtJet") = - thisJet->p4().DeltaR(maxPtJet->p4()); - } - const xAOD::JetContainer *antiKt10RecoJets(nullptr); - ANA_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); + ATH_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); + // do something with antiKt10RecoJets + const xAOD::JetContainer *antiKtVRRecoJets(nullptr); + ATH_CHECK(m_jetVRHandle.retrieve(antiKtVRRecoJets, sys)); // do something with antiKt10RecoJets + ATH_MSG_DEBUG("Number of 0.4 jets in event " << antiKt4RecoJets->size()); + ATH_MSG_DEBUG("Number of 1.0 jets in event " + << antiKt10RecoJets->size()); + + // std::cout << antiKt4RecoJets->size() << "\n"; + // std::cout << jetSmallBTag->size() << "\n"; + + // for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) + // { + // const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); + // // std::cout << jetIndex; + // // std::cout << antiKt4RecoJets->size(); + // SG::AuxElement::ConstAccessor<char> isTag77( + // "ftag_kin_select_DL1r_FixedCutBEff_77"); + // std::cout << isTag77(*thisJet) << "\n"; + // } + + // TODO: send in btagged jets + // set defaults + eventInfo->auxdecor<double>("dR_jets_in_h1") = -1; + eventInfo->auxdecor<double>("dR_jets_in_h2") = -1; + eventInfo->auxdecor<double>("m_h1") = -1; + eventInfo->auxdecor<double>("m_h2") = -1; + eventInfo->auxdecor<double>("m_hh") = -1; + + // // check if we have 4 jets + // if (antiKt4RecoJets->size() < 4) + // { + // return StatusCode::SUCCESS; + // } + // // get indices of 4 largest pt jets + // std::vector<int> fourLargestPtJetsIndices = + // kLargestJets(antiKt4RecoJets, 4); + + // const xAOD::Jet *largestPtJet = + // antiKt4RecoJets->at(fourLargestPtJetsIndices[0]); + + // // calc dR to other higgs candidate jets + // std::vector<double> dRtoLargestPtJet; + // for (int jetIndex : fourLargestPtJetsIndices) + // { + // const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); + // double thisDRtoLargestPtJet = + // thisJet->p4().DeltaR(largestPtJet->p4()); + // dRtoLargestPtJet.push_back(thisDRtoLargestPtJet); + // ATH_MSG_DEBUG(thisDRtoLargestPtJet); + // } + + // // get closest jet to leading jet + // int closestToLeadingJetEntry = + // std::min_element(dRtoLargestPtJet.begin(), dRtoLargestPtJet.end()) + // - dRtoLargestPtJet.begin(); + // const xAOD::Jet *closestToLeadingJet = antiKt4RecoJets->at( + // fourLargestPtJetsIndices[closestToLeadingJetEntry]); + + // // make higgs candidates + // TLorentzVector h1_cand = largestPtJet->p4() + + // closestToLeadingJet->p4(); double dR_jets_in_h1 = + // largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); + // // make a copy of the indices and delete the ones of the h1_cand + // // order matters! + // std::vector<int> otherJetIndices = fourLargestPtJetsIndices; + // otherJetIndices.erase(otherJetIndices.begin() + + // closestToLeadingJetEntry); + // otherJetIndices.erase(otherJetIndices.begin()); + + // const xAOD::Jet *otherJet1 = antiKt4RecoJets->at(otherJetIndices[0]); + // const xAOD::Jet *otherJet2 = antiKt4RecoJets->at(otherJetIndices[1]); + + // TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); + // double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); + + // double m_h1 = h1_cand.M(); + // double m_h2 = h2_cand.M(); + // double m_hh = (h1_cand + h2_cand).M(); + + // TODO: return resolved function as std::map "m_h1" + + // for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) + // { + // const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); + // // std::cout << jetIndex; + // // std::cout << antiKt4RecoJets->size(); + // SG::AuxElement::ConstAccessor<char> isTag77( + // "ftag_kin_select_DL1r_FixedCutBEff_77"); + // std::cout << isTag77(*thisJet) << "\n"; + // } + + // recommended by ftag Remove the event if any of your signal jets have + // relativeDeltaRToVRJet < 1.0. + // getBoostedHiggsCandidates(antiKt10RecoJets); + + // write out Higgs candidates + eventInfo->auxdecor<double>("m_h1") = m_h1; + eventInfo->auxdecor<double>("m_h2") = m_h2; + eventInfo->auxdecor<double>("m_hh") = m_hh; + eventInfo->auxdecor<double>("dR_jets_in_resolved_h1") = dR_jets_in_h1; + eventInfo->auxdecor<double>("dR_jets_in_resolved_h2") = dR_jets_in_h2; } return StatusCode::SUCCESS; diff --git a/HH4bAnalysis/src/VariableDumperAlg.h b/HH4bAnalysis/src/VariableDumperAlg.h index 401fd82d7..80c818d94 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.h +++ b/HH4bAnalysis/src/VariableDumperAlg.h @@ -15,6 +15,7 @@ #include <AthContainers/AuxElement.h> #include <SystematicsHandles/SysListHandle.h> #include <SystematicsHandles/SysReadHandle.h> +#include <TLorentzVector.h> #include <xAODEgamma/ElectronContainer.h> #include <xAODEgamma/PhotonContainer.h> #include <xAODEventInfo/EventInfo.h> @@ -79,6 +80,10 @@ private: this, "jetlargeR", "AnalysisLargeRRecoJets_%SYS%", "the large-R jet collection to run on"}; + CP::SysReadHandle<xAOD::JetContainer> m_jetVRHandle{ + this, "jetVRR", "AnalysisVRRecoJets_%SYS%", + "the Variable radius jet collection to run on"}; + // output variables for the current event unsigned int m_runNumber = 0; unsigned long long m_eventNumber = 0; diff --git a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx new file mode 100644 index 000000000..ebf42668a --- /dev/null +++ b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx @@ -0,0 +1,21 @@ +#include "getBoostedHiggsCandidates.h" +#include "kLargestJets.h" +#include "map" +// #include "vector" +#include "string" +#include "xAODJet/JetContainer.h" + +std::map<std::string, double> +getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets) +{ + std::map<std::string, double> h_cand_vars; + h_cand_vars["sun"] = 3; + + std::vector<int> twoLargestPtJetsIndices = kLargestJets(largeRjets, 2); + + // need track jet container inside first and second + // how to associate, until when are they still inside large R + // tag them as b's + + return h_cand_vars; +}; \ No newline at end of file diff --git a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h new file mode 100644 index 000000000..f1a1b1996 --- /dev/null +++ b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h @@ -0,0 +1,10 @@ +#ifndef HH4BANALYSIS_GET_BOOSTED_HIGGS_CANDIDATES +#define HH4BANALYSIS_GET_BOOSTED_HIGGS_CANDIDATES + +#include "map" +#include "xAODJet/JetContainer.h" + +std::map<std::string, double> +getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets); + +#endif \ No newline at end of file diff --git a/HH4bAnalysis/src/tools/kLargestJets.cxx b/HH4bAnalysis/src/tools/kLargestJets.cxx new file mode 100644 index 000000000..06a7dcb84 --- /dev/null +++ b/HH4bAnalysis/src/tools/kLargestJets.cxx @@ -0,0 +1,49 @@ +#include "queue" +#include "xAODJet/JetContainer.h" + +// efficient algorithm to find k largest elements in size n vector with +// efficienvy O(n log k) +// see https://stackoverflow.com/a/38391603 + +// returns jet indices in descending order of the largest k found pt's +std::vector<int> kLargestJets(const xAOD::JetContainer *jets, int k_) +{ + // Priority queues are a type of container adaptors, specifically designed + // such that its first element is always the greatest of the elements it + // contains. Using std::greater<T> causes the smallest element to appear as + // the top(). + std::priority_queue<std::pair<double, int>, + std::vector<std::pair<double, int>>, + std::greater<std::pair<double, int>>> + queue; + long unsigned int k = k_; // number of indices we need + + // loop over jets + const xAOD::Jet *thisJet; + double thisJetPt; + for (long unsigned int i = 0; i < jets->size(); i++) + { + thisJet = jets->at(i); + thisJetPt = thisJet->pt(); + // fill queue with first k values + if (queue.size() < k) + // push inserts element into queue and sorts it + queue.push(std::pair<double, int>(thisJetPt, i)); + // if smallest element in queue is smaller than thisJetPt, replace + else if (queue.top().first < thisJetPt) + { + queue.pop(); + queue.push(std::pair<double, int>(thisJetPt, i)); + } + } + + // return vector indices in descending order of the largest k found elements + k = queue.size(); + std::vector<int> res(k); + for (long unsigned int i = 0; i < k; ++i) + { + res[k - i - 1] = queue.top().second; + queue.pop(); + } + return res; +} diff --git a/HH4bAnalysis/src/tools/kLargestJets.h b/HH4bAnalysis/src/tools/kLargestJets.h new file mode 100644 index 000000000..a5e004508 --- /dev/null +++ b/HH4bAnalysis/src/tools/kLargestJets.h @@ -0,0 +1,18 @@ +#ifndef HH4BANALYSIS_K_LARGEST_JETS +#define HH4BANALYSIS_K_LARGEST_JETS + +#include "vector" +#include "xAODJet/JetContainer.h" + +// efficient algorithm to find k largest elements in size n vector with +// efficienvy O(n log k). see https://stackoverflow.com/a/38391603 + +// it works something like this : +// jet_with_pt's {2, 8, 7, 5, 9, 3, 6, 1, 10, 4}; +// kLargestJets(jets,5) returns +// [8,4,1,2,6] + +// returns jet indices in descending order of the largest k found pt's +std::vector<int> kLargestJets(const xAOD::JetContainer *jets, int k_); + +#endif \ No newline at end of file -- GitLab From 6bd60b83d73364cddfdaeb0150955b747cf8e073 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Wed, 13 Jul 2022 15:43:15 +0200 Subject: [PATCH 03/33] saving --- HH4bAnalysis/share/VariableDumperConfig.py | 52 ++---- HH4bAnalysis/src/ResolvedAnalysis.cxx | 34 ++++ HH4bAnalysis/src/VariableDumperAlg.cxx | 157 +++++++++--------- HH4bAnalysis/src/VariableDumperAlg.h | 8 +- .../src/tools/getBoostedHiggsCandidates.cxx | 12 +- .../src/tools/getBoostedHiggsCandidates.h | 6 +- 6 files changed, 146 insertions(+), 123 deletions(-) create mode 100644 HH4bAnalysis/src/ResolvedAnalysis.cxx diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 0c6989a9c..ff73a2508 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -51,7 +51,7 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): reco4JetContainerName = getContainerName("Reco4PFlowJets", isDaodPhyslite) reco10JetContainerName = getContainerName("Reco10PFlowJets", isDaodPhyslite) - recoVRJetContainerName = getContainerName("RecoVRPFlowJets", isDaodPhyslite) + recoVRJetContainerName = getContainerName("RecoVRTrackJets", isDaodPhyslite) muonsContainerName = getContainerName("Muons", isDaodPhyslite) electronsContainerName = getContainerName("Electrons", isDaodPhyslite) photonsContainerName = getContainerName("Photons", isDaodPhyslite) @@ -225,17 +225,17 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): # Define and configure a tool instance # Properties can be set as keyword arguments to the tool constructor - # bTagSelectionTool = CompFactory.BTaggingSelectionTool( - # "bTagSelectionTool", - # FlvTagCutDefinitionsFileName=( - # "xAODBTaggingEfficiency/13TeV/2021-22-13TeV-MC16-CDI-2021-12-02_v2.root" - # ), - # TaggerName="DL1dv00", - # OperatingPoint="FixedCutBEff_77", - # JetAuthor=reco4JetContainerName, - # MinPt=20e3, - # MaxEta=2.5, - # ) + bTagSelectionTool = CompFactory.BTaggingSelectionTool( + "bTagSelectionTool", + FlvTagCutDefinitionsFileName=( + "xAODBTaggingEfficiency/13TeV/2021-22-13TeV-MC16-CDI-2021-12-02_v2.root" + ), + TaggerName="DL1dv00", + OperatingPoint="FixedCutBEff_77", + JetAuthor=reco4JetContainerName, + MinPt=20e3, + MaxEta=2.5, + ) from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence @@ -262,31 +262,6 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): for largeJetAlg in largeJetAlgsCnv: cfg.addEventAlgo(largeJetAlg, largeRrecojetSequenceCnv.getName()) - from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence - - largeRrecojetSequence = makeJetAnalysisSequence( - dataType, - reco10JetContainerName, - postfix="VR", - deepCopyOutput=False, - shallowViewOutput=True, - runGhostMuonAssociation=False, - enableCutflow=False, - enableKinematicHistograms=False, - largeRMass="Comb", - ) - largeRrecojetSequence.configure( - inputName=recoVRJetContainerName, outputName="AnalysisVRRecoJets_%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, @@ -343,9 +318,10 @@ def VariableDumperCfg(flags, isDaodPhyslite, outfname): CompFactory.HH4B.VariableDumperAlg( "VariableDumper", EventInfoKey="EventInfo", + VRTrackJetsKey=recoVRJetContainerName, RootStreamName="ANALYSIS", applyJetCleaning=True, - # BTaggingSelectionTool=bTagSelectionTool, + BTaggingSelectionTool=bTagSelectionTool, ) ) diff --git a/HH4bAnalysis/src/ResolvedAnalysis.cxx b/HH4bAnalysis/src/ResolvedAnalysis.cxx new file mode 100644 index 000000000..7ad886b71 --- /dev/null +++ b/HH4bAnalysis/src/ResolvedAnalysis.cxx @@ -0,0 +1,34 @@ +// A simple TTreeReader use: read data from hsimple.root (written by hsimple.C) + +#include "TFile.h" +#include "TH1F.h" +#include "TTreeReader.h" +#include "TTreeReaderValue.h" + +void hsimpleReader() +{ + // Create a histogram for the values we read. + TH1F("h1", "ntuple", 100, -4, 4); + + // Open the file containing the tree. + TFile *myFile = TFile::Open("$ROOTSYS/tutorials/hsimple.root"); + + // Create a TTreeReader for the tree, for instance by passing the + // TTree's name and the TDirectory / TFile it is in. + TTreeReader myReader("ntuple", myFile); + + // The branch "px" contains floats; access them as myPx. + TTreeReaderValue<Float_t> myPx(myReader, "px"); + // The branch "py" contains floats, too; access those as myPy. + TTreeReaderValue<Float_t> myPy(myReader, "py"); + + // Loop over all entries of the TTree or TChain. + while (myReader.Next()) + { + // Just access the data as if myPx and myPy were iterators (note the '*' + // in front of them): + myHist->Fill(*myPx + *myPy); + } + + myHist->Draw(); +} \ No newline at end of file diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index efe31cee0..d14bae242 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -7,9 +7,9 @@ // Class definition #include "VariableDumperAlg.h" -// #include "tools/getBoostedHiggsCandidates.h" +#include "tools/getBoostedHiggsCandidates.h" // #include "tools/kLargestJets.h" - +#include "map" // // method implementations // @@ -20,10 +20,8 @@ namespace HH4B ISvcLocator *pSvcLocator) : AthHistogramAlgorithm(name, pSvcLocator), m_acc_DFCommonJets_eventClean_LooseBad( - "DFCommonJets_eventClean_LooseBad") m_acc_VRTrackJets - - SG::AuxElement::ConstAccessor<char> m_acc_VRTrackJets; - AntiKtVR30Rmax4Rmin02PV0TrackJets(DataVector<xAOD::Jet_v1>)[Jet] + "DFCommonJets_eventClean_LooseBad"), + m_acc_VRTrackJets("AntiKtVR30Rmax4Rmin02PV0TrackJets") { declareProperty("applyJetCleaning", m_applyJetCleaning); } @@ -46,6 +44,7 @@ namespace HH4B ATH_CHECK(m_btagSelTool.retrieve()); ATH_CHECK(m_EventInfoKey.initialize()); + ATH_CHECK(m_VRTrackJetsKey.initialize()); ATH_CHECK(m_systematicsList.initialize()); ATH_MSG_INFO("Will search \"" << m_EventInfoKey.key() @@ -63,7 +62,10 @@ namespace HH4B std::string sysname; ATH_CHECK(m_systematicsList.service().makeSystematicsName(sysname, "%SYS%", sys)); + ATH_MSG_INFO("Will apply sysname \"" << sysname << "\" for event"); + + // Do something with Eventinfo SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey); ATH_CHECK(eventInfo.isValid()); // jet cleaning @@ -90,15 +92,28 @@ namespace HH4B const xAOD::JetContainer *antiKt10RecoJets(nullptr); ATH_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); // do something with antiKt10RecoJets - const xAOD::JetContainer *antiKtVRRecoJets(nullptr); - ATH_CHECK(m_jetVRHandle.retrieve(antiKtVRRecoJets, sys)); - // do something with antiKt10RecoJets - ATH_MSG_DEBUG("Number of 0.4 jets in event " << antiKt4RecoJets->size()); - ATH_MSG_DEBUG("Number of 1.0 jets in event " - << antiKt10RecoJets->size()); + // get Variable Radius Track jets for large R jet substructure + SG::ReadHandle<xAOD::JetContainer> VRTrackJetsHandle(m_VRTrackJetsKey); + ATH_CHECK(VRTrackJetsHandle.isValid()); + // convert handle to container + const xAOD::JetContainer *VRTrackJets = VRTrackJetsHandle.cptr(); + + // set defaults + std::map<std::string, double> h_cand_vars; + h_cand_vars["m_h1"] = -1; + h_cand_vars["m_h2"] = -1; + h_cand_vars["m_hh"] = -1; + h_cand_vars["dR_jets_in_h1"] = -1; + h_cand_vars["dR_jets_in_h2"] = -1; + + getBoostedHiggsCandidates(antiKt10RecoJets, VRTrackJets, h_cand_vars); + + // recommended by ftag Remove the event if any of your signal jets have + // relativeDeltaRToVRJet < 1.0. + // getBoostedHiggsCandidates(antiKt10RecoJets); // std::cout << antiKt4RecoJets->size() << "\n"; - // std::cout << jetSmallBTag->size() << "\n"; + // std::cout << VRTrackJets->size() << "\n"; // for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) // { @@ -112,62 +127,58 @@ namespace HH4B // TODO: send in btagged jets // set defaults - eventInfo->auxdecor<double>("dR_jets_in_h1") = -1; - eventInfo->auxdecor<double>("dR_jets_in_h2") = -1; - eventInfo->auxdecor<double>("m_h1") = -1; - eventInfo->auxdecor<double>("m_h2") = -1; - eventInfo->auxdecor<double>("m_hh") = -1; - - // // check if we have 4 jets - // if (antiKt4RecoJets->size() < 4) - // { - // return StatusCode::SUCCESS; - // } - // // get indices of 4 largest pt jets - // std::vector<int> fourLargestPtJetsIndices = - // kLargestJets(antiKt4RecoJets, 4); - // const xAOD::Jet *largestPtJet = - // antiKt4RecoJets->at(fourLargestPtJetsIndices[0]); + // check if we have 4 jets + if (antiKt4RecoJets->size() < 4) + { + return StatusCode::SUCCESS; + } + // get indices of 4 largest pt jets + std::vector<int> fourLargestPtJetsIndices = + kLargestJets(antiKt4RecoJets, 4); + + const xAOD::Jet *largestPtJet = + antiKt4RecoJets->at(fourLargestPtJetsIndices[0]); - // // calc dR to other higgs candidate jets - // std::vector<double> dRtoLargestPtJet; - // for (int jetIndex : fourLargestPtJetsIndices) - // { - // const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); - // double thisDRtoLargestPtJet = - // thisJet->p4().DeltaR(largestPtJet->p4()); - // dRtoLargestPtJet.push_back(thisDRtoLargestPtJet); - // ATH_MSG_DEBUG(thisDRtoLargestPtJet); - // } + // calc dR to other higgs candidate jets + std::vector<double> dRtoLargestPtJet; + for (int jetIndex : fourLargestPtJetsIndices) + { + const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); + double thisDRtoLargestPtJet = thisJet->p4().DeltaR(largestPtJet->p4()); + dRtoLargestPtJet.push_back(thisDRtoLargestPtJet); + ATH_MSG_DEBUG(thisDRtoLargestPtJet); + } + + // get closest jet to leading jet + int closestToLeadingJetEntry = + std::min_element(dRtoLargestPtJet.begin(), dRtoLargestPtJet.end()) - + dRtoLargestPtJet.begin(); + const xAOD::Jet *closestToLeadingJet = antiKt4RecoJets->at( + fourLargestPtJetsIndices[closestToLeadingJetEntry]); + + // make higgs candidates + TLorentzVector h1_cand = largestPtJet->p4() + closestToLeadingJet->p4(); - // // get closest jet to leading jet - // int closestToLeadingJetEntry = - // std::min_element(dRtoLargestPtJet.begin(), dRtoLargestPtJet.end()) - // - dRtoLargestPtJet.begin(); - // const xAOD::Jet *closestToLeadingJet = antiKt4RecoJets->at( - // fourLargestPtJetsIndices[closestToLeadingJetEntry]); - - // // make higgs candidates - // TLorentzVector h1_cand = largestPtJet->p4() + - // closestToLeadingJet->p4(); double dR_jets_in_h1 = - // largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); - // // make a copy of the indices and delete the ones of the h1_cand - // // order matters! - // std::vector<int> otherJetIndices = fourLargestPtJetsIndices; - // otherJetIndices.erase(otherJetIndices.begin() + - // closestToLeadingJetEntry); - // otherJetIndices.erase(otherJetIndices.begin()); - - // const xAOD::Jet *otherJet1 = antiKt4RecoJets->at(otherJetIndices[0]); - // const xAOD::Jet *otherJet2 = antiKt4RecoJets->at(otherJetIndices[1]); - - // TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); - // double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); - - // double m_h1 = h1_cand.M(); - // double m_h2 = h2_cand.M(); - // double m_hh = (h1_cand + h2_cand).M(); + double dR_jets_in_h1 = + largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); + + // make a copy of the indices and delete the ones of the h1_cand + // order matters! + std::vector<int> otherJetIndices = fourLargestPtJetsIndices; + otherJetIndices.erase(otherJetIndices.begin() + + closestToLeadingJetEntry); + otherJetIndices.erase(otherJetIndices.begin()); + + const xAOD::Jet *otherJet1 = antiKt4RecoJets->at(otherJetIndices[0]); + const xAOD::Jet *otherJet2 = antiKt4RecoJets->at(otherJetIndices[1]); + + TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); + double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); + + double m_h1 = h1_cand.M(); + double m_h2 = h2_cand.M(); + double m_hh = (h1_cand + h2_cand).M(); // TODO: return resolved function as std::map "m_h1" @@ -181,16 +192,12 @@ namespace HH4B // std::cout << isTag77(*thisJet) << "\n"; // } - // recommended by ftag Remove the event if any of your signal jets have - // relativeDeltaRToVRJet < 1.0. - // getBoostedHiggsCandidates(antiKt10RecoJets); - // write out Higgs candidates - eventInfo->auxdecor<double>("m_h1") = m_h1; - eventInfo->auxdecor<double>("m_h2") = m_h2; - eventInfo->auxdecor<double>("m_hh") = m_hh; - eventInfo->auxdecor<double>("dR_jets_in_resolved_h1") = dR_jets_in_h1; - eventInfo->auxdecor<double>("dR_jets_in_resolved_h2") = dR_jets_in_h2; + // eventInfo->auxdecor<double>("m_h1") = m_h1; + // eventInfo->auxdecor<double>("m_h2") = m_h2; + // eventInfo->auxdecor<double>("m_hh") = m_hh; + // eventInfo->auxdecor<double>("dR_jets_in_resolved_h1") = dR_jets_in_h1; + // eventInfo->auxdecor<double>("dR_jets_in_resolved_h2") = dR_jets_in_h2; } return StatusCode::SUCCESS; diff --git a/HH4bAnalysis/src/VariableDumperAlg.h b/HH4bAnalysis/src/VariableDumperAlg.h index 80c818d94..0147f98b1 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.h +++ b/HH4bAnalysis/src/VariableDumperAlg.h @@ -53,13 +53,15 @@ private: // Member variables for configuration SG::ReadHandleKey<xAOD::EventInfo> m_EventInfoKey{ this, "EventInfoKey", "", "EventInfo container to dump"}; - + SG::ReadHandleKey<xAOD::JetContainer> m_VRTrackJetsKey{ + this, "VRTrackJetsKey", "", "VRTrackJets container to use"}; // for jet cleaning: quality criteria to identify events which are // consistent with noise in the calorimeter or non-collision background // For details last paragraph on page 6: // https://cds.cern.ch/record/2809414/files/ATLAS-COM-CONF-2022-035.pdf bool m_applyJetCleaning; SG::AuxElement::ConstAccessor<char> m_acc_DFCommonJets_eventClean_LooseBad; + SG::AuxElement::ConstAccessor<char> m_acc_VRTrackJets; CP::SysReadHandle<xAOD::ElectronContainer> m_electronHandle{ this, "electrons", "AnalysisElectrons_%SYS%", @@ -80,10 +82,6 @@ private: this, "jetlargeR", "AnalysisLargeRRecoJets_%SYS%", "the large-R jet collection to run on"}; - CP::SysReadHandle<xAOD::JetContainer> m_jetVRHandle{ - this, "jetVRR", "AnalysisVRRecoJets_%SYS%", - "the Variable radius jet collection to run on"}; - // output variables for the current event unsigned int m_runNumber = 0; unsigned long long m_eventNumber = 0; diff --git a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx index ebf42668a..32cf7ad86 100644 --- a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx +++ b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx @@ -6,11 +6,17 @@ #include "xAODJet/JetContainer.h" std::map<std::string, double> -getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets) +getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, + const xAOD::JetContainer *VRTrackJets, + std::map<std::string, double> h_cand_vars); { - std::map<std::string, double> h_cand_vars; - h_cand_vars["sun"] = 3; + // need two large R + // least pt of large R's 250 + // largest at least 450 + // eta < 2.0 + + // delta eta between large r jets std::vector<int> twoLargestPtJetsIndices = kLargestJets(largeRjets, 2); // need track jet container inside first and second diff --git a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h index f1a1b1996..3599290a4 100644 --- a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h +++ b/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h @@ -5,6 +5,8 @@ #include "xAODJet/JetContainer.h" std::map<std::string, double> -getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets); +getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, + const xAOD::JetContainer *VRTrackJets, + std::map<std::string, double> h_cand_vars); -#endif \ No newline at end of file +#endif -- GitLab From 18b195d092011830645fcd6516ea0384250d14b2 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Mon, 18 Jul 2022 09:23:42 +0200 Subject: [PATCH 04/33] saving --- ...iggsCandidates.cxx => BoostedAnalysis.cxx} | 6 +- ...tedHiggsCandidates.h => BoostedAnalysis.h} | 4 +- HH4bAnalysis/src/ResolvedAnalysis.cxx | 49 +++++++--------- HH4bAnalysis/src/ResolvedAnalysis.h | 12 ++++ HH4bAnalysis/src/VariableDumperAlg.cxx | 58 +------------------ 5 files changed, 43 insertions(+), 86 deletions(-) rename HH4bAnalysis/src/{tools/getBoostedHiggsCandidates.cxx => BoostedAnalysis.cxx} (79%) rename HH4bAnalysis/src/{tools/getBoostedHiggsCandidates.h => BoostedAnalysis.h} (74%) create mode 100644 HH4bAnalysis/src/ResolvedAnalysis.h diff --git a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx b/HH4bAnalysis/src/BoostedAnalysis.cxx similarity index 79% rename from HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx rename to HH4bAnalysis/src/BoostedAnalysis.cxx index 32cf7ad86..03fcbb0a1 100644 --- a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.cxx +++ b/HH4bAnalysis/src/BoostedAnalysis.cxx @@ -1,4 +1,4 @@ -#include "getBoostedHiggsCandidates.h" +#include "BoostedAnalysis.h" #include "kLargestJets.h" #include "map" // #include "vector" @@ -23,5 +23,9 @@ getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, // how to associate, until when are they still inside large R // tag them as b's + // recommended by ftag Remove the event if any of your signal jets have + // relativeDeltaRToVRJet < 1.0. + // getBoostedHiggsCandidates(antiKt10RecoJets); + return h_cand_vars; }; \ No newline at end of file diff --git a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h b/HH4bAnalysis/src/BoostedAnalysis.h similarity index 74% rename from HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h rename to HH4bAnalysis/src/BoostedAnalysis.h index 3599290a4..6738ea504 100644 --- a/HH4bAnalysis/src/tools/getBoostedHiggsCandidates.h +++ b/HH4bAnalysis/src/BoostedAnalysis.h @@ -1,5 +1,5 @@ -#ifndef HH4BANALYSIS_GET_BOOSTED_HIGGS_CANDIDATES -#define HH4BANALYSIS_GET_BOOSTED_HIGGS_CANDIDATES +#ifndef HH4BANALYSIS_BOOSTED_ANALYSIS +#define HH4BANALYSIS_BOOSTED_ANALYSIS #include "map" #include "xAODJet/JetContainer.h" diff --git a/HH4bAnalysis/src/ResolvedAnalysis.cxx b/HH4bAnalysis/src/ResolvedAnalysis.cxx index 7ad886b71..ce3256ab1 100644 --- a/HH4bAnalysis/src/ResolvedAnalysis.cxx +++ b/HH4bAnalysis/src/ResolvedAnalysis.cxx @@ -1,34 +1,27 @@ -// A simple TTreeReader use: read data from hsimple.root (written by hsimple.C) +#include "ResolvedAnalysis.h" +#include "kLargestJets.h" +#include "map" +// #include "vector" +#include "string" +#include "xAODJet/JetContainer.h" -#include "TFile.h" -#include "TH1F.h" -#include "TTreeReader.h" -#include "TTreeReaderValue.h" - -void hsimpleReader() +std::map<std::string, double> +getResolvedHiggsCandidates(const xAOD::JetContainer *largeRjets, + const xAOD::JetContainer *VRTrackJets, + std::map<std::string, double> h_cand_vars); { - // Create a histogram for the values we read. - TH1F("h1", "ntuple", 100, -4, 4); - - // Open the file containing the tree. - TFile *myFile = TFile::Open("$ROOTSYS/tutorials/hsimple.root"); - // Create a TTreeReader for the tree, for instance by passing the - // TTree's name and the TDirectory / TFile it is in. - TTreeReader myReader("ntuple", myFile); + // need two large R + // least pt of large R's 250 + // largest at least 450 + // eta < 2.0 - // The branch "px" contains floats; access them as myPx. - TTreeReaderValue<Float_t> myPx(myReader, "px"); - // The branch "py" contains floats, too; access those as myPy. - TTreeReaderValue<Float_t> myPy(myReader, "py"); + // delta eta between large r jets + std::vector<int> twoLargestPtJetsIndices = kLargestJets(largeRjets, 2); - // Loop over all entries of the TTree or TChain. - while (myReader.Next()) - { - // Just access the data as if myPx and myPy were iterators (note the '*' - // in front of them): - myHist->Fill(*myPx + *myPy); - } + // need track jet container inside first and second + // how to associate, until when are they still inside large R + // tag them as b's - myHist->Draw(); -} \ No newline at end of file + return h_cand_vars; +}; \ No newline at end of file diff --git a/HH4bAnalysis/src/ResolvedAnalysis.h b/HH4bAnalysis/src/ResolvedAnalysis.h new file mode 100644 index 000000000..d2376e0eb --- /dev/null +++ b/HH4bAnalysis/src/ResolvedAnalysis.h @@ -0,0 +1,12 @@ +#ifndef HH4BANALYSIS_BOOSTED_ANALYSIS +#define HH4BANALYSIS_BOOSTED_ANALYSIS + +#include "map" +#include "xAODJet/JetContainer.h" + +std::map<std::string, double> +getResolvedHiggsCandidates(const xAOD::JetContainer *largeRjets, + const xAOD::JetContainer *VRTrackJets, + std::map<std::string, double> h_cand_vars); + +#endif diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index d14bae242..894a43615 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -7,7 +7,7 @@ // Class definition #include "VariableDumperAlg.h" -#include "tools/getBoostedHiggsCandidates.h" +#include "getBoostedHiggsCandidates.h" // #include "tools/kLargestJets.h" #include "map" // @@ -106,7 +106,8 @@ namespace HH4B h_cand_vars["dR_jets_in_h1"] = -1; h_cand_vars["dR_jets_in_h2"] = -1; - getBoostedHiggsCandidates(antiKt10RecoJets, VRTrackJets, h_cand_vars); + h_cand_vars = getBoostedHiggsCandidates(antiKt10RecoJets, VRTrackJets, + h_cand_vars); // recommended by ftag Remove the event if any of your signal jets have // relativeDeltaRToVRJet < 1.0. @@ -126,59 +127,6 @@ namespace HH4B // } // TODO: send in btagged jets - // set defaults - - // check if we have 4 jets - if (antiKt4RecoJets->size() < 4) - { - return StatusCode::SUCCESS; - } - // get indices of 4 largest pt jets - std::vector<int> fourLargestPtJetsIndices = - kLargestJets(antiKt4RecoJets, 4); - - const xAOD::Jet *largestPtJet = - antiKt4RecoJets->at(fourLargestPtJetsIndices[0]); - - // calc dR to other higgs candidate jets - std::vector<double> dRtoLargestPtJet; - for (int jetIndex : fourLargestPtJetsIndices) - { - const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); - double thisDRtoLargestPtJet = thisJet->p4().DeltaR(largestPtJet->p4()); - dRtoLargestPtJet.push_back(thisDRtoLargestPtJet); - ATH_MSG_DEBUG(thisDRtoLargestPtJet); - } - - // get closest jet to leading jet - int closestToLeadingJetEntry = - std::min_element(dRtoLargestPtJet.begin(), dRtoLargestPtJet.end()) - - dRtoLargestPtJet.begin(); - const xAOD::Jet *closestToLeadingJet = antiKt4RecoJets->at( - fourLargestPtJetsIndices[closestToLeadingJetEntry]); - - // make higgs candidates - TLorentzVector h1_cand = largestPtJet->p4() + closestToLeadingJet->p4(); - - double dR_jets_in_h1 = - largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); - - // make a copy of the indices and delete the ones of the h1_cand - // order matters! - std::vector<int> otherJetIndices = fourLargestPtJetsIndices; - otherJetIndices.erase(otherJetIndices.begin() + - closestToLeadingJetEntry); - otherJetIndices.erase(otherJetIndices.begin()); - - const xAOD::Jet *otherJet1 = antiKt4RecoJets->at(otherJetIndices[0]); - const xAOD::Jet *otherJet2 = antiKt4RecoJets->at(otherJetIndices[1]); - - TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); - double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); - - double m_h1 = h1_cand.M(); - double m_h2 = h2_cand.M(); - double m_hh = (h1_cand + h2_cand).M(); // TODO: return resolved function as std::map "m_h1" -- GitLab From e5b38644bb93a4b6f36c961de0a846d0c3cefe55 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Tue, 19 Jul 2022 19:00:30 +0200 Subject: [PATCH 05/33] progress... --- HH4bAnalysis/share/VariableDumperConfig.py | 60 ++++++++++-- HH4bAnalysis/src/BoostedAnalysis.cxx | 93 ++++++++++++++++-- HH4bAnalysis/src/BoostedAnalysis.h | 1 - HH4bAnalysis/src/ResolvedAnalysis.cxx | 64 +++++++++--- HH4bAnalysis/src/ResolvedAnalysis.h | 9 +- HH4bAnalysis/src/VariableDumperAlg.cxx | 108 ++++++++------------- HH4bAnalysis/src/VariableDumperAlg.h | 11 +-- 7 files changed, 235 insertions(+), 111 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index d6f4115f5..5ceab230a 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -8,6 +8,8 @@ # Basic setup import sys +from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence +from AnaAlgorithm.DualUseConfig import createAlgorithm from AthenaCommon import Logging from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory @@ -230,14 +232,55 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): inputName=reco4JetContainerName, outputName="AnalysisJets_%SYS%", ) - # print(jetSequence) # For debugging + 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 + # Variable Radius jets Ftag sqeuence + VRSequence = AnaAlgSequence("VRTrackFTagAnalysisSequence") + # the following lines make a shallow copy, + # this isn't needed anymore with this MR + # https://gitlab.cern.ch/atlas/athena/-/merge_requests/54929 + alg = createAlgorithm("CP::AsgViewFromSelectionAlg", "VRJetSelectionAlg") + VRSequence.append( + alg, + inputPropName="input", + outputPropName="output", + stageName="selection", + dynConfig={}, + ) + VRftagSequence = makeFTagAnalysisSequence( + VRSequence, + dataType, + "AntiKtVR30Rmax4Rmin02TrackJets", + btagWP="FixedCutBEff_77", + btagger="DL1r", + postfix="VR", + preselection=None, + kinematicSelection=True, + noEfficiency=False, + legacyRecommendations=False, + enableCutflow=False, + minPt=20000, + ) + + for ftagAlg in VRftagSequence: + if "FTagSelectionAlg" in ftagAlg.getName(): + ftagAlg.selectionTool.FlvTagCutDefinitionsFileName = bTagCalibFile + if "FTagEfficiencyScaleFactorAlg" in ftagAlg.getName(): + ftagAlg.efficiencyTool.ScaleFactorFileName = bTagCalibFile + + VRSequence.configure( + inputName=recoVRJetContainerName, outputName="VRTrackJetsBTAG_%SYS%" + ) + + VRjetSequenceCnv, VRjetAlgsCnv = convertSequenceAndGetAlgs(CompFactory, VRSequence) + cfg.addSequence(VRjetSequenceCnv) + for VRjetAlg in VRjetAlgsCnv: + cfg.addEventAlgo(VRjetAlg, VRjetSequenceCnv.getName()) largeRrecojetSequence = makeJetAnalysisSequence( dataType, @@ -318,9 +361,8 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): CompFactory.HH4B.VariableDumperAlg( "VariableDumper", EventInfoKey="EventInfo", - VRTrackJetsKey=recoVRJetContainerName, RootStreamName="ANALYSIS", - applyJetCleaning=True, + # btag_wps=btag_wps, ) ) @@ -338,11 +380,6 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): # we currently don't have any pileup calib files setup # 'EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%', "EventInfo.mcEventWeights -> mcEventWeights", - "EventInfo.m_h1 -> m_h1", - "EventInfo.m_h2 -> m_h2", - "EventInfo.m_hh -> m_hh", - "EventInfo.dR_jets_in_h1 -> dR_jets_in_h1", - "EventInfo.dR_jets_in_h2 -> dR_jets_in_h2", "AnalysisElectrons_%SYS%.pt -> el_%SYS%_pt", "AnalysisElectrons_%SYS%.eta -> el_%SYS%_eta", "AnalysisElectrons_%SYS%.phi -> el_%SYS%_phi", @@ -377,6 +414,11 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): "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.resolved_m_h1 -> resolved_m_h1", + "EventInfo.resolved_m_h2 -> resolved_m_h2", + "EventInfo.resolved_m_hh -> resolved_m_hh", + "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", + "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", ] ntupleMaker.Branches += [ f"AnalysisJets_%SYS%.ftag_select_{btag_wp} -> recojet_antikt4_%SYS%_{btag_wp}" diff --git a/HH4bAnalysis/src/BoostedAnalysis.cxx b/HH4bAnalysis/src/BoostedAnalysis.cxx index 03fcbb0a1..3f1016e03 100644 --- a/HH4bAnalysis/src/BoostedAnalysis.cxx +++ b/HH4bAnalysis/src/BoostedAnalysis.cxx @@ -1,23 +1,26 @@ #include "BoostedAnalysis.h" -#include "kLargestJets.h" #include "map" -// #include "vector" #include "string" +#include "tools/kLargestJets.h" #include "xAODJet/JetContainer.h" std::map<std::string, double> getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, - const xAOD::JetContainer *VRTrackJets, - std::map<std::string, double> h_cand_vars); + std::map<std::string, double> h_cand_vars) { - // need two large R // least pt of large R's 250 // largest at least 450 // eta < 2.0 // delta eta between large r jets - std::vector<int> twoLargestPtJetsIndices = kLargestJets(largeRjets, 2); + + // check if we have at least 2 large R jets + if (largeRjets->size() < 2) + { + return h_cand_vars; + } + std::vector<int> twoLeadingPtJetsIndices = kLargestJets(largeRjets, 2); // need track jet container inside first and second // how to associate, until when are they still inside large R @@ -25,7 +28,83 @@ getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, // recommended by ftag Remove the event if any of your signal jets have // relativeDeltaRToVRJet < 1.0. - // getBoostedHiggsCandidates(antiKt10RecoJets); + + // ghost associated track jets are only on the untrimmed 1.0 jets + SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> + m_acc_largeR_untrimmed("Parent"); + SG::AuxElement::ConstAccessor< + std::vector<ElementLink<xAOD::IParticleContainer>>> + m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); + + SG::AuxElement::ConstAccessor<char> isBtag( + "ftag_select_DL1r_FixedCutBEff_77"); + std::vector<std::vector<ElementLink<xAOD::IParticleContainer>>> + btagged_VRTrackjets; + // loop over the two large R jets + for (int i : twoLeadingPtJetsIndices) + { + const xAOD::Jet *thisJet = largeRjets->at(i); + // get ghost associated VR track jets + const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); + const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = + m_acc_VRTrackJets(*thisJet_untrimmed); + // get the btagged VR trackjets per large R jet + for (auto VRjet : VRTrackjets) + { + if (isBtag(**VRjet)) + { + // (i is the large R jet index not a counter) + btagged_VRTrackjets[i].emplace_back(VRjet); + } + } + // check if we have at least 2 per large R jet, otherwise exit + // (subject to change) + if (btagged_VRTrackjets[i].size() < 2) + { + return h_cand_vars; + } + } + // // make higgs candidates + // TLorentzVector h1_cand = largestPtJet->p4() + closestToLeadingJet->p4(); + // double dR_jets_in_h1 = + // largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); + + // // make a copy of the indices and delete the ones of the h1_cand to get + // the + // // ones of the h2_cand, order matters! + // std::vector<int> otherJetIndices = fourLargestPtJetsIndices; + // otherJetIndices.erase(otherJetIndices.begin() + closestToLeadingJetEntry); + // otherJetIndices.erase(otherJetIndices.begin()); + + // const xAOD::Jet *otherJet1 = smallRjets->at(otherJetIndices[0]); + // const xAOD::Jet *otherJet2 = smallRjets->at(otherJetIndices[1]); + + // TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); + // double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); + + // // write to dictionary + // h_cand_vars["resolved_m_h1"] = h1_cand.M(); + // h_cand_vars["resolved_m_h2"] = h2_cand.M(); + // h_cand_vars["resolved_m_hh"] = (h1_cand + h2_cand).M(); + // h_cand_vars["resolved_dR_jets_in_h1"] = dR_jets_in_h1; + // h_cand_vars["resolved_dR_jets_in_h2"] = dR_jets_in_h2; + + // const xAOD::Jet *thisJet; + + // SG::AuxElement::ConstAccessor<char> isTag77( + + // GhostVR30Rmax4Rmin02PV0TrackJet + // SG::AuxElement::ConstAccessor<char> isTag77( + // "ftag_select_DL1r_FixedCutBEff_77"); + // for (long unsigned int i = 0; i < VRTrackJets->size(); i++) + // { + // thisJet = VRTrackJets->at(i); + // std::cout << int(isTag77(*thisJet)) << std::endl; + // } + + // bool pass_btag = false; + // if (isTag77.isAvailable(*jet)) + // VRtrackjet_btag77.push_back(isTag77(*jet)); return h_cand_vars; }; \ No newline at end of file diff --git a/HH4bAnalysis/src/BoostedAnalysis.h b/HH4bAnalysis/src/BoostedAnalysis.h index 6738ea504..2efad7b90 100644 --- a/HH4bAnalysis/src/BoostedAnalysis.h +++ b/HH4bAnalysis/src/BoostedAnalysis.h @@ -6,7 +6,6 @@ std::map<std::string, double> getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, - const xAOD::JetContainer *VRTrackJets, std::map<std::string, double> h_cand_vars); #endif diff --git a/HH4bAnalysis/src/ResolvedAnalysis.cxx b/HH4bAnalysis/src/ResolvedAnalysis.cxx index ce3256ab1..b590e8e8e 100644 --- a/HH4bAnalysis/src/ResolvedAnalysis.cxx +++ b/HH4bAnalysis/src/ResolvedAnalysis.cxx @@ -1,27 +1,61 @@ #include "ResolvedAnalysis.h" -#include "kLargestJets.h" #include "map" -// #include "vector" -#include "string" +#include "tools/kLargestJets.h" #include "xAODJet/JetContainer.h" std::map<std::string, double> -getResolvedHiggsCandidates(const xAOD::JetContainer *largeRjets, - const xAOD::JetContainer *VRTrackJets, - std::map<std::string, double> h_cand_vars); +getResolvedHiggsCandidates(const xAOD::JetContainer *smallRjets, + std::map<std::string, double> &h_cand_vars) { + // check if we have at least 4 jets + if (smallRjets->size() < 4) + { + return h_cand_vars; + } + // get indices of 4 largest pt jets + // need to do this because sequence filtering destroys order + std::vector<int> fourLeadingPtJetsIndices = kLargestJets(smallRjets, 4); + // get largest pt jet + const xAOD::Jet *largestPtJet = smallRjets->at(fourLeadingPtJetsIndices[0]); - // need two large R - // least pt of large R's 250 - // largest at least 450 - // eta < 2.0 + // calculate dR to other higgs candidate jets + std::vector<double> dRtoLargestPtJet; + for (int jetIndex : fourLeadingPtJetsIndices) + { + const xAOD::Jet *thisJet = smallRjets->at(jetIndex); + double thisDRtoLargestPtJet = thisJet->p4().DeltaR(largestPtJet->p4()); + dRtoLargestPtJet.push_back(thisDRtoLargestPtJet); + } - // delta eta between large r jets - std::vector<int> twoLargestPtJetsIndices = kLargestJets(largeRjets, 2); + // get closest jet to leading jet + int closestToLeadingJetEntry = + std::min_element(dRtoLargestPtJet.begin(), dRtoLargestPtJet.end()) - + dRtoLargestPtJet.begin(); + const xAOD::Jet *closestToLeadingJet = + smallRjets->at(fourLeadingPtJetsIndices[closestToLeadingJetEntry]); - // need track jet container inside first and second - // how to associate, until when are they still inside large R - // tag them as b's + // make higgs candidates + TLorentzVector h1_cand = largestPtJet->p4() + closestToLeadingJet->p4(); + double dR_jets_in_h1 = largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); + + // make a copy of the indices and delete the ones of the h1_cand to get the + // ones of the h2_cand, order matters! + std::vector<int> otherJetIndices = fourLeadingPtJetsIndices; + otherJetIndices.erase(otherJetIndices.begin() + closestToLeadingJetEntry); + otherJetIndices.erase(otherJetIndices.begin()); + + const xAOD::Jet *otherJet1 = smallRjets->at(otherJetIndices[0]); + const xAOD::Jet *otherJet2 = smallRjets->at(otherJetIndices[1]); + + TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); + double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); + + // write to dictionary + h_cand_vars["resolved_m_h1"] = h1_cand.M(); + h_cand_vars["resolved_m_h2"] = h2_cand.M(); + h_cand_vars["resolved_m_hh"] = (h1_cand + h2_cand).M(); + h_cand_vars["resolved_dR_jets_in_h1"] = dR_jets_in_h1; + h_cand_vars["resolved_dR_jets_in_h2"] = dR_jets_in_h2; return h_cand_vars; }; \ No newline at end of file diff --git a/HH4bAnalysis/src/ResolvedAnalysis.h b/HH4bAnalysis/src/ResolvedAnalysis.h index d2376e0eb..d9d38b545 100644 --- a/HH4bAnalysis/src/ResolvedAnalysis.h +++ b/HH4bAnalysis/src/ResolvedAnalysis.h @@ -1,12 +1,11 @@ -#ifndef HH4BANALYSIS_BOOSTED_ANALYSIS -#define HH4BANALYSIS_BOOSTED_ANALYSIS +#ifndef HH4BANALYSIS_RESOLVED_ANALYSIS +#define HH4BANALYSIS_RESOLVED_ANALYSIS #include "map" #include "xAODJet/JetContainer.h" std::map<std::string, double> -getResolvedHiggsCandidates(const xAOD::JetContainer *largeRjets, - const xAOD::JetContainer *VRTrackJets, - std::map<std::string, double> h_cand_vars); +getResolvedHiggsCandidates(const xAOD::JetContainer *smallRjets, + std::map<std::string, double> &h_cand_vars); #endif diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 894a43615..957379cf0 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -7,8 +7,8 @@ // Class definition #include "VariableDumperAlg.h" -#include "getBoostedHiggsCandidates.h" -// #include "tools/kLargestJets.h" +#include "BoostedAnalysis.h" +#include "ResolvedAnalysis.h" #include "map" // // method implementations @@ -18,12 +18,8 @@ namespace HH4B { VariableDumperAlg ::VariableDumperAlg(const std::string &name, ISvcLocator *pSvcLocator) - : AthHistogramAlgorithm(name, pSvcLocator), - m_acc_DFCommonJets_eventClean_LooseBad( - "DFCommonJets_eventClean_LooseBad"), - m_acc_VRTrackJets("AntiKtVR30Rmax4Rmin02PV0TrackJets") + : AthHistogramAlgorithm(name, pSvcLocator) { - declareProperty("applyJetCleaning", m_applyJetCleaning); } StatusCode VariableDumperAlg ::initialize() @@ -41,10 +37,8 @@ namespace HH4B ATH_CHECK(m_systematicsList.addHandle(m_muonHandle)); ATH_CHECK(m_systematicsList.addHandle(m_jetsmallRHandle)); ATH_CHECK(m_systematicsList.addHandle(m_jetlargeRHandle)); - ATH_CHECK(m_btagSelTool.retrieve()); - + ATH_CHECK(m_systematicsList.addHandle(m_VRtrackjetHandle)); ATH_CHECK(m_EventInfoKey.initialize()); - ATH_CHECK(m_VRTrackJetsKey.initialize()); ATH_CHECK(m_systematicsList.initialize()); ATH_MSG_INFO("Will search \"" << m_EventInfoKey.key() @@ -69,13 +63,13 @@ namespace HH4B SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey); ATH_CHECK(eventInfo.isValid()); // jet cleaning - if (m_applyJetCleaning) - { - if (!m_acc_DFCommonJets_eventClean_LooseBad(*eventInfo)) - { - return StatusCode::SUCCESS; // go to next event - } - } + // if (m_applyJetCleaning) + // { + // if (!m_acc_DFCommonJets_eventClean_LooseBad(*eventInfo)) + // { + // return StatusCode::SUCCESS; // go to next event + // } + // } const xAOD::ElectronContainer *electrons(nullptr); ATH_CHECK(m_electronHandle.retrieve(electrons, sys)); @@ -92,60 +86,38 @@ namespace HH4B const xAOD::JetContainer *antiKt10RecoJets(nullptr); ATH_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); // do something with antiKt10RecoJets - // get Variable Radius Track jets for large R jet substructure - SG::ReadHandle<xAOD::JetContainer> VRTrackJetsHandle(m_VRTrackJetsKey); - ATH_CHECK(VRTrackJetsHandle.isValid()); - // convert handle to container - const xAOD::JetContainer *VRTrackJets = VRTrackJetsHandle.cptr(); - - // set defaults + const xAOD::JetContainer *VRTrackJets(nullptr); + ATH_CHECK(m_VRtrackjetHandle.retrieve(VRTrackJets, sys)); + // do something with VRTrackJets + + // variable list + // TODO: need to find way to initialize all the v + std::vector<std::string> h_cand_vars_list({ + "resolved_m_h1", + "resolved_m_h2", + "resolved_m_hh", + "resolved_dR_jets_in_h1", + "resolved_dR_jets_in_h2", + }); + + // set defaults in h_cand_vars dictionary std::map<std::string, double> h_cand_vars; - h_cand_vars["m_h1"] = -1; - h_cand_vars["m_h2"] = -1; - h_cand_vars["m_hh"] = -1; - h_cand_vars["dR_jets_in_h1"] = -1; - h_cand_vars["dR_jets_in_h2"] = -1; - - h_cand_vars = getBoostedHiggsCandidates(antiKt10RecoJets, VRTrackJets, - h_cand_vars); - - // recommended by ftag Remove the event if any of your signal jets have - // relativeDeltaRToVRJet < 1.0. - // getBoostedHiggsCandidates(antiKt10RecoJets); - - // std::cout << antiKt4RecoJets->size() << "\n"; - // std::cout << VRTrackJets->size() << "\n"; - - // for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) - // { - // const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); - // // std::cout << jetIndex; - // // std::cout << antiKt4RecoJets->size(); - // SG::AuxElement::ConstAccessor<char> isTag77( - // "ftag_kin_select_DL1r_FixedCutBEff_77"); - // std::cout << isTag77(*thisJet) << "\n"; - // } - - // TODO: send in btagged jets - - // TODO: return resolved function as std::map "m_h1" + for (std::string var : h_cand_vars_list) + { + h_cand_vars[var] = -1; + } - // for (int jetIndex = 0; jetIndex < antiKt4RecoJets->size(); jetIndex++) - // { - // const xAOD::Jet *thisJet = antiKt4RecoJets->at(jetIndex); - // // std::cout << jetIndex; - // // std::cout << antiKt4RecoJets->size(); - // SG::AuxElement::ConstAccessor<char> isTag77( - // "ftag_kin_select_DL1r_FixedCutBEff_77"); - // std::cout << isTag77(*thisJet) << "\n"; - // } + // TODO: make configurable with which btagging WP Higgs candidates are + // created + // std::vector<std::string> + h_cand_vars = getResolvedHiggsCandidates(antiKt4RecoJets, h_cand_vars); + h_cand_vars = getBoostedHiggsCandidates(antiKt10RecoJets, h_cand_vars); - // write out Higgs candidates - // eventInfo->auxdecor<double>("m_h1") = m_h1; - // eventInfo->auxdecor<double>("m_h2") = m_h2; - // eventInfo->auxdecor<double>("m_hh") = m_hh; - // eventInfo->auxdecor<double>("dR_jets_in_resolved_h1") = dR_jets_in_h1; - // eventInfo->auxdecor<double>("dR_jets_in_resolved_h2") = dR_jets_in_h2; + // decorate eventInfo with Higgs candidates + for (std::string var : h_cand_vars_list) + { + eventInfo->auxdecor<double>(var) = h_cand_vars[var]; + } } return StatusCode::SUCCESS; diff --git a/HH4bAnalysis/src/VariableDumperAlg.h b/HH4bAnalysis/src/VariableDumperAlg.h index e47da448e..a06415b3e 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.h +++ b/HH4bAnalysis/src/VariableDumperAlg.h @@ -50,16 +50,11 @@ private: // Member variables for configuration SG::ReadHandleKey<xAOD::EventInfo> m_EventInfoKey{ this, "EventInfoKey", "", "EventInfo container to dump"}; - SG::ReadHandleKey<xAOD::JetContainer> m_VRTrackJetsKey{ - this, "VRTrackJetsKey", "", "VRTrackJets container to use"}; + // TODO: jet cleaning will become of own selection/filter algorithm // for jet cleaning: quality criteria to identify events which are // consistent with noise in the calorimeter or non-collision background // For details last paragraph on page 6: // https://cds.cern.ch/record/2809414/files/ATLAS-COM-CONF-2022-035.pdf - bool m_applyJetCleaning; - SG::AuxElement::ConstAccessor<char> m_acc_DFCommonJets_eventClean_LooseBad; - SG::AuxElement::ConstAccessor<char> m_acc_VRTrackJets; - CP::SysReadHandle<xAOD::ElectronContainer> m_electronHandle{ this, "electrons", "AnalysisElectrons_%SYS%", "the electron collection to run on"}; @@ -78,6 +73,10 @@ private: CP::SysReadHandle<xAOD::JetContainer> m_jetlargeRHandle{ this, "jetlargeR", "AnalysisLargeRRecoJets_%SYS%", "the large-R jet collection to run on"}; + + CP::SysReadHandle<xAOD::JetContainer> m_VRtrackjetHandle{ + this, "VRtrackjets", "VRTrackJetsBTAG_%SYS%", + "the VR track jet collection to run on"}; }; } -- GitLab From c123c0c5051b33fd3be1eb361a1b88c65eded48e Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 21 Jul 2022 10:12:54 +0200 Subject: [PATCH 06/33] proof of principle --- HH4bAnalysis/share/VariableDumperConfig.py | 5 + HH4bAnalysis/src/BoostedAnalysis.cxx | 128 ++++++++++++--------- HH4bAnalysis/src/VariableDumperAlg.cxx | 6 +- HH4bAnalysis/src/tools/kLargestJets.cxx | 2 +- 4 files changed, 84 insertions(+), 57 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 5ceab230a..b1b9a94cc 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -419,6 +419,11 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): "EventInfo.resolved_m_hh -> resolved_m_hh", "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", + "EventInfo.boosted_m_h1 -> boosted_m_h1", + "EventInfo.boosted_m_h2 -> boosted_m_h2", + "EventInfo.boosted_m_hh -> boosted_m_hh", + "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", + "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", ] ntupleMaker.Branches += [ f"AnalysisJets_%SYS%.ftag_select_{btag_wp} -> recojet_antikt4_%SYS%_{btag_wp}" diff --git a/HH4bAnalysis/src/BoostedAnalysis.cxx b/HH4bAnalysis/src/BoostedAnalysis.cxx index 3f1016e03..3ed325d2c 100644 --- a/HH4bAnalysis/src/BoostedAnalysis.cxx +++ b/HH4bAnalysis/src/BoostedAnalysis.cxx @@ -3,31 +3,35 @@ #include "string" #include "tools/kLargestJets.h" #include "xAODJet/JetContainer.h" +#include <AthContainers/ConstDataVector.h> + +// struct higgs_cand +// { +// int largeRjetIndex; +// } std::map<std::string, double> getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, std::map<std::string, double> h_cand_vars) { + // TODO: list + // cuts + // recommended by ftag : Remove the event if any of your signal jets have + // relativeDeltaRToVRJet < 1.0. // least pt of large R's 250 // largest at least 450 // eta < 2.0 // delta eta between large r jets + // make btagging configurable // check if we have at least 2 large R jets if (largeRjets->size() < 2) { return h_cand_vars; } - std::vector<int> twoLeadingPtJetsIndices = kLargestJets(largeRjets, 2); - - // need track jet container inside first and second - // how to associate, until when are they still inside large R - // tag them as b's - - // recommended by ftag Remove the event if any of your signal jets have - // relativeDeltaRToVRJet < 1.0. + std::vector<int> twoLeadingPtLargeRjetsIndices = kLargestJets(largeRjets, 2); // ghost associated track jets are only on the untrimmed 1.0 jets SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> @@ -35,21 +39,29 @@ getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, SG::AuxElement::ConstAccessor< std::vector<ElementLink<xAOD::IParticleContainer>>> m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); - SG::AuxElement::ConstAccessor<char> isBtag( "ftag_select_DL1r_FixedCutBEff_77"); + + // need to allocate size of this to work with the + // twoLeadingPtLargeRjetsIndices + int allocation_size = *max_element(twoLeadingPtLargeRjetsIndices.begin(), + twoLeadingPtLargeRjetsIndices.end()) + + 1; std::vector<std::vector<ElementLink<xAOD::IParticleContainer>>> - btagged_VRTrackjets; - // loop over the two large R jets - for (int i : twoLeadingPtJetsIndices) + btagged_VRTrackjets(allocation_size); + + // loop over the two large R jets to get the btagged VR jets inside of each + // (i is the large R jet index not a counter) + for (int i : twoLeadingPtLargeRjetsIndices) { + const xAOD::Jet *thisJet = largeRjets->at(i); - // get ghost associated VR track jets + // get ghost associated VR track jets from untrimmed large R const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = m_acc_VRTrackJets(*thisJet_untrimmed); // get the btagged VR trackjets per large R jet - for (auto VRjet : VRTrackjets) + for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) { if (isBtag(**VRjet)) { @@ -57,54 +69,60 @@ getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, btagged_VRTrackjets[i].emplace_back(VRjet); } } + } + + // get leading pt jets of btagged VRtrackJets in largeRjet i + // e.g. h_cand_indices[twoLeadingPtLargeRjetsIndices[0]] contains pt-sorted + // VRtrackjet indices for the leading (twoLeadingPtLargeRjetsIndices[0]) + // largeRjet + + std::vector<std::vector<int>> h_cand_indices(allocation_size); + for (int i : twoLeadingPtLargeRjetsIndices) + { // check if we have at least 2 per large R jet, otherwise exit // (subject to change) if (btagged_VRTrackjets[i].size() < 2) { return h_cand_vars; } + + ConstDataVector<xAOD::JetContainer> tmpVRjets(SG::VIEW_ELEMENTS); + // cast VRjet to xAOD::jet to use kLargestJets sorting function + // we do it this way since we want to make shallow copies + // tmpVRjets is recreated per i + for (auto VRjet : btagged_VRTrackjets[i]) + { + const auto *jet = dynamic_cast<const xAOD::Jet *>(*VRjet); + tmpVRjets.push_back(jet); + } + + h_cand_indices[i] = kLargestJets(tmpVRjets.asDataVector(), 2); } - // // make higgs candidates - // TLorentzVector h1_cand = largestPtJet->p4() + closestToLeadingJet->p4(); - // double dR_jets_in_h1 = - // largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); - - // // make a copy of the indices and delete the ones of the h1_cand to get - // the - // // ones of the h2_cand, order matters! - // std::vector<int> otherJetIndices = fourLargestPtJetsIndices; - // otherJetIndices.erase(otherJetIndices.begin() + closestToLeadingJetEntry); - // otherJetIndices.erase(otherJetIndices.begin()); - - // const xAOD::Jet *otherJet1 = smallRjets->at(otherJetIndices[0]); - // const xAOD::Jet *otherJet2 = smallRjets->at(otherJetIndices[1]); - - // TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); - // double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); - - // // write to dictionary - // h_cand_vars["resolved_m_h1"] = h1_cand.M(); - // h_cand_vars["resolved_m_h2"] = h2_cand.M(); - // h_cand_vars["resolved_m_hh"] = (h1_cand + h2_cand).M(); - // h_cand_vars["resolved_dR_jets_in_h1"] = dR_jets_in_h1; - // h_cand_vars["resolved_dR_jets_in_h2"] = dR_jets_in_h2; - - // const xAOD::Jet *thisJet; - - // SG::AuxElement::ConstAccessor<char> isTag77( - - // GhostVR30Rmax4Rmin02PV0TrackJet - // SG::AuxElement::ConstAccessor<char> isTag77( - // "ftag_select_DL1r_FixedCutBEff_77"); - // for (long unsigned int i = 0; i < VRTrackJets->size(); i++) - // { - // thisJet = VRTrackJets->at(i); - // std::cout << int(isTag77(*thisJet)) << std::endl; - // } - - // bool pass_btag = false; - // if (isTag77.isAvailable(*jet)) - // VRtrackjet_btag77.push_back(isTag77(*jet)); + + // make higgs candidates + + std::vector<TLorentzVector> h_cand(allocation_size); + std::vector<double> dR_jets_in_h_cand(allocation_size); + + for (int i : twoLeadingPtLargeRjetsIndices) + { + auto leadingVR_h_cand = *btagged_VRTrackjets[i][h_cand_indices[i][0]]; + auto subleadingVR_h_cand = *btagged_VRTrackjets[i][h_cand_indices[i][1]]; + h_cand[i] = leadingVR_h_cand->p4() + subleadingVR_h_cand->p4(); + dR_jets_in_h_cand[i] = + leadingVR_h_cand->p4().DeltaR(subleadingVR_h_cand->p4()); + } + + // write to dictionary + auto h1_cand = h_cand[twoLeadingPtLargeRjetsIndices[0]]; + auto h2_cand = h_cand[twoLeadingPtLargeRjetsIndices[1]]; + h_cand_vars["boosted_m_h1"] = h1_cand.M(); + h_cand_vars["boosted_m_h2"] = h2_cand.M(); + h_cand_vars["boosted_m_hh"] = (h1_cand + h2_cand).M(); + h_cand_vars["boosted_dR_jets_in_h1"] = + dR_jets_in_h_cand[twoLeadingPtLargeRjetsIndices[0]]; + h_cand_vars["boosted_dR_jets_in_h2"] = + dR_jets_in_h_cand[twoLeadingPtLargeRjetsIndices[1]]; return h_cand_vars; }; \ No newline at end of file diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 957379cf0..d4476ac56 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -91,13 +91,17 @@ namespace HH4B // do something with VRTrackJets // variable list - // TODO: need to find way to initialize all the v std::vector<std::string> h_cand_vars_list({ "resolved_m_h1", "resolved_m_h2", "resolved_m_hh", "resolved_dR_jets_in_h1", "resolved_dR_jets_in_h2", + "boosted_m_h1", + "boosted_m_h2", + "boosted_m_hh", + "boosted_dR_jets_in_h1", + "boosted_dR_jets_in_h2", }); // set defaults in h_cand_vars dictionary diff --git a/HH4bAnalysis/src/tools/kLargestJets.cxx b/HH4bAnalysis/src/tools/kLargestJets.cxx index 06a7dcb84..b2d21cddd 100644 --- a/HH4bAnalysis/src/tools/kLargestJets.cxx +++ b/HH4bAnalysis/src/tools/kLargestJets.cxx @@ -2,7 +2,7 @@ #include "xAODJet/JetContainer.h" // efficient algorithm to find k largest elements in size n vector with -// efficienvy O(n log k) +// efficiency O(n log k) // see https://stackoverflow.com/a/38391603 // returns jet indices in descending order of the largest k found pt's -- GitLab From ee510fe844502d965ec4a3815ef664fc7d91b56a Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Mon, 8 Aug 2022 08:22:48 +0200 Subject: [PATCH 07/33] saving --- HH4bAnalysis/src/BoostedAnalysis.cxx | 25 ++++++++++++++++++++++--- HH4bAnalysis/src/VariableDumperAlg.cxx | 3 ++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/HH4bAnalysis/src/BoostedAnalysis.cxx b/HH4bAnalysis/src/BoostedAnalysis.cxx index 3ed325d2c..4ca76d571 100644 --- a/HH4bAnalysis/src/BoostedAnalysis.cxx +++ b/HH4bAnalysis/src/BoostedAnalysis.cxx @@ -3,8 +3,11 @@ #include "string" #include "tools/kLargestJets.h" #include "xAODJet/JetContainer.h" +#include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> +using namespace asg::msgUserCode; + // struct higgs_cand // { // int largeRjetIndex; @@ -61,13 +64,29 @@ getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = m_acc_VRTrackJets(*thisJet_untrimmed); // get the btagged VR trackjets per large R jet + int counter = 0; for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) { - if (isBtag(**VRjet)) + auto &test = VRjet; + // check if VRjet link is valid + // should we handle this differently? + if (!test.isValid()) + { + // doing this gives a lot of warnings, wonder why + // ANA_MSG_WARNING("Invalid track link found!"); + std::cout << "size " << VRTrackjets.size() << "count " << counter + 1; + continue; + } + // some (very little) of the VR jets are not btagged, this means the + // VRtrack ftag sequence does not tag some of them + if (!isBtag.isAvailable(**VRjet)) { - // (i is the large R jet index not a counter) - btagged_VRTrackjets[i].emplace_back(VRjet); + ANA_MSG_WARNING("Skipped non B-tagged VR jet"); + continue; } + + // (i is the large R jet index not a counter) + btagged_VRTrackjets[i].emplace_back(VRjet); } } diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index d4476ac56..9d55c1a98 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -57,7 +57,8 @@ namespace HH4B ATH_CHECK(m_systematicsList.service().makeSystematicsName(sysname, "%SYS%", sys)); - ATH_MSG_INFO("Will apply sysname \"" << sysname << "\" for event"); + // ATH_MSG_INFO("Will apply sysname \"" << sysname << "\" for event"); + ATH_MSG_WARNING("Invalid track link found!"); // Do something with Eventinfo SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey); -- GitLab From e45a85765f214cf7c92142aae20ced9bb06c0c28 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Wed, 10 Aug 2022 08:57:49 +0200 Subject: [PATCH 08/33] make object oriented --- HH4bAnalysis/share/VariableDumperConfig.py | 2 +- HH4bAnalysis/src/BoostedAnalysis.cxx | 5 - HH4bAnalysis/src/DiHiggsAnalysis.cxx | 136 +++++++++++++++++++++ HH4bAnalysis/src/DiHiggsAnalysis.h | 44 +++++++ HH4bAnalysis/src/VariableDumperAlg.cxx | 46 ++----- 5 files changed, 188 insertions(+), 45 deletions(-) create mode 100644 HH4bAnalysis/src/DiHiggsAnalysis.cxx create mode 100644 HH4bAnalysis/src/DiHiggsAnalysis.h diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index b1b9a94cc..392fdb43a 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -379,7 +379,7 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): "EventInfo.eventNumber -> eventNumber", # we currently don't have any pileup calib files setup # 'EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%', - "EventInfo.mcEventWeights -> mcEventWeights", + # "EventInfo.mcEventWeights -> mcEventWeights", "AnalysisElectrons_%SYS%.pt -> el_%SYS%_pt", "AnalysisElectrons_%SYS%.eta -> el_%SYS%_eta", "AnalysisElectrons_%SYS%.phi -> el_%SYS%_phi", diff --git a/HH4bAnalysis/src/BoostedAnalysis.cxx b/HH4bAnalysis/src/BoostedAnalysis.cxx index 4ca76d571..75ad5a28c 100644 --- a/HH4bAnalysis/src/BoostedAnalysis.cxx +++ b/HH4bAnalysis/src/BoostedAnalysis.cxx @@ -8,11 +8,6 @@ using namespace asg::msgUserCode; -// struct higgs_cand -// { -// int largeRjetIndex; -// } - std::map<std::string, double> getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, std::map<std::string, double> h_cand_vars) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx new file mode 100644 index 000000000..84d4bdc06 --- /dev/null +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -0,0 +1,136 @@ + +#include "DiHiggsAnalysis.h" +#include "tools/kLargestJets.h" +#include "xAODJet/JetContainer.h" +#include <AsgMessaging/MessageCheck.h> +#include <AthContainers/ConstDataVector.h> + +// wollen vars immer rausschreiben + +namespace HH4B +{ + + DiHiggsAnalysis::DiHiggsAnalysis() + { + // set defaults in h_cand_vars dictionary on construction + for (std::string var : h_cand_vars_list) + { + h_cand_vars[var] = -1; + } + }; + + using namespace asg::msgUserCode; + + void + DiHiggsAnalysis::makeBoostedAnalysis(const xAOD::JetContainer *largeRjets) + { + // TODO: list + + // cuts + // recommended by ftag : Remove the event if any of your signal jets have + // relativeDeltaRToVRJet < 1.0. + // least pt of large R's 250 + // largest at least 450 + // eta < 2.0 + + // delta eta between large r jets + // make btagging configurable + + // check if we have at least 2 large R jets + if (largeRjets->size() < 2) + { + return; + } + // leadding higgs candidate + HiggsCandidate h1; + // subleading higgs candidate + HiggsCandidate h2; + std::vector<HiggsCandidate> h_candidates{h1, h2}; + std::vector<int> twoLeadingPtLargeRjetsIndices = + kLargestJets(largeRjets, 2); + h1.largeRjetIndex = twoLeadingPtLargeRjetsIndices[0]; + h2.largeRjetIndex = twoLeadingPtLargeRjetsIndices[1]; + + // ghost associated track jets are only on the untrimmed 1.0 jets + SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> + m_acc_largeR_untrimmed("Parent"); + SG::AuxElement::ConstAccessor< + std::vector<ElementLink<xAOD::IParticleContainer>>> + m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); + SG::AuxElement::ConstAccessor<char> isBtag( + "ftag_select_DL1r_FixedCutBEff_77"); + + // loop over the two large R jets to get the btagged VR jets inside of each + for (HiggsCandidate h : h_candidates) + { + const xAOD::Jet *thisJet = largeRjets->at(h.largeRjetIndex); + // get ghost associated VR track jets from untrimmed large R + const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); + const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = + m_acc_VRTrackJets(*thisJet_untrimmed); + // get the btagged VR trackjets per large R jet + int counter = 0; + for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) + { + auto &test = VRjet; + // check if VRjet link is valid + // should we handle this differently? + if (!test.isValid()) + { + // doing this gives a lot of warnings, wonder why + // ANA_MSG_WARNING("Invalid track link found!"); + std::cout << "size " << VRTrackjets.size() << "count " + << counter + 1; + continue; + } + // some (very little) of the VR jets are not btagged, this means the + // VRtrack ftag sequence does not tag some of them + if (!isBtag.isAvailable(**VRjet)) + { + ANA_MSG_WARNING("Skipped non B-tagged VR jet"); + continue; + } + h.btagged_VRTrackjets.push_back(VRjet); + } + } + + // find the leading vr jets + for (HiggsCandidate h : h_candidates) + { + // check if we have at least 2 per large R jet, otherwise exit + // (subject to change) + if (h.btagged_VRTrackjets.size() < 2) + { + return; + } + + // cast VRjet to xAOD::jet to use kLargestJets sorting function + // we do it this way since we want to make shallow copies + ConstDataVector<xAOD::JetContainer> tmpVRjets(SG::VIEW_ELEMENTS); + for (auto VRjet : h.btagged_VRTrackjets) + { + const auto *jet = dynamic_cast<const xAOD::Jet *>(*VRjet); + tmpVRjets.push_back(jet); + } + // write leading and subleading vr jet onto HiggsCandidate objects + std::vector<int> twoLeadingVrJetIndices = + kLargestJets(tmpVRjets.asDataVector(), 2); + h.leadingJet = dynamic_cast<const xAOD::Jet *>( + *h.btagged_VRTrackjets[twoLeadingVrJetIndices[0]]); + h.subleadingJet = dynamic_cast<const xAOD::Jet *>( + *h.btagged_VRTrackjets[twoLeadingVrJetIndices[1]]); + // calc variables + h.fourVector = h.leadingJet->p4() + h.subleadingJet->p4(); + h.dRjets = h.leadingJet->p4().DeltaR(h.subleadingJet->p4()); + } + + // write to dictionary + h_cand_vars["boosted_m_h1"] = h1.fourVector.M(); + h_cand_vars["boosted_m_h2"] = h2.fourVector.M(); + h_cand_vars["boosted_m_hh"] = (h1.fourVector + h2.fourVector).M(); + h_cand_vars["boosted_dR_jets_in_h1"] = h1.dRjets; + h_cand_vars["boosted_dR_jets_in_h2"] = h2.dRjets; + return; + }; + +} diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h new file mode 100644 index 000000000..06c2c8cb8 --- /dev/null +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -0,0 +1,44 @@ +#ifndef HH4B_DIHIGGSANALYSIS +#define HH4B_DIHIGGSANALYSIS + +#include "xAODJet/JetContainer.h" + +// wollen vars immer rausschreiben + +namespace HH4B +{ + // used variables + std::vector<std::string> h_cand_vars_list{ + "resolved_m_h1", "resolved_m_h2", + "resolved_m_hh", "resolved_dR_jets_in_h1", + "resolved_dR_jets_in_h2", "boosted_m_h1", + "boosted_m_h2", "boosted_m_hh", + "boosted_dR_jets_in_h1", "boosted_dR_jets_in_h2", + }; + + // value dictionary h_cand + std::map<std::string, double> h_cand_vars; + + struct HiggsCandidate + { + // b-jets for h + const xAOD::Jet *leadingJet = nullptr; + const xAOD::Jet *subleadingJet = nullptr; + + // boosted analysis + // bool isBoosted? + int largeRjetIndex = -1; + // container holding links to btagged vr track jets inside the large R jet + std::vector<ElementLink<xAOD::IParticleContainer>> btagged_VRTrackjets; + TLorentzVector fourVector; + double dRjets = -1; + }; + + class DiHiggsAnalysis : HiggsCandidate + { + DiHiggsAnalysis(); + void makeResolvedAnalysis(); + void makeBoostedAnalysis(const xAOD::JetContainer *largeRjets); + }; +} +#endif diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 9d55c1a98..611e42d4c 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -57,21 +57,9 @@ namespace HH4B ATH_CHECK(m_systematicsList.service().makeSystematicsName(sysname, "%SYS%", sys)); - // ATH_MSG_INFO("Will apply sysname \"" << sysname << "\" for event"); - ATH_MSG_WARNING("Invalid track link found!"); - // Do something with Eventinfo SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey); ATH_CHECK(eventInfo.isValid()); - // jet cleaning - // if (m_applyJetCleaning) - // { - // if (!m_acc_DFCommonJets_eventClean_LooseBad(*eventInfo)) - // { - // return StatusCode::SUCCESS; // go to next event - // } - // } - const xAOD::ElectronContainer *electrons(nullptr); ATH_CHECK(m_electronHandle.retrieve(electrons, sys)); // do something with electrons @@ -91,38 +79,18 @@ namespace HH4B ATH_CHECK(m_VRtrackjetHandle.retrieve(VRTrackJets, sys)); // do something with VRTrackJets - // variable list - std::vector<std::string> h_cand_vars_list({ - "resolved_m_h1", - "resolved_m_h2", - "resolved_m_hh", - "resolved_dR_jets_in_h1", - "resolved_dR_jets_in_h2", - "boosted_m_h1", - "boosted_m_h2", - "boosted_m_hh", - "boosted_dR_jets_in_h1", - "boosted_dR_jets_in_h2", - }); - - // set defaults in h_cand_vars dictionary - std::map<std::string, double> h_cand_vars; - for (std::string var : h_cand_vars_list) - { - h_cand_vars[var] = -1; - } - // TODO: make configurable with which btagging WP Higgs candidates are // created // std::vector<std::string> - h_cand_vars = getResolvedHiggsCandidates(antiKt4RecoJets, h_cand_vars); - h_cand_vars = getBoostedHiggsCandidates(antiKt10RecoJets, h_cand_vars); + // h_cand_vars = getResolvedHiggsCandidates(antiKt4RecoJets, + // h_cand_vars); h_cand_vars = + // getBoostedHiggsCandidates(antiKt10RecoJets, h_cand_vars); // decorate eventInfo with Higgs candidates - for (std::string var : h_cand_vars_list) - { - eventInfo->auxdecor<double>(var) = h_cand_vars[var]; - } + // for (std::string var : h_cand_vars_list) + // { + // eventInfo->auxdecor<double>(var) = h_cand_vars[var]; + // } } return StatusCode::SUCCESS; -- GitLab From 5d0f7d6d5d6813f518c62e2c4e952b91f70de8c5 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Wed, 10 Aug 2022 18:37:53 +0200 Subject: [PATCH 09/33] added decoration --- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 56 ++++++++++++++++---------- HH4bAnalysis/src/DiHiggsAnalysis.h | 24 +++++------ HH4bAnalysis/src/VariableDumperAlg.cxx | 10 +++-- 3 files changed, 51 insertions(+), 39 deletions(-) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 84d4bdc06..3cc96a947 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -4,19 +4,23 @@ #include "xAODJet/JetContainer.h" #include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> - -// wollen vars immer rausschreiben +#include <SystematicsHandles/SysReadHandle.h> +#include <xAODEventInfo/EventInfo.h> namespace HH4B { - - DiHiggsAnalysis::DiHiggsAnalysis() - { - // set defaults in h_cand_vars dictionary on construction - for (std::string var : h_cand_vars_list) - { - h_cand_vars[var] = -1; - } + int initValue = -1; + std::map<std::string, double> h_cand_vars{ + {"resolved_m_h1", initValue}, + {"resolved_m_h2", initValue}, + {"resolved_m_hh", initValue}, + {"resolved_dR_jets_in_h1", initValue}, + {"resolved_dR_jets_in_h2", initValue}, + {"boosted_m_h1", initValue}, + {"boosted_m_h2", initValue}, + {"boosted_m_hh", initValue}, + {"boosted_dR_jets_in_h1", initValue}, + {"boosted_dR_jets_in_h2", initValue}, }; using namespace asg::msgUserCode; @@ -45,7 +49,6 @@ namespace HH4B HiggsCandidate h1; // subleading higgs candidate HiggsCandidate h2; - std::vector<HiggsCandidate> h_candidates{h1, h2}; std::vector<int> twoLeadingPtLargeRjetsIndices = kLargestJets(largeRjets, 2); h1.largeRjetIndex = twoLeadingPtLargeRjetsIndices[0]; @@ -61,15 +64,16 @@ namespace HH4B "ftag_select_DL1r_FixedCutBEff_77"); // loop over the two large R jets to get the btagged VR jets inside of each - for (HiggsCandidate h : h_candidates) + // need to do std::ref to access the actual objects h1, h2 + // for (HiggsCandidate h : {h1, h2}) would make copies of h1, h2 + for (HiggsCandidate &h : {std::ref(h1), std::ref(h2)}) { const xAOD::Jet *thisJet = largeRjets->at(h.largeRjetIndex); - // get ghost associated VR track jets from untrimmed large R + // get ghost associated VR track jets from untrimmed large R jet const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = m_acc_VRTrackJets(*thisJet_untrimmed); // get the btagged VR trackjets per large R jet - int counter = 0; for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) { auto &test = VRjet; @@ -77,14 +81,11 @@ namespace HH4B // should we handle this differently? if (!test.isValid()) { - // doing this gives a lot of warnings, wonder why - // ANA_MSG_WARNING("Invalid track link found!"); - std::cout << "size " << VRTrackjets.size() << "count " - << counter + 1; + ANA_MSG_WARNING("Invalid track link found!"); continue; } - // some (very little) of the VR jets are not btagged, this means the - // VRtrack ftag sequence does not tag some of them + // VRtrack ftag sequence does not tag all of them, so take only the + // btagged ones if (!isBtag.isAvailable(**VRjet)) { ANA_MSG_WARNING("Skipped non B-tagged VR jet"); @@ -95,7 +96,7 @@ namespace HH4B } // find the leading vr jets - for (HiggsCandidate h : h_candidates) + for (HiggsCandidate &h : {std::ref(h1), std::ref(h2)}) { // check if we have at least 2 per large R jet, otherwise exit // (subject to change) @@ -133,4 +134,17 @@ namespace HH4B return; }; + std::map<std::string, double> DiHiggsAnalysis::getHiggsVars() + { + return h_cand_vars; + }; + + void DiHiggsAnalysis::decorateHiggsVars(const xAOD::EventInfo &eventInfo) + { + // the range looks weird, but its just a loop over the h_cand_vars map + for (const auto &[key, value] : h_cand_vars) + { + eventInfo.auxdecor<double>(key) = value; + } + }; } diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index 06c2c8cb8..cd33d43e3 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -2,23 +2,15 @@ #define HH4B_DIHIGGSANALYSIS #include "xAODJet/JetContainer.h" +#include <SystematicsHandles/SysReadHandle.h> +#include <xAODEventInfo/EventInfo.h> // wollen vars immer rausschreiben namespace HH4B { - // used variables - std::vector<std::string> h_cand_vars_list{ - "resolved_m_h1", "resolved_m_h2", - "resolved_m_hh", "resolved_dR_jets_in_h1", - "resolved_dR_jets_in_h2", "boosted_m_h1", - "boosted_m_h2", "boosted_m_hh", - "boosted_dR_jets_in_h1", "boosted_dR_jets_in_h2", - }; - - // value dictionary h_cand - std::map<std::string, double> h_cand_vars; - + // dictionary holding the final vars + extern std::map<std::string, double> h_cand_vars; struct HiggsCandidate { // b-jets for h @@ -26,19 +18,21 @@ namespace HH4B const xAOD::Jet *subleadingJet = nullptr; // boosted analysis - // bool isBoosted? int largeRjetIndex = -1; - // container holding links to btagged vr track jets inside the large R jet + // btagged vr track jets inside the large R jet std::vector<ElementLink<xAOD::IParticleContainer>> btagged_VRTrackjets; + TLorentzVector fourVector; double dRjets = -1; }; class DiHiggsAnalysis : HiggsCandidate { - DiHiggsAnalysis(); +public: void makeResolvedAnalysis(); void makeBoostedAnalysis(const xAOD::JetContainer *largeRjets); + std::map<std::string, double> getHiggsVars(); + void decorateHiggsVars(const xAOD::EventInfo &eventInfo); }; } #endif diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 611e42d4c..5f4e13f7a 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -7,9 +7,8 @@ // Class definition #include "VariableDumperAlg.h" -#include "BoostedAnalysis.h" -#include "ResolvedAnalysis.h" -#include "map" +#include "DiHiggsAnalysis.h" + // // method implementations // @@ -81,6 +80,11 @@ namespace HH4B // TODO: make configurable with which btagging WP Higgs candidates are // created + + DiHiggsAnalysis hh4b_analysis; + hh4b_analysis.makeBoostedAnalysis(antiKt10RecoJets); + hh4b_analysis.decorateHiggsVars(*eventInfo); + // std::vector<std::string> // h_cand_vars = getResolvedHiggsCandidates(antiKt4RecoJets, // h_cand_vars); h_cand_vars = -- GitLab From f2a9a33047a205eb9cd179c2a44fb507e33a3bdf Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 11 Aug 2022 11:00:13 +0200 Subject: [PATCH 10/33] saving --- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 79 +++++++++++++++++++++++++- HH4bAnalysis/src/DiHiggsAnalysis.h | 10 ++-- HH4bAnalysis/src/VariableDumperAlg.cxx | 12 +--- 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 3cc96a947..63e4733d3 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -6,6 +6,7 @@ #include <AthContainers/ConstDataVector.h> #include <SystematicsHandles/SysReadHandle.h> #include <xAODEventInfo/EventInfo.h> +using namespace asg::msgUserCode; namespace HH4B { @@ -23,7 +24,81 @@ namespace HH4B {"boosted_dR_jets_in_h2", initValue}, }; - using namespace asg::msgUserCode; + void + DiHiggsAnalysis::makeResolvedAnalysis(const xAOD::JetContainer *smallRjets) + { + // check if we have at least 4 jets + if (smallRjets->size() < 4) + { + return; + } + // leadding higgs candidate + HiggsCandidate h1; + // subleading higgs candidate + HiggsCandidate h2; + + // get indices of 4 largest pt jets + // need to do this because sequence filtering destroys order + std::vector<int> fourLeadingPtJetsIndices = kLargestJets(smallRjets, 4); + + // get largest pt jet + h1.leadingJet = smallRjets->at(fourLeadingPtJetsIndices[0]); + + // calculate dR to other jets to find closest one + std::vector<double> dRtoLeadingJet; + double minDR = 0; + int minDRindex = -1; + for (int jetIndex : fourLeadingPtJetsIndices) + { + const xAOD::Jet *thisJet = smallRjets->at(jetIndex); + double thisDRtoLeadingJet = thisJet->p4().DeltaR(h1.leadingJet->p4()); + dRtoLeadingJet.push_back(thisDRtoLeadingJet); + if (minDR > 0 || minDR > thisDRtoLeadingJet) + { + minDR = thisDRtoLeadingJet; + minDRindex = jetIndex; + } + } + + std::cout << dRtoLeadingJet[0] << ", " << dRtoLeadingJet[1] << ", " + << dRtoLeadingJet[2] << ", " << dRtoLeadingJet[3] << std::endl; + std::cout << minDRindex << std::endl; + h1.subleadingJet = smallRjets->at(minDRindex); + + // get closest jet to leading jet + // find index (iterator) of closest jet, skip leading one as dR=0 + std::vector<double>::iterator dRminPosition = + std::min_element(dRtoLeadingJet.begin() + 1, dRtoLeadingJet.end()); + // get position in fourLeadingPtJetsIndices to access the actual jet + int closestToLeadingJetIndex = + std::distance(dRtoLeadingJet.begin(), dRminPosition); + h1.subleadingJet = + smallRjets->at(fourLeadingPtJetsIndices[closestToLeadingJetIndex]); + + // make higgs candidates + h1.fourVector = h1.leadingJet->p4() + h1.subleadingJet->p4(); + h1.dRjets = h1.leadingJet->p4().DeltaR(h1.subleadingJet->p4()); + + // make a copy of the indices and delete the ones of the h1 to get the ones + // of h2, order matters! + std::vector<int> otherJetIndices = fourLeadingPtJetsIndices; + otherJetIndices.erase(otherJetIndices.begin() + closestToLeadingJetIndex); + otherJetIndices.erase(otherJetIndices.begin()); + + h2.leadingJet = smallRjets->at(otherJetIndices[0]); + h2.subleadingJet = smallRjets->at(otherJetIndices[1]); + + h2.fourVector = h2.leadingJet->p4() + h2.subleadingJet->p4(); + h2.dRjets = h2.leadingJet->p4().DeltaR(h2.subleadingJet->p4()); + // write to dictionary + h_cand_vars["resolved_m_h1"] = h1.fourVector.M(); + h_cand_vars["resolved_m_h2"] = h2.fourVector.M(); + h_cand_vars["resolved_m_hh"] = (h1.fourVector + h2.fourVector).M(); + h_cand_vars["resolved_dR_jets_in_h1"] = h1.dRjets; + h_cand_vars["resolved_dR_jets_in_h2"] = h2.dRjets; + + return; + }; void DiHiggsAnalysis::makeBoostedAnalysis(const xAOD::JetContainer *largeRjets) @@ -65,7 +140,7 @@ namespace HH4B // loop over the two large R jets to get the btagged VR jets inside of each // need to do std::ref to access the actual objects h1, h2 - // for (HiggsCandidate h : {h1, h2}) would make copies of h1, h2 + // "for (HiggsCandidate h : {h1, h2})" would make copies of h1, h2 for (HiggsCandidate &h : {std::ref(h1), std::ref(h2)}) { const xAOD::Jet *thisJet = largeRjets->at(h.largeRjetIndex); diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index cd33d43e3..73fad58f1 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -17,19 +17,19 @@ namespace HH4B const xAOD::Jet *leadingJet = nullptr; const xAOD::Jet *subleadingJet = nullptr; - // boosted analysis + TLorentzVector fourVector; + double dRjets = -1; + + // for boosted analysis int largeRjetIndex = -1; // btagged vr track jets inside the large R jet std::vector<ElementLink<xAOD::IParticleContainer>> btagged_VRTrackjets; - - TLorentzVector fourVector; - double dRjets = -1; }; class DiHiggsAnalysis : HiggsCandidate { public: - void makeResolvedAnalysis(); + void makeResolvedAnalysis(const xAOD::JetContainer *smallRjets); void makeBoostedAnalysis(const xAOD::JetContainer *largeRjets); std::map<std::string, double> getHiggsVars(); void decorateHiggsVars(const xAOD::EventInfo &eventInfo); diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 5f4e13f7a..c1d145ff1 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -82,19 +82,9 @@ namespace HH4B // created DiHiggsAnalysis hh4b_analysis; + hh4b_analysis.makeResolvedAnalysis(antiKt4RecoJets); hh4b_analysis.makeBoostedAnalysis(antiKt10RecoJets); hh4b_analysis.decorateHiggsVars(*eventInfo); - - // std::vector<std::string> - // h_cand_vars = getResolvedHiggsCandidates(antiKt4RecoJets, - // h_cand_vars); h_cand_vars = - // getBoostedHiggsCandidates(antiKt10RecoJets, h_cand_vars); - - // decorate eventInfo with Higgs candidates - // for (std::string var : h_cand_vars_list) - // { - // eventInfo->auxdecor<double>(var) = h_cand_vars[var]; - // } } return StatusCode::SUCCESS; -- GitLab From 956c8ca844e4e0b2562987b0e861bbf4ddef64bb Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 11 Aug 2022 12:01:54 +0200 Subject: [PATCH 11/33] moved to object orientation --- HH4bAnalysis/src/BoostedAnalysis.cxx | 142 -------------------------- HH4bAnalysis/src/BoostedAnalysis.h | 11 -- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 47 +++------ HH4bAnalysis/src/DiHiggsAnalysis.h | 13 ++- HH4bAnalysis/src/ResolvedAnalysis.cxx | 61 ----------- HH4bAnalysis/src/ResolvedAnalysis.h | 11 -- 6 files changed, 24 insertions(+), 261 deletions(-) delete mode 100644 HH4bAnalysis/src/BoostedAnalysis.cxx delete mode 100644 HH4bAnalysis/src/BoostedAnalysis.h delete mode 100644 HH4bAnalysis/src/ResolvedAnalysis.cxx delete mode 100644 HH4bAnalysis/src/ResolvedAnalysis.h diff --git a/HH4bAnalysis/src/BoostedAnalysis.cxx b/HH4bAnalysis/src/BoostedAnalysis.cxx deleted file mode 100644 index 75ad5a28c..000000000 --- a/HH4bAnalysis/src/BoostedAnalysis.cxx +++ /dev/null @@ -1,142 +0,0 @@ -#include "BoostedAnalysis.h" -#include "map" -#include "string" -#include "tools/kLargestJets.h" -#include "xAODJet/JetContainer.h" -#include <AsgMessaging/MessageCheck.h> -#include <AthContainers/ConstDataVector.h> - -using namespace asg::msgUserCode; - -std::map<std::string, double> -getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, - std::map<std::string, double> h_cand_vars) -{ - // TODO: list - - // cuts - // recommended by ftag : Remove the event if any of your signal jets have - // relativeDeltaRToVRJet < 1.0. - // least pt of large R's 250 - // largest at least 450 - // eta < 2.0 - - // delta eta between large r jets - // make btagging configurable - - // check if we have at least 2 large R jets - if (largeRjets->size() < 2) - { - return h_cand_vars; - } - std::vector<int> twoLeadingPtLargeRjetsIndices = kLargestJets(largeRjets, 2); - - // ghost associated track jets are only on the untrimmed 1.0 jets - SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> - m_acc_largeR_untrimmed("Parent"); - SG::AuxElement::ConstAccessor< - std::vector<ElementLink<xAOD::IParticleContainer>>> - m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); - SG::AuxElement::ConstAccessor<char> isBtag( - "ftag_select_DL1r_FixedCutBEff_77"); - - // need to allocate size of this to work with the - // twoLeadingPtLargeRjetsIndices - int allocation_size = *max_element(twoLeadingPtLargeRjetsIndices.begin(), - twoLeadingPtLargeRjetsIndices.end()) + - 1; - std::vector<std::vector<ElementLink<xAOD::IParticleContainer>>> - btagged_VRTrackjets(allocation_size); - - // loop over the two large R jets to get the btagged VR jets inside of each - // (i is the large R jet index not a counter) - for (int i : twoLeadingPtLargeRjetsIndices) - { - - const xAOD::Jet *thisJet = largeRjets->at(i); - // get ghost associated VR track jets from untrimmed large R - const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); - const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = - m_acc_VRTrackJets(*thisJet_untrimmed); - // get the btagged VR trackjets per large R jet - int counter = 0; - for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) - { - auto &test = VRjet; - // check if VRjet link is valid - // should we handle this differently? - if (!test.isValid()) - { - // doing this gives a lot of warnings, wonder why - // ANA_MSG_WARNING("Invalid track link found!"); - std::cout << "size " << VRTrackjets.size() << "count " << counter + 1; - continue; - } - // some (very little) of the VR jets are not btagged, this means the - // VRtrack ftag sequence does not tag some of them - if (!isBtag.isAvailable(**VRjet)) - { - ANA_MSG_WARNING("Skipped non B-tagged VR jet"); - continue; - } - - // (i is the large R jet index not a counter) - btagged_VRTrackjets[i].emplace_back(VRjet); - } - } - - // get leading pt jets of btagged VRtrackJets in largeRjet i - // e.g. h_cand_indices[twoLeadingPtLargeRjetsIndices[0]] contains pt-sorted - // VRtrackjet indices for the leading (twoLeadingPtLargeRjetsIndices[0]) - // largeRjet - - std::vector<std::vector<int>> h_cand_indices(allocation_size); - for (int i : twoLeadingPtLargeRjetsIndices) - { - // check if we have at least 2 per large R jet, otherwise exit - // (subject to change) - if (btagged_VRTrackjets[i].size() < 2) - { - return h_cand_vars; - } - - ConstDataVector<xAOD::JetContainer> tmpVRjets(SG::VIEW_ELEMENTS); - // cast VRjet to xAOD::jet to use kLargestJets sorting function - // we do it this way since we want to make shallow copies - // tmpVRjets is recreated per i - for (auto VRjet : btagged_VRTrackjets[i]) - { - const auto *jet = dynamic_cast<const xAOD::Jet *>(*VRjet); - tmpVRjets.push_back(jet); - } - - h_cand_indices[i] = kLargestJets(tmpVRjets.asDataVector(), 2); - } - - // make higgs candidates - - std::vector<TLorentzVector> h_cand(allocation_size); - std::vector<double> dR_jets_in_h_cand(allocation_size); - - for (int i : twoLeadingPtLargeRjetsIndices) - { - auto leadingVR_h_cand = *btagged_VRTrackjets[i][h_cand_indices[i][0]]; - auto subleadingVR_h_cand = *btagged_VRTrackjets[i][h_cand_indices[i][1]]; - h_cand[i] = leadingVR_h_cand->p4() + subleadingVR_h_cand->p4(); - dR_jets_in_h_cand[i] = - leadingVR_h_cand->p4().DeltaR(subleadingVR_h_cand->p4()); - } - - // write to dictionary - auto h1_cand = h_cand[twoLeadingPtLargeRjetsIndices[0]]; - auto h2_cand = h_cand[twoLeadingPtLargeRjetsIndices[1]]; - h_cand_vars["boosted_m_h1"] = h1_cand.M(); - h_cand_vars["boosted_m_h2"] = h2_cand.M(); - h_cand_vars["boosted_m_hh"] = (h1_cand + h2_cand).M(); - h_cand_vars["boosted_dR_jets_in_h1"] = - dR_jets_in_h_cand[twoLeadingPtLargeRjetsIndices[0]]; - h_cand_vars["boosted_dR_jets_in_h2"] = - dR_jets_in_h_cand[twoLeadingPtLargeRjetsIndices[1]]; - - return h_cand_vars; -}; \ No newline at end of file diff --git a/HH4bAnalysis/src/BoostedAnalysis.h b/HH4bAnalysis/src/BoostedAnalysis.h deleted file mode 100644 index 2efad7b90..000000000 --- a/HH4bAnalysis/src/BoostedAnalysis.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef HH4BANALYSIS_BOOSTED_ANALYSIS -#define HH4BANALYSIS_BOOSTED_ANALYSIS - -#include "map" -#include "xAODJet/JetContainer.h" - -std::map<std::string, double> -getBoostedHiggsCandidates(const xAOD::JetContainer *largeRjets, - std::map<std::string, double> h_cand_vars); - -#endif diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 63e4733d3..c137cfcd2 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -1,11 +1,8 @@ #include "DiHiggsAnalysis.h" #include "tools/kLargestJets.h" -#include "xAODJet/JetContainer.h" #include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> -#include <SystematicsHandles/SysReadHandle.h> -#include <xAODEventInfo/EventInfo.h> using namespace asg::msgUserCode; namespace HH4B @@ -37,7 +34,7 @@ namespace HH4B // subleading higgs candidate HiggsCandidate h2; - // get indices of 4 largest pt jets + // get indices of 4 largest pt jets in descending order // need to do this because sequence filtering destroys order std::vector<int> fourLeadingPtJetsIndices = kLargestJets(smallRjets, 4); @@ -45,51 +42,37 @@ namespace HH4B h1.leadingJet = smallRjets->at(fourLeadingPtJetsIndices[0]); // calculate dR to other jets to find closest one - std::vector<double> dRtoLeadingJet; - double minDR = 0; + double minDR = -1; int minDRindex = -1; for (int jetIndex : fourLeadingPtJetsIndices) { const xAOD::Jet *thisJet = smallRjets->at(jetIndex); double thisDRtoLeadingJet = thisJet->p4().DeltaR(h1.leadingJet->p4()); - dRtoLeadingJet.push_back(thisDRtoLeadingJet); - if (minDR > 0 || minDR > thisDRtoLeadingJet) + if (thisDRtoLeadingJet > 0 or minDR > thisDRtoLeadingJet) { minDR = thisDRtoLeadingJet; minDRindex = jetIndex; } } - std::cout << dRtoLeadingJet[0] << ", " << dRtoLeadingJet[1] << ", " - << dRtoLeadingJet[2] << ", " << dRtoLeadingJet[3] << std::endl; - std::cout << minDRindex << std::endl; h1.subleadingJet = smallRjets->at(minDRindex); - - // get closest jet to leading jet - // find index (iterator) of closest jet, skip leading one as dR=0 - std::vector<double>::iterator dRminPosition = - std::min_element(dRtoLeadingJet.begin() + 1, dRtoLeadingJet.end()); - // get position in fourLeadingPtJetsIndices to access the actual jet - int closestToLeadingJetIndex = - std::distance(dRtoLeadingJet.begin(), dRminPosition); - h1.subleadingJet = - smallRjets->at(fourLeadingPtJetsIndices[closestToLeadingJetIndex]); - - // make higgs candidates + // calculate higgs candidate four vector and dR between jets h1.fourVector = h1.leadingJet->p4() + h1.subleadingJet->p4(); h1.dRjets = h1.leadingJet->p4().DeltaR(h1.subleadingJet->p4()); - // make a copy of the indices and delete the ones of the h1 to get the ones - // of h2, order matters! - std::vector<int> otherJetIndices = fourLeadingPtJetsIndices; - otherJetIndices.erase(otherJetIndices.begin() + closestToLeadingJetIndex); - otherJetIndices.erase(otherJetIndices.begin()); - - h2.leadingJet = smallRjets->at(otherJetIndices[0]); - h2.subleadingJet = smallRjets->at(otherJetIndices[1]); + // get jet indices of subleading higgs candidate h2 + std::vector<int> h2_indices; + for (int jetIndex : fourLeadingPtJetsIndices) + { + if (jetIndex != fourLeadingPtJetsIndices[0] and jetIndex != minDRindex) + h2_indices.push_back(jetIndex); + } + h2.leadingJet = smallRjets->at(h2_indices[0]); + h2.subleadingJet = smallRjets->at(h2_indices[1]); h2.fourVector = h2.leadingJet->p4() + h2.subleadingJet->p4(); h2.dRjets = h2.leadingJet->p4().DeltaR(h2.subleadingJet->p4()); + // write to dictionary h_cand_vars["resolved_m_h1"] = h1.fourVector.M(); h_cand_vars["resolved_m_h2"] = h2.fourVector.M(); @@ -109,7 +92,7 @@ namespace HH4B // recommended by ftag : Remove the event if any of your signal jets have // relativeDeltaRToVRJet < 1.0. // least pt of large R's 250 - // largest at least 450 + // largest pt jet large R at least 450 // eta < 2.0 // delta eta between large r jets diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index 73fad58f1..9ff5cd839 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -2,7 +2,6 @@ #define HH4B_DIHIGGSANALYSIS #include "xAODJet/JetContainer.h" -#include <SystematicsHandles/SysReadHandle.h> #include <xAODEventInfo/EventInfo.h> // wollen vars immer rausschreiben @@ -11,27 +10,33 @@ namespace HH4B { // dictionary holding the final vars extern std::map<std::string, double> h_cand_vars; + struct HiggsCandidate { - // b-jets for h + // b-jets for Higgs candidate const xAOD::Jet *leadingJet = nullptr; const xAOD::Jet *subleadingJet = nullptr; - + // four vector of Higgs candidate TLorentzVector fourVector; + // dR between leading and subleading jet double dRjets = -1; // for boosted analysis int largeRjetIndex = -1; - // btagged vr track jets inside the large R jet + // btagged ghost associated VR track jets inside the large R jet std::vector<ElementLink<xAOD::IParticleContainer>> btagged_VRTrackjets; }; class DiHiggsAnalysis : HiggsCandidate { public: + // do resolved Analysis void makeResolvedAnalysis(const xAOD::JetContainer *smallRjets); + // do boosted Analysis void makeBoostedAnalysis(const xAOD::JetContainer *largeRjets); + // returns h_cand_vars for other purposes std::map<std::string, double> getHiggsVars(); + // decorates the h_cand_vars to the eventInfo void decorateHiggsVars(const xAOD::EventInfo &eventInfo); }; } diff --git a/HH4bAnalysis/src/ResolvedAnalysis.cxx b/HH4bAnalysis/src/ResolvedAnalysis.cxx deleted file mode 100644 index b590e8e8e..000000000 --- a/HH4bAnalysis/src/ResolvedAnalysis.cxx +++ /dev/null @@ -1,61 +0,0 @@ -#include "ResolvedAnalysis.h" -#include "map" -#include "tools/kLargestJets.h" -#include "xAODJet/JetContainer.h" - -std::map<std::string, double> -getResolvedHiggsCandidates(const xAOD::JetContainer *smallRjets, - std::map<std::string, double> &h_cand_vars) -{ - // check if we have at least 4 jets - if (smallRjets->size() < 4) - { - return h_cand_vars; - } - // get indices of 4 largest pt jets - // need to do this because sequence filtering destroys order - std::vector<int> fourLeadingPtJetsIndices = kLargestJets(smallRjets, 4); - // get largest pt jet - const xAOD::Jet *largestPtJet = smallRjets->at(fourLeadingPtJetsIndices[0]); - - // calculate dR to other higgs candidate jets - std::vector<double> dRtoLargestPtJet; - for (int jetIndex : fourLeadingPtJetsIndices) - { - const xAOD::Jet *thisJet = smallRjets->at(jetIndex); - double thisDRtoLargestPtJet = thisJet->p4().DeltaR(largestPtJet->p4()); - dRtoLargestPtJet.push_back(thisDRtoLargestPtJet); - } - - // get closest jet to leading jet - int closestToLeadingJetEntry = - std::min_element(dRtoLargestPtJet.begin(), dRtoLargestPtJet.end()) - - dRtoLargestPtJet.begin(); - const xAOD::Jet *closestToLeadingJet = - smallRjets->at(fourLeadingPtJetsIndices[closestToLeadingJetEntry]); - - // make higgs candidates - TLorentzVector h1_cand = largestPtJet->p4() + closestToLeadingJet->p4(); - double dR_jets_in_h1 = largestPtJet->p4().DeltaR(closestToLeadingJet->p4()); - - // make a copy of the indices and delete the ones of the h1_cand to get the - // ones of the h2_cand, order matters! - std::vector<int> otherJetIndices = fourLeadingPtJetsIndices; - otherJetIndices.erase(otherJetIndices.begin() + closestToLeadingJetEntry); - otherJetIndices.erase(otherJetIndices.begin()); - - const xAOD::Jet *otherJet1 = smallRjets->at(otherJetIndices[0]); - const xAOD::Jet *otherJet2 = smallRjets->at(otherJetIndices[1]); - - TLorentzVector h2_cand = otherJet1->p4() + otherJet2->p4(); - double dR_jets_in_h2 = otherJet1->p4().DeltaR(otherJet2->p4()); - - // write to dictionary - h_cand_vars["resolved_m_h1"] = h1_cand.M(); - h_cand_vars["resolved_m_h2"] = h2_cand.M(); - h_cand_vars["resolved_m_hh"] = (h1_cand + h2_cand).M(); - h_cand_vars["resolved_dR_jets_in_h1"] = dR_jets_in_h1; - h_cand_vars["resolved_dR_jets_in_h2"] = dR_jets_in_h2; - - return h_cand_vars; -}; \ No newline at end of file diff --git a/HH4bAnalysis/src/ResolvedAnalysis.h b/HH4bAnalysis/src/ResolvedAnalysis.h deleted file mode 100644 index d9d38b545..000000000 --- a/HH4bAnalysis/src/ResolvedAnalysis.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef HH4BANALYSIS_RESOLVED_ANALYSIS -#define HH4BANALYSIS_RESOLVED_ANALYSIS - -#include "map" -#include "xAODJet/JetContainer.h" - -std::map<std::string, double> -getResolvedHiggsCandidates(const xAOD::JetContainer *smallRjets, - std::map<std::string, double> &h_cand_vars); - -#endif -- GitLab From db01f983156a2e6e2dc2e5b9129cb0c8e4dd2078 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 11 Aug 2022 13:36:43 +0200 Subject: [PATCH 12/33] adapt to new master --- HH4bAnalysis/share/VariableDumperConfig.py | 850 +++++++++--------- .../share/utils/containerNameHelper.py | 3 - 2 files changed, 412 insertions(+), 441 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 392fdb43a..41fc6ee40 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -1,440 +1,421 @@ #!/bin/env python -################################################################################ + +# +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# + +# # VariableDumperConfig.py # A simple CA file to create a tree of variables # -# Author: Victor Ruelas -# Basic setup import sys +from pathlib import Path -from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence -from AnaAlgorithm.DualUseConfig import createAlgorithm from AthenaCommon import Logging +from AthenaConfiguration.AutoConfigFlags import GetFileMD from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory -from utils.argsHelper import checkArgs -from utils.containerNameHelper import getContainerName -from utils.convertOldConfigHelper import convertSequenceAndGetAlgs +from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg +from HH4bAnalysis.Algs.Event import ( + EventSelectionAnalysisSequenceCfg, + GeneratorAnalysisSequenceCfg, + PileupAnalysisSequenceCfg, + TriggerAnalysisSequenceCfg, +) +from HH4bAnalysis.Algs.Jets import ( + FatJetAnalysisSequenceCfg, + JetAnalysisSequenceCfg, + VRJetAnalysisSequenceCfg, +) +from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg +from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg +from HH4bAnalysis.Algs.Postprocessing import OverlapAnalysisSequenceCfg +from HH4bAnalysis.Algs.Tree import AnalysisTreeAlgCfg +from HH4bAnalysis.Config.Base import cache_metadata, pileupConfigFiles, update_metadata +from HH4bAnalysis.utils.containerNameHelper import getContainerName + +log = Logging.logging.getLogger("VariableDumperConfig") + + +def defineArgs(ConfigFlags): + # Generate a parser and add an output file argument, then retrieve the args + parser = ConfigFlags.getArgumentParser() + parser.add_argument( + "--outFile", + type=str, + default="analysis-variables.root", + help="Output file name", + ) + parser.add_argument( + "--btag-wps", + type=str, + nargs="*", + default=[ + "DL1dv00_FixedCutBEff_77", + "DL1dv00_FixedCutBEff_85", + ], + help="Btag working points default %(default)s", + ) + parser.add_argument( + "--vr-btag-wps", + type=str, + nargs="*", + default=[ + # "DL1r_FixedCutBEff_77", + # "DL1r_FixedCutBEff_85", + ], + help="VR Jets btag working points default %(default)s", + ) + parser.add_argument( + "--trigger-list", + type=str, + default="Run3", + help="Trigger list to use, default: %(default)s", + ) + parser.add_argument( + "-c", + "--meta-cache", + type=Path, + default=None, + nargs="?", + const=Path("metadata.json"), + help="use metadata cache file, defaults to %(const)s", + ) + parser.add_argument( + "-o", + "--loose", + action="store_true", + help="use loose event cleaning (to get something to pass)", + ) + return parser + -variabledumperlog = Logging.logging.getLogger("VariableDumperConfig") +def _is_physlite(flags): + fileMD = GetFileMD(flags.Input.Files[0]) + return fileMD.get("processingTags", []) == ["StreamDAOD_PHYSLITE"] -def pileupConfigFiles(dataType): - """Return the PRW (Pileup ReWeighting) config files and lumicalc files""" - if dataType == "data": - prwFiles = [] - lumicalcFiles = [] +def _is_mc_phys(flags): + return flags.Input.isMC and not _is_physlite(flags) + + +def _get_container_names(flags): + is_daod_physlite = _is_physlite(flags) + inputs = dict( + reco4Jet=getContainerName("Reco4PFlowJets", is_daod_physlite), + reco10Jet=getContainerName("Reco10PFlowJets", is_daod_physlite), + vrJet=getContainerName("VRJets", is_daod_physlite), + muons=getContainerName("Muons", is_daod_physlite), + electrons=getContainerName("Electrons", is_daod_physlite), + photons=getContainerName("Photons", is_daod_physlite), + ) + outputs = dict( + reco4Jet=f"Analysis{inputs['reco4Jet']}_%SYS%", + muons=f"Analysis{inputs['muons']}_%SYS%", + electrons=f"Analysis{inputs['electrons']}_%SYS%", + photons=f"Analysis{inputs['photons']}_%SYS%", + ) + if inputs["reco10Jet"]: + outputs["reco10Jet"] = f"Analysis{inputs['reco10Jet']}_%SYS%" else: - lumicalcFiles = [ - # These need to be updated for release 22 data - # "GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root", - # "GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root", - # "GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.lumicalc.OflLumi-13TeV-010.root", - # "GoodRunsLists/data18_13TeV/20190318/ilumicalc_histograms_None_348885-364292_OflLumi-13TeV-010.root", - ] - if dataType == "mc": - prwFiles = [ - # Need to be updated and are job specific? - # "/cvmfs/atlas.cern.ch/repo/sw/database/GroupData/dev/PileupReweighting/share/DSID364xxx/pileup_mc20d_dsid364701_FS.root" - ] - else: - # We don't have a PRW file that works properly for the AFII file - # so we don't apply it in this case - prwFiles = [] - return prwFiles, lumicalcFiles + outputs["reco10Jet"] = "" + if inputs["vrJet"]: + outputs["vrJet"] = f"Analysis{inputs['vrJet']}_%SYS%" + else: + outputs["vrJet"] = "" + return {"inputs": inputs, "outputs": outputs} # 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 AnalysisAlgsCfg( + flags, + btag_wps, + vr_btag_wps, + trigger_chains=[], + do_muons=True, + metadata_cache=None, + do_loose=False, +): + fileMD = GetFileMD(flags.Input.Files[0]) + if metadata_cache: + update_metadata(metadata_cache) dataType = "mc" if flags.Input.isMC else "data" + is_daod_physlite = _is_physlite(flags) + log.info( + f"Self-configured: dataType: '{dataType}', is PHYSLITE? {is_daod_physlite}" + ) - reco4JetContainerName = getContainerName("Reco4PFlowJets", is_daod_physlite) - reco10JetContainerName = getContainerName("Reco10PFlowJets", is_daod_physlite) - recoVRJetContainerName = getContainerName("RecoVRTrackJets", is_daod_physlite) - muonsContainerName = getContainerName("Muons", is_daod_physlite) - electronsContainerName = getContainerName("Electrons", is_daod_physlite) - photonsContainerName = getContainerName("Photons", is_daod_physlite) + log.debug(f"Containers available in dataset: {flags.Input.Collections}") + + # TODO: no DL1d branches in PHYSLITE yet + if is_daod_physlite: + btag_wps = [wp.replace("DL1dv00", "DL1r") for wp in btag_wps] cfg = ComponentAccumulator() # Every CA should include all its dependencies, apart from the global ones # included in the main function. # - # Add an instance of THistSvc, to create the output file and associated stream. - # This is needed so that the alg can register its output TTree. - # The syntax for the output is: - # Stream name: "ANALYSIS" (default assumed by AthHistogramAlgorithm) - # Output file name: specified by setting "DATAFILE" - # File I/O option: specified by setting "OPT" and passed to the TFile constructor - # "RECREATE" will (over)write the specified file name with a new file - cfg.addService( - CompFactory.THistSvc(Output=[f"ANALYSIS DATAFILE='{outfname}', OPT='RECREATE'"]) - ) # 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, + systematicsSvc = CompFactory.getComp("CP::SystematicsSvc")("SystematicsSvc") + cfg.addService(systematicsSvc) + + log.info("Adding trigger analysis algs") + # Removes events failing trigger and adds variable to EventInfo + # if trigger passed or not, for example: + # EventInfo.trigger_name + cfg.merge(TriggerAnalysisSequenceCfg(flags, dataType, trigger_chains)) + + log.info("Add DQ event filter sequence") + # Remove events failing DQ criteria + cfg.merge( + EventSelectionAnalysisSequenceCfg(flags, dataType, grlFiles=[], loose=do_loose) ) - 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 + doPRW = _is_mc_phys(flags) + log.info( + f"Do PRW is {doPRW}. {'Add' if doPRW else 'Skip'} pileup re-weight sequence" ) - cfg.addSequence(electronSequenceCnv) - for electronAlg in electronAlgsCnv: - cfg.addEventAlgo(electronAlg, electronSequenceCnv.getName()) + if doPRW: + try: + prwFiles, lumicalcFiles = pileupConfigFiles(fileMD) + # Adds variable to EventInfo if for pileup weight, for example: + # EventInfo.PileWeight_%SYS$ + cfg.merge( + PileupAnalysisSequenceCfg( + flags, + dataType=dataType, + prwFiles=prwFiles, + lumicalcFiles=lumicalcFiles, + ) + ) - # Include, and then set up the photon analysis sequence: - from EgammaAnalysisAlgorithms.PhotonAnalysisSequence import ( - makePhotonAnalysisSequence, + log.info("Adding generator analysis sequence") + runNumbers = fileMD.get("runNumbers", []) + # Adds variable to EventInfo if for generator weight, for example: + # EventInfo.generatorWeight_%SYS% + cfg.merge(GeneratorAnalysisSequenceCfg(flags, dataType, runNumbers[0])) + + except LookupError as err: + log.error(err) + doPRW = False + + containers = _get_container_names(flags) + + log.info("Add electron seq") + cfg.merge( + ElectronAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["electrons"], + outputContainerName=containers["outputs"]["electrons"], + ) ) - 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, + log.info("Add photon seq") + cfg.merge( + PhotonAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["photons"], + outputContainerName=containers["outputs"]["photons"], + ) ) - from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence + if do_muons: + log.info("Add muon seq") + cfg.merge( + MuonAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["muons"], + outputContainerName=containers["outputs"]["muons"], + ) + ) - 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, + log.info("Add jet seq") + cfg.merge( + JetAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["reco4Jet"], + outputContainerName=containers["outputs"]["reco4Jet"], + workingPoints=btag_wps, + is_daod_physlite=is_daod_physlite, ) - # 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: - cfg.addEventAlgo(jetAlg, jetSequenceCnv.getName()) - - # Variable Radius jets Ftag sqeuence - VRSequence = AnaAlgSequence("VRTrackFTagAnalysisSequence") - # the following lines make a shallow copy, - # this isn't needed anymore with this MR - # https://gitlab.cern.ch/atlas/athena/-/merge_requests/54929 - alg = createAlgorithm("CP::AsgViewFromSelectionAlg", "VRJetSelectionAlg") - VRSequence.append( - alg, - inputPropName="input", - outputPropName="output", - stageName="selection", - dynConfig={}, - ) - VRftagSequence = makeFTagAnalysisSequence( - VRSequence, - dataType, - "AntiKtVR30Rmax4Rmin02TrackJets", - btagWP="FixedCutBEff_77", - btagger="DL1r", - postfix="VR", - preselection=None, - kinematicSelection=True, - noEfficiency=False, - legacyRecommendations=False, - enableCutflow=False, - minPt=20000, ) - for ftagAlg in VRftagSequence: - if "FTagSelectionAlg" in ftagAlg.getName(): - ftagAlg.selectionTool.FlvTagCutDefinitionsFileName = bTagCalibFile - if "FTagEfficiencyScaleFactorAlg" in ftagAlg.getName(): - ftagAlg.efficiencyTool.ScaleFactorFileName = bTagCalibFile + if is_daod_physlite: + log.warning("On PHYSLITE, skip large-R jet sequence for now") + else: + log.info("Add large-R jet seq") + cfg.merge( + FatJetAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["reco10Jet"], + outputContainerName=containers["outputs"]["reco10Jet"], + ) + ) - VRSequence.configure( - inputName=recoVRJetContainerName, outputName="VRTrackJetsBTAG_%SYS%" - ) + if is_daod_physlite: + log.warning("On PHYSLITE, skip VR jet sequence for now") + else: + log.info("Add VR jet seq") + cfg.merge( + VRJetAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["vrJet"], + outputContainerName=containers["outputs"]["vrJet"], + workingPoints=vr_btag_wps, + ) + ) - VRjetSequenceCnv, VRjetAlgsCnv = convertSequenceAndGetAlgs(CompFactory, VRSequence) - cfg.addSequence(VRjetSequenceCnv) - for VRjetAlg in VRjetAlgsCnv: - cfg.addEventAlgo(VRjetAlg, VRjetSequenceCnv.getName()) - - 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 + ######################################################################## + # Begin postprocessing + ######################################################################## + + log.info("Add Overlap Removal sequence") + overlapInputNames = { + "electrons": containers["outputs"]["electrons"], + "photons": containers["outputs"]["photons"], + "jets": containers["outputs"]["reco4Jet"], + } + if do_muons: + overlapInputNames["muons"] = containers["outputs"]["muons"] + + if not is_daod_physlite: + overlapInputNames["fatJets"] = containers["outputs"]["reco10Jet"] + + overlapOutputNames = {k: f"{v}_OR" for k, v in overlapInputNames.items()} + + cfg.merge( + OverlapAnalysisSequenceCfg( + flags, + dataType=dataType, + inputNames=overlapInputNames, + outputNames=overlapOutputNames, + doFatJets=not is_daod_physlite, + doMuons=do_muons, + ) ) - 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, - ) + if metadata_cache: + cache_metadata(metadata_cache) - 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", - # btag_wps=btag_wps, - ) - ) + return cfg + + +def MiniTupleCfg( + flags, + outfname, + trigger_chains, + working_points, + do_muons=True, +): + cfg = ComponentAccumulator() + is_daod_physlite = _is_physlite(flags) + doPRW = _is_mc_phys(flags) + containers = _get_container_names(flags)["outputs"] + log.debug(f"Containers requested in dataset: {containers}") + + ######################################################################## # Create analysis mini-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 = [ + ######################################################################## + + # Add an instance of THistSvc, to create the output file and associated stream. + # This is needed so that the alg can register its output TTree. + # The syntax for the output is: + # Stream name: "ANALYSIS" (default assumed by AthHistogramAlgorithm) + # Output file name: specified by setting "DATAFILE" + # File I/O option: specified by setting "OPT" and passed to the TFile constructor + # "RECREATE" will (over)write the specified file name with a new file + cfg.addService( + CompFactory.THistSvc(Output=[f"ANALYSIS DATAFILE='{outfname}', OPT='RECREATE'"]) + ) + + def getFourMomBranches(container, alias, doOR=False): + ORstr = "_OR" if doOR else "" + + branches = [] + vars = ["pt", "eta", "phi"] + if "Jets" in container: + vars.append("m") + for var in vars: + branches += [ + f"{container}{ORstr}.{var} -> {alias}{ORstr}_%SYS%_{var}", + ] + return branches + + analysisTreeBranches = [ "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.resolved_m_h1 -> resolved_m_h1", - "EventInfo.resolved_m_h2 -> resolved_m_h2", - "EventInfo.resolved_m_hh -> resolved_m_hh", - "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", - "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", - "EventInfo.boosted_m_h1 -> boosted_m_h1", - "EventInfo.boosted_m_h2 -> boosted_m_h2", - "EventInfo.boosted_m_hh -> boosted_m_hh", - "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", - "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", + "EventInfo.mcEventWeights -> mcEventWeights", + "EventInfo.averageInteractionsPerCrossing -> averageInteractionsPerCrossing", ] - ntupleMaker.Branches += [ - f"AnalysisJets_%SYS%.ftag_select_{btag_wp} -> recojet_antikt4_%SYS%_{btag_wp}" - for btag_wp in btag_wps + + for trig_chain in trigger_chains: + cleaned = trig_chain.replace("-", "_") + if "." in trig_chain: + continue + analysisTreeBranches.append( + f"EventInfo.trigPassed_{cleaned} -> trigPassed_{cleaned}" + ) + + if doPRW: + analysisTreeBranches += [ + "EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%", + "EventInfo.generatorWeight_%SYS% -> generatorWeight_%SYS%", + ] + else: + analysisTreeBranches += [ + "EventInfo.mcEventWeights -> pileupWeight_NOSYS", + ] + + objectpairs = { + containers["electrons"]: "el", + containers["photons"]: "ph", + containers["reco4Jet"]: "recojet_antikt4", + } + if do_muons: + containers["muons"] = "mu" + + for cont, alias in objectpairs.items(): + analysisTreeBranches += getFourMomBranches(cont, alias) + analysisTreeBranches += getFourMomBranches(cont, alias, doOR=True) + + # B-jet WPs + analysisTreeBranches += [ + f"{containers['reco4Jet']}.ftag_select_{btag_wp}" + f" -> recojet_antikt4_%SYS%_{btag_wp}" + for btag_wp in working_points["ak4"] + ] + analysisTreeBranches += [ + f"{containers['reco4Jet']}_OR.ftag_select_{btag_wp}" + f" -> recojet_antikt4_OR_%SYS%_{btag_wp}" + for btag_wp in working_points["ak4"] ] - cfg.addEventAlgo(ntupleMaker) - # Fill tree - treeFiller = CompFactory.getComp("CP::TreeFillerAlg")("TreeFiller") - treeFiller.TreeName = "AnalysisMiniTree" - cfg.addEventAlgo(treeFiller) + if not is_daod_physlite: + analysisTreeBranches += getFourMomBranches( + containers["reco10Jet"], "recojet_antikt10" + ) + analysisTreeBranches += getFourMomBranches( + containers["reco10Jet"], "recojet_antikt10", doOR=True + ) + analysisTreeBranches += getFourMomBranches(containers["vrJet"], "vrjet") + analysisTreeBranches += [ + f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" + for btag_wp in working_points["vr"] + ] + + log.info("Add tree seq") + cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) return cfg @@ -443,55 +424,31 @@ def VariableDumperCfg(flags, outfname, is_daod_physlite, btag_wps): # We define a "main function" that will run a test job if the module # is executed rather than imported. def main(): + # Import the job configuration flags, some of which will be autoconfigured. + # These are used for steering the job, and include e.g. the input file (list). + from AthenaConfiguration.AllConfigFlags import ConfigFlags + + # Get the arguments, defined at the top for easy browsing + parser = defineArgs(ConfigFlags) + args = ConfigFlags.fillFromArgs([], parser) + # Lock the flags so that the configuration of job subcomponents cannot + # modify them silently/unpredictably. + # Workaround for buggy glob, needed prior + # to https://gitlab.cern.ch/atlas/athena/-/merge_requests/55561 + if ConfigFlags.Input.Files[0] == "_ATHENA_GENERIC_INPUTFILE_NAME_": + ConfigFlags.Input.Files = ConfigFlags.Input.Files[1:] + log.info(f"Operating on input files {ConfigFlags.Input.Files}") + ConfigFlags.lock() + + # Get a ComponentAccumulator setting up the standard components + # needed to run an Athena job. # Setting temporarily needed for Run 3 code, to generate python # Configurable objects for deduplication from AthenaCommon.Configurable import ConfigurableRun3Behavior + from AthenaConfiguration.MainServicesConfig import MainServicesCfg with ConfigurableRun3Behavior(): - # Import the job configuration flags, some of which will be autoconfigured. - # These are used for steering the job, and include e.g. the input file (list). - from AthenaConfiguration.AllConfigFlags import ConfigFlags - - # Generate a parser and add an output file argument, then retrieve the args - parser = ConfigFlags.getArgumentParser() - parser.add_argument( - "--outFile", - type=str, - default="analysis-variables.root", - help="Output file name", - ) - parser.add_argument( - "--mc", - action="store_true", - help="Input is Monte Carlo", - ) - parser.add_argument( - "--daod-physlite", - action="store_true", - help="Input is DAOD_PHYSLITE", - ) - parser.add_argument( - "--btag-wps", - type=str, - nargs="+", - default=[ - "DL1dv00_FixedCutBEff_77", - "DL1dv00_FixedCutBEff_85", - ], - help="btag working points default %(default)s", - ) - args = ConfigFlags.fillFromArgs([], parser) - # Lock the flags so that the configuration of job subcomponents cannot - # modify them silently/unpredictably. - ConfigFlags.lock() - - checkArgs(ConfigFlags, args, parser) - - # Get a ComponentAccumulator setting up the standard components - # needed to run an Athena job. - from AthenaConfiguration.MainServicesConfig import MainServicesCfg - cfg = MainServicesCfg(ConfigFlags) # Adjust the loop manager to announce the event number less frequently. # Makes a big difference if running over many events @@ -502,25 +459,42 @@ def main(): else: cfg.addService(CompFactory.AthenaEventLoopMgr(EventPrintoutInterval=500)) - # Add the components for reading in POOL files -- this is a specialised - # ROOT format storing structured objects like the - # ATLAS physics objects (jets etc) - from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + from HH4bAnalysis.Config.xAODEventSelectorConfig import xAODReadCfg - cfg.merge(PoolReadCfg(ConfigFlags)) + cfg.merge(xAODReadCfg(ConfigFlags)) # Add our VariableDumper CA, calling the function defined above. + from HH4bAnalysis.Config.TriggerLists import TriggerLists + + trigger_chains = TriggerLists[args.trigger_list] + do_muons = not args.meta_cache + + cfg.addSequence(CompFactory.AthSequencer("HH4bSeq"), "AthAlgSeq") cfg.merge( - VariableDumperCfg( + AnalysisAlgsCfg( ConfigFlags, - outfname=args.outFile, - is_daod_physlite=args.daod_physlite, btag_wps=args.btag_wps, - ) + vr_btag_wps=args.vr_btag_wps, + trigger_chains=trigger_chains, + metadata_cache=args.meta_cache, + do_muons=do_muons, + do_loose=args.loose, + ), + "HH4bSeq", + ) + cfg.merge( + MiniTupleCfg( + ConfigFlags, + outfname=args.outFile, + trigger_chains=trigger_chains, + working_points={"ak4": args.btag_wps, "vr": args.vr_btag_wps}, + do_muons=do_muons, + ), + "HH4bSeq", ) # Print the full job configuration - cfg.printConfig() + cfg.printConfig(summariseProps=False) # Execute the job defined in the ComponentAccumulator. # The number of events is specified by `args.evtMax` diff --git a/HH4bAnalysis/share/utils/containerNameHelper.py b/HH4bAnalysis/share/utils/containerNameHelper.py index 359a74d88..121a76bde 100644 --- a/HH4bAnalysis/share/utils/containerNameHelper.py +++ b/HH4bAnalysis/share/utils/containerNameHelper.py @@ -3,7 +3,6 @@ # custom container names used in this framework RECO_4_PFLOW_JETS_KEY = "Reco4PFlowJets" RECO_10_PFLOW_JETS_KEY = "Reco10PFlowJets" -RECO_VR_TRACK_JETS_KEY = "RecoVRTrackJets" TRUTH_4_JETS_KEY = "Truth4Jets" TRUTH_10_JETS_KEY = "Truth10Jets" MUONS_KEY = "Muons" @@ -14,7 +13,6 @@ container_map = { "DAOD_PHYS": { RECO_4_PFLOW_JETS_KEY: "AntiKt4EMPFlowJets", RECO_10_PFLOW_JETS_KEY: "AntiKt10LCTopoTrimmedPtFrac5SmallR20Jets", - RECO_VR_TRACK_JETS_KEY: "AntiKtVR30Rmax4Rmin02PV0TrackJets", TRUTH_4_JETS_KEY: "AntiKt4TruthDressedWZJets", TRUTH_10_JETS_KEY: "AntiKt10TruthTrimmedPtFrac5SmallR20Jets", MUONS_KEY: "Muons", @@ -24,7 +22,6 @@ container_map = { "DAOD_PHYSLITE": { RECO_4_PFLOW_JETS_KEY: "AnalysisJets", RECO_10_PFLOW_JETS_KEY: "?", - RECO_VR_TRACK_JETS_KEY: "?", TRUTH_4_JETS_KEY: "AntiKt4TruthDressedWZJets", TRUTH_10_JETS_KEY: "?", MUONS_KEY: "AnalysisMuons", -- GitLab From e197017d6e30b7660c0cae7361ec9ccc7526e91a Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 11 Aug 2022 13:40:34 +0200 Subject: [PATCH 13/33] adapt to new master --- HH4bAnalysis/python/Algs/Electrons.py | 38 ++++ HH4bAnalysis/python/Algs/Event.py | 83 ++++++++ HH4bAnalysis/python/Algs/Jets.py | 162 ++++++++++++++++ HH4bAnalysis/python/Algs/Muons.py | 29 +++ HH4bAnalysis/python/Algs/Photons.py | 33 ++++ HH4bAnalysis/python/Algs/Postprocessing.py | 48 +++++ HH4bAnalysis/python/Algs/Tree.py | 23 +++ HH4bAnalysis/python/Algs/__init__.py | 0 HH4bAnalysis/python/Config/Base.py | 100 ++++++++++ HH4bAnalysis/python/Config/TriggerLists.py | 45 +++++ HH4bAnalysis/python/Config/__init__.py | 0 .../python/Config/xAODEventSelectorConfig.py | 114 +++++++++++ HH4bAnalysis/python/__init__.py | 0 HH4bAnalysis/python/utils/__init__.py | 0 HH4bAnalysis/python/utils/argsHelper.py | 25 +++ .../python/utils/containerNameHelper.py | 37 ++++ HH4bAnalysis/share/VariableDumperConfig.py | 23 +-- HH4bAnalysis/share/grid_submit.py | 182 ++++++++++++++++++ HH4bAnalysis/share/hh4b-test | 117 +++++++++++ 19 files changed, 1048 insertions(+), 11 deletions(-) create mode 100644 HH4bAnalysis/python/Algs/Electrons.py create mode 100644 HH4bAnalysis/python/Algs/Event.py create mode 100644 HH4bAnalysis/python/Algs/Jets.py create mode 100644 HH4bAnalysis/python/Algs/Muons.py create mode 100644 HH4bAnalysis/python/Algs/Photons.py create mode 100644 HH4bAnalysis/python/Algs/Postprocessing.py create mode 100644 HH4bAnalysis/python/Algs/Tree.py create mode 100644 HH4bAnalysis/python/Algs/__init__.py create mode 100644 HH4bAnalysis/python/Config/Base.py create mode 100644 HH4bAnalysis/python/Config/TriggerLists.py create mode 100644 HH4bAnalysis/python/Config/__init__.py create mode 100644 HH4bAnalysis/python/Config/xAODEventSelectorConfig.py create mode 100644 HH4bAnalysis/python/__init__.py create mode 100644 HH4bAnalysis/python/utils/__init__.py create mode 100644 HH4bAnalysis/python/utils/argsHelper.py create mode 100644 HH4bAnalysis/python/utils/containerNameHelper.py create mode 100755 HH4bAnalysis/share/grid_submit.py create mode 100755 HH4bAnalysis/share/hh4b-test diff --git a/HH4bAnalysis/python/Algs/Electrons.py b/HH4bAnalysis/python/Algs/Electrons.py new file mode 100644 index 000000000..473f7b119 --- /dev/null +++ b/HH4bAnalysis/python/Algs/Electrons.py @@ -0,0 +1,38 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + +# Include, and then set up the electron analysis sequence: +from EgammaAnalysisAlgorithms.ElectronAnalysisSequence import ( + makeElectronAnalysisSequence, +) + + +def ElectronAnalysisSequenceCfg( + flags, dataType, inputContainerName, outputContainerName +): + cfg = ComponentAccumulator() + + # with ConfigurableRun3Behavior(False): + 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=inputContainerName, outputName=outputContainerName + ) + + cfg.addSequence(CompFactory.AthSequencer(electronSequence.getName())) + for alg in electronSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, electronSequence.getName()) + + return cfg diff --git a/HH4bAnalysis/python/Algs/Event.py b/HH4bAnalysis/python/Algs/Event.py new file mode 100644 index 000000000..282c73892 --- /dev/null +++ b/HH4bAnalysis/python/Algs/Event.py @@ -0,0 +1,83 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def EventSelectionAnalysisSequenceCfg(flags, dataType, grlFiles=[], loose=False): + cfg = ComponentAccumulator() + from AsgAnalysisAlgorithms.EventSelectionAnalysisSequence import ( + makeEventSelectionAnalysisSequence, + ) + + eventSelectionSequence = makeEventSelectionAnalysisSequence( + dataType, userGRLFiles=grlFiles, runEventCleaning=True + ) + + cfg.addSequence(CompFactory.AthSequencer(eventSelectionSequence.getName())) + for alg in eventSelectionSequence.getGaudiConfig2Components(): + if "PrimaryVertexSelectorAlg" in alg.getName(): + alg.MinTracks = 2 + if "EventFlagSelectorAlg" in alg.getName(): + selectionFlags = ["DFCommonJets_eventClean_LooseBad"] + selectionFlags += ["DFCommonJets_isBadBatman"] if not loose else [] + alg.FilterDescription = ( + f"selecting events passing {', '.join(selectionFlags)}" + ) + alg.selectionFlags = [f"{flag},as_char" for flag in selectionFlags] + + cfg.addEventAlgo(alg, eventSelectionSequence.getName()) + + return cfg + + +def TriggerAnalysisSequenceCfg(flags, dataType, triggerChains): + cfg = ComponentAccumulator() + from TriggerAnalysisAlgorithms.TriggerAnalysisSequence import ( + makeTriggerAnalysisSequence, + ) + + triggerSequence = makeTriggerAnalysisSequence(dataType, triggerChains=triggerChains) + + cfg.addSequence(CompFactory.AthSequencer(triggerSequence.getName())) + for alg in triggerSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, triggerSequence.getName()) + + return cfg + + +def PileupAnalysisSequenceCfg(flags, dataType, prwFiles, lumicalcFiles): + cfg = ComponentAccumulator() + from AsgAnalysisAlgorithms.PileupAnalysisSequence import makePileupAnalysisSequence + + pileupSequence = makePileupAnalysisSequence( + dataType, + userPileupConfigs=prwFiles, + userLumicalcFiles=lumicalcFiles, + autoConfig=False, + ) + pileupSequence.configure(inputName={}, outputName={}) + + cfg.addSequence(CompFactory.AthSequencer(pileupSequence.getName())) + for alg in pileupSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, pileupSequence.getName()) + + return cfg + + +def GeneratorAnalysisSequenceCfg(flags, dataType, runNumber): + cfg = ComponentAccumulator() + from AsgAnalysisAlgorithms.GeneratorAnalysisSequence import ( + makeGeneratorAnalysisSequence, + ) + + generatorSequence = makeGeneratorAnalysisSequence( + dataType, + saveCutBookkeepers=True, + runNumber=runNumber, + cutBookkeepersSystematics=True, + ) + + cfg.addSequence(CompFactory.AthSequencer(generatorSequence.getName())) + for alg in generatorSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, generatorSequence.getName()) + + return cfg diff --git a/HH4bAnalysis/python/Algs/Jets.py b/HH4bAnalysis/python/Algs/Jets.py new file mode 100644 index 000000000..be56fec30 --- /dev/null +++ b/HH4bAnalysis/python/Algs/Jets.py @@ -0,0 +1,162 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence +from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence + + +def JetAnalysisSequenceCfg( + flags, + dataType, + inputContainerName, + outputContainerName, + workingPoints, + is_daod_physlite, +): + cfg = ComponentAccumulator() + jetSequence = makeJetAnalysisSequence( + dataType, + jetCollection=inputContainerName, + postfix="smallR", + deepCopyOutput=False, + shallowViewOutput=True, + runGhostMuonAssociation=not is_daod_physlite, + enableCutflow=False, + enableKinematicHistograms=False, + runJvtUpdate=False, + runJvtSelection=True, + ) + + bTagCalibFile = ( + "xAODBTaggingEfficiency/13TeV/2022-22-13TeV-MC20-CDI-2022-07-28_v1.root" + ) + # This is the container name that is available in the CDI aboce + jetBTagContaienrName = "AntiKt4EMPFlowJets" + + for tagger_wp in workingPoints: + tagger, btag_wp = tagger_wp.split("_", 1) + makeFTagAnalysisSequence( + jetSequence, + dataType, + jetCollection=jetBTagContaienrName, + btagWP=btag_wp, + btagger=tagger, + generator="Pythia8", + minPt=20000, + postfix="", + preselection=None, + kinematicSelection=False, + noEfficiency=False, + legacyRecommendations=False, + enableCutflow=False, + ) + + jetSequence.configure( + inputName=inputContainerName, + outputName=outputContainerName, + ) + + cfg.addSequence(CompFactory.AthSequencer(jetSequence.getName())) + # Hack until this is merged: + # https://gitlab.cern.ch/atlas/athena/-/merge_requests/54939] + for alg in jetSequence.getGaudiConfig2Components(): + if "FTagSelectionAlg" in alg.getName(): + alg.selectionTool.FlvTagCutDefinitionsFileName = bTagCalibFile + if "FTagEfficiencyScaleFactorAlg" in alg.getName(): + alg.efficiencyTool.ScaleFactorFileName = bTagCalibFile + + cfg.addEventAlgo(alg, jetSequence.getName()) + + return cfg + + +def FatJetAnalysisSequenceCfg(flags, dataType, inputContainerName, outputContainerName): + cfg = ComponentAccumulator() + # with ConfigurableRun3Behavior(False): + largeRrecojetSequence = makeJetAnalysisSequence( + dataType, + jetCollection=inputContainerName, + postfix="largeR", + deepCopyOutput=False, + shallowViewOutput=True, + runGhostMuonAssociation=False, + enableCutflow=False, + enableKinematicHistograms=False, + largeRMass="Comb", + ) + + largeRrecojetSequence.configure( + inputName=inputContainerName, outputName=outputContainerName + ) + + cfg.addSequence(CompFactory.AthSequencer(largeRrecojetSequence.getName())) + for alg in largeRrecojetSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, largeRrecojetSequence.getName()) + + return cfg + + +def VRJetAnalysisSequenceCfg( + flags, dataType, inputContainerName, outputContainerName, workingPoints +): + cfg = ComponentAccumulator() + + def createVRJetSequence(): + from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence + from AnaAlgorithm.DualUseConfig import createAlgorithm + + postfix = "VR" + seq = AnaAlgSequence("JetAnalysisSequence" + postfix) + # Set up an algorithm that makes a view container + alg = createAlgorithm( + "CP::AsgViewFromSelectionAlg", "VRJetSelectionAlg" + postfix + ) + seq.append( + alg, + inputPropName="input", + outputPropName="output", + stageName="selection", + dynConfig={}, + ) + return seq + + vrJetSequence = createVRJetSequence() + + bTagCalibFile = ( + "xAODBTaggingEfficiency/13TeV/2021-22-13TeV-MC16-CDI-2021-12-02_v2.root" + ) + # This is the container name that is available in the CDI aboce + vrJetBTagContaienrName = "AntiKtVR30Rmax4Rmin02TrackJets" + for tagger_wp in workingPoints: + tagger, btag_wp = tagger_wp.split("_", 1) + makeFTagAnalysisSequence( + vrJetSequence, + dataType, + jetCollection=vrJetBTagContaienrName, + btagWP=btag_wp, + btagger=tagger, + generator="Pythia8", + minPt=10e3, + postfix="", + preselection=None, + noEfficiency=False, + legacyRecommendations=False, + enableCutflow=False, + ) + + vrJetSequence.configure( + inputName=inputContainerName, + outputName=outputContainerName, + ) + + cfg.addSequence(CompFactory.AthSequencer(vrJetSequence.getName())) + # Hack until this is merged: + # https://gitlab.cern.ch/atlas/athena/-/merge_requests/54939] + for alg in vrJetSequence.getGaudiConfig2Components(): + if "FTagSelectionAlg" in alg.getName(): + alg.selectionTool.FlvTagCutDefinitionsFileName = bTagCalibFile + if "FTagEfficiencyScaleFactorAlg" in alg.getName(): + alg.efficiencyTool.ScaleFactorFileName = bTagCalibFile + + cfg.addEventAlgo(alg, vrJetSequence.getName()) + + return cfg diff --git a/HH4bAnalysis/python/Algs/Muons.py b/HH4bAnalysis/python/Algs/Muons.py new file mode 100644 index 000000000..c9c4c85f3 --- /dev/null +++ b/HH4bAnalysis/python/Algs/Muons.py @@ -0,0 +1,29 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def MuonAnalysisSequenceCfg(flags, dataType, inputContainerName, outputContainerName): + cfg = ComponentAccumulator() + 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=inputContainerName, outputName=outputContainerName) + # print(muonSequence) # For debugging + + cfg.addSequence(CompFactory.AthSequencer(muonSequence.getName())) + for alg in muonSequence.getGaudiConfig2Components(): + if "MuonSelectionAlg" in alg.getName(): + alg.selectionTool.IsRun3Geo = min(flags.Input.RunNumber) > 400000 + cfg.addEventAlgo(alg, muonSequence.getName()) + + return cfg diff --git a/HH4bAnalysis/python/Algs/Photons.py b/HH4bAnalysis/python/Algs/Photons.py new file mode 100644 index 000000000..fae5c91a6 --- /dev/null +++ b/HH4bAnalysis/python/Algs/Photons.py @@ -0,0 +1,33 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def PhotonAnalysisSequenceCfg(flags, dataType, inputContainerName, outputContainerName): + cfg = ComponentAccumulator() + 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=inputContainerName, outputName=outputContainerName + ) + + cfg.addSequence(CompFactory.AthSequencer(photonSequence.getName())) + for alg in photonSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, photonSequence.getName()) + + return cfg diff --git a/HH4bAnalysis/python/Algs/Postprocessing.py b/HH4bAnalysis/python/Algs/Postprocessing.py new file mode 100644 index 000000000..b32f369bf --- /dev/null +++ b/HH4bAnalysis/python/Algs/Postprocessing.py @@ -0,0 +1,48 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def OverlapAnalysisSequenceCfg( + flags, + dataType, + inputNames, + outputNames, + doFatJets=True, + doMuons=True, +): + cfg = ComponentAccumulator() + from AsgAnalysisAlgorithms.OverlapAnalysisSequence import ( + makeOverlapAnalysisSequence, + ) + + overlapSequence = makeOverlapAnalysisSequence( + dataType, + inputLabel="", + outputLabel="passesOR", + linkOverlapObjects=False, + doEleEleOR=False, + doMuPFJetOR=False, + doTaus=False, + doElectrons=True, + doMuons=doMuons, + doJets=True, + doPhotons=True, + doFatJets=doFatJets, + enableUserPriority=False, + bJetLabel="", + boostedLeptons=False, + postfix="", + shallowViewOutput=True, + enableCutflow=False, + ) + overlapSequence.configure( + inputName=inputNames, + outputName=outputNames, + ) + # print(overlapSequence) # For debugging + + cfg.addSequence(CompFactory.AthSequencer(overlapSequence.getName())) + for alg in overlapSequence.getGaudiConfig2Components(): + cfg.addEventAlgo(alg, overlapSequence.getName()) + + return cfg diff --git a/HH4bAnalysis/python/Algs/Tree.py b/HH4bAnalysis/python/Algs/Tree.py new file mode 100644 index 000000000..611e4fd83 --- /dev/null +++ b/HH4bAnalysis/python/Algs/Tree.py @@ -0,0 +1,23 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def AnalysisTreeAlgCfg(flags, branches): + cfg = ComponentAccumulator() + # Create analysis mini-ntuple + treeMaker = CompFactory.getComp("CP::TreeMakerAlg")("TreeMaker") + treeMaker.TreeName = "AnalysisMiniTree" + cfg.addEventAlgo(treeMaker) + + # Add branches + ntupleMaker = CompFactory.getComp("CP::AsgxAODNTupleMakerAlg")("NTupleMaker") + ntupleMaker.TreeName = "AnalysisMiniTree" + ntupleMaker.Branches = branches + cfg.addEventAlgo(ntupleMaker) + + # Fill tree + treeFiller = CompFactory.getComp("CP::TreeFillerAlg")("TreeFiller") + treeFiller.TreeName = "AnalysisMiniTree" + cfg.addEventAlgo(treeFiller) + + return cfg diff --git a/HH4bAnalysis/python/Algs/__init__.py b/HH4bAnalysis/python/Algs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/HH4bAnalysis/python/Config/Base.py b/HH4bAnalysis/python/Config/Base.py new file mode 100644 index 000000000..55b41d28d --- /dev/null +++ b/HH4bAnalysis/python/Config/Base.py @@ -0,0 +1,100 @@ +from enum import Enum +import json + + +class SampleTypes(Enum): + mc20a = "r13167" + mc20d = "r13144" + mc20e = "r13145" + + +def cache_metadata(path): + from AthenaConfiguration.AutoConfigFlags import _fileMetaData + + all_md = {} + for f, m in _fileMetaData.items(): + all_md[f] = { + "metadata": m.metadata, + "level": m.metAccessLevel, + } + with open(path, "w") as cached: + json.dump(all_md, cached) + + +def update_metadata(path): + from AthenaConfiguration.AutoConfigFlags import _fileMetaData + + if not path.exists(): + return + with open(path) as cached_file: + all_cached = json.load(cached_file) + for f, m in _fileMetaData.items(): + cached = all_cached.get(f) + if cached: + md = _fileMetaData[f] + md.metadata.update(cached["metadata"]) + md.filename = f + md.metAccessLevel = cached["level"] + + +def pileupConfigFiles(fileMD): + """Return the PRW (Pileup ReWeighting) config files and lumicalc files""" + tags = fileMD["AMITag"] + dsid = fileMD["mc_channel_number"] + split_tags = tags.split("_") + # Figure out which MC we are using + if SampleTypes.mc20a.value in split_tags: + subcampaign = SampleTypes.mc20a + elif SampleTypes.mc20d.value in split_tags: + subcampaign = SampleTypes.mc20d + elif SampleTypes.mc20e.value in split_tags: + subcampaign = SampleTypes.mc20e + else: + raise LookupError(f"Cannot determine subcampaign for DSID {dsid}") + + lumicalc_files = getLumicalcFiles(subcampaign) + prw_files = getPrwFiles(dsid, subcampaign, tags) + + return prw_files, lumicalc_files + + +def getLumicalcFiles(subcampaign): + list = [] + if subcampaign == SampleTypes.mc20a: + list.extend( + ( + "GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root", # noqa + "GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root", # noqa + ) + ) + if subcampaign == SampleTypes.mc20d: + list.append( + "GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.lumicalc.OflLumi-13TeV-010.root", # noqa + ) + if subcampaign == SampleTypes.mc20e: + list.append( + "GoodRunsLists/data18_13TeV/20190318/ilumicalc_histograms_None_348885-364292_OflLumi-13TeV-010.root" # noqa + ) + + return list + + +def getPrwFiles(dsid, subcampaign, tags): + actual_mu = [] + prw_files = [] + if subcampaign == SampleTypes.mc20d: + actual_mu.append( + "GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.actualMu.OflLumi-13TeV-010.root" # noqa + ) + if subcampaign == SampleTypes.mc20e: + actual_mu.append( + "GoodRunsLists/data18_13TeV/20190318/physics_25ns_Triggerno17e33prim.actualMu.OflLumi-13TeV-010.root" # noqa + ) + + if dsid: + dsid_as_str = str(dsid) + prw_files.append( + f"dev/PileupReweighting/share/DSID{dsid_as_str[:3]}xxx/pileup_{subcampaign.name}_dsid{dsid_as_str}_{'AFII' if 'a' in tags else 'FS'}.root" # noqa + ) + + return prw_files + actual_mu diff --git a/HH4bAnalysis/python/Config/TriggerLists.py b/HH4bAnalysis/python/Config/TriggerLists.py new file mode 100644 index 000000000..38d2fa279 --- /dev/null +++ b/HH4bAnalysis/python/Config/TriggerLists.py @@ -0,0 +1,45 @@ +TriggerLists = { + "Run3": [ + "HLT_j80c_020jvt_j55c_020jvt_j28c_020jvt_j20c_020jvt_SHARED_3j20c_020jvt_bdl1d82_pf_ftf_presel2c20XX2c20b85_L1J45p0ETA21_3J15p0ETA25", # noqa + "HLT_j80c_020jvt_j55c_020jvt_j28c_020jvt_j20c_020jvt_SHARED_3j20c_020jvt_bdl1r85_pf_ftf_presel2c20XX2c20b85_L1J45p0ETA21_3J15p0ETA25", # noqa + "HLT_j80c_020jvt_j55c_020jvt_j28c_020jvt_j20c_020jvt_SHARED_2j20c_020jvt_bdl1d77_pf_ftf_presel2c20XX2c20b85_L1J45p0ETA21_3J15p0ETA25", # noqa + "HLT_j80c_020jvt_j55c_020jvt_j28c_020jvt_j20c_020jvt_SHARED_2j20c_020jvt_bdl1r77_pf_ftf_presel2c20XX2c20b85_L1J45p0ETA21_3J15p0ETA25", # noqa + "HLT_j80c_020jvt_j55c_020jvt_j28c_020jvt_j20c_020jvt_SHARED_2j20c_020jvt_bdl1d77_pf_ftf_presel2c20XX2c20b85_L1MU8F_2J15_J20", # noqa + "HLT_j80c_020jvt_j55c_020jvt_j28c_020jvt_j20c_020jvt_SHARED_2j20c_020jvt_bdl1r77_pf_ftf_presel2c20XX2c20b85_L1MU8F_2J15_J20", # noqa + "HLT_2j35c_020jvt_bdl1d60_2j35c_020jvt_pf_ftf_presel2j25XX2j25b85_L14J15p0ETA25", # noqa + "HLT_2j35c_020jvt_bdl1r60_2j35c_020jvt_pf_ftf_presel2j25XX2j25b85_L14J15p0ETA25", # noqa + "HLT_j150_2j55_0eta290_020jvt_bdl1d70_pf_ftf_preselj80XX2j45b90_L1J85_3J30", # noqa + "HLT_j150_2j55_0eta290_020jvt_bdl1r70_pf_ftf_preselj80XX2j45b90_L1J85_3J30", # noqa + ], + "Run2": [ + # 2015 (not used in the resolved analysis): + "HLT_2j35_btight_2j35_L13J25.0ETA23", + "HLT_j100_2j55_bmedium", + "HLT_j225_bloose", + "HLT_j360_a10_lcw_sub_L1J100", + # 2016: + "HLT_j175_bmv2c2040_split", + "HLT_j225_bmv2c2060_split", + "HLT_2j35_bmv2c2060_split_2j35_L14J15.0ETA25", + "HLT_2j55_bmv2c2060_split_ht300_L14J15", + "HLT_j100_2j55_bmv2c2060_split", + "HLT_j150_bmv2c2060_split_j50_bmv2c2060_split", + "HLT_j420_a10_lcw_L1J100", + # 2017: + "HLT_j175_gsc225_bmv2c1040_split", # also 2018 + "HLT_j225_gsc275_bmv2c1060_split", + "HLT_j150_gsc175_bmv2c1060_split_j45_gsc60_bmv2c1060_split", # and 2018 + "HLT_j110_gsc150_boffperf_split_2j35_gsc55_bmv2c1070_split_L1J85_3J30", + "HLT_2j15_gsc35_bmv2c1040_split_2j15_gsc35_boffperf_split_L14J15.0ETA25", + "HLT_2j35_gsc55_bmv2c1050_split_ht300_L1HT190-J15s5.ETA21", + "HLT_2j35_gsc55_bmv2c1060_split_ht300_L1HT190-J15s5.ETA21", # (below 1.5e34) + "HLT_j420_a10t_lcw_jes_40smcINF_L1J100", + "HLT_j390_a10t_lcw_jes_30smcINF_L1J100", # also 2018 + # 2018: + "HLT_j225_gsc275_bhmv2c1060_split", + "HLT_j110_gsc150_boffperf_split_2j45_gsc55_bmv2c1070_split_L1J85_3J30", + "HLT_2j35_bmv2c1060_split_2j35_L14J15.0ETA25", + "HLT_2j45_gsc55_bmv2c1050_split_ht300_L1HT190-J15s5.ETA21", + "HLT_j420_a10t_lcw_jes_35smcINF_L1J100", + ], +} diff --git a/HH4bAnalysis/python/Config/__init__.py b/HH4bAnalysis/python/Config/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/HH4bAnalysis/python/Config/xAODEventSelectorConfig.py b/HH4bAnalysis/python/Config/xAODEventSelectorConfig.py new file mode 100644 index 000000000..3822828a4 --- /dev/null +++ b/HH4bAnalysis/python/Config/xAODEventSelectorConfig.py @@ -0,0 +1,114 @@ +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +# @file xAODHybridSelectorConfig +# @purpose make the Athena framework read a set of xAOD files to emulate the +# usual TEvent event loop ... BUT READ METADATA WITH POOL! +# Converted from ReadAthenaxAODHybrid.py +# @author Teng Jian Khoo +# + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from AthenaCommon import Logging +from AthenaCommon import Constants + +# suppress the event loop heartbeat as it is somewhat I/O hungry for +# no real gain in n-tuple reading/writing scenarii +# if not hasattr(svcMgr, theApp.EventLoop): +# svcMgr += getattr(CfgMgr, theApp.EventLoop)() +# evtloop = getattr(svcMgr, theApp.EventLoop) +# try: +# evtloop.EventPrintoutInterval = 10000 +# except Exception: +# msg.info('disabling event loop heartbeat... [failed]') +# msg.info('performances might be sub-par... sorry.') +# pass + +from enum import IntEnum + + +# Duplicate here because it's probably more efficient than importing from ROOT +class xAODAccessMode(IntEnum): + BRANCH_ACCESS = 0 + CLASS_ACCESS = 1 + ATHENA_ACCESS = 2 + + +# Default to the most efficient access method +def xAODReadCfg(configFlags, AccessMode=xAODAccessMode.CLASS_ACCESS): + """ + Creates a ComponentAccumulator instance containing the + athena services required for xAOD file reading + """ + + msg = Logging.logging.getLogger("ReadAthenaxAODHybrid") + msg.debug( + "Configuring Athena for reading xAOD files" + + " (via TEvent, with POOL for Metadata)..." + ) + + result = ComponentAccumulator() + + result.addService( + CompFactory.EvtPersistencySvc( + "EventPersistencySvc", + ) + ) + result.addService( + CompFactory.MetaDataSvc("MetaDataSvc", MetaDataContainer="MetaDataHdr") + ) + result.addService(CompFactory.StoreGateSvc("MetaDataStore")) + # Suppress some uninformative messages + result.addService(CompFactory.PoolSvc("PoolSvc", OutputLevel=Constants.WARNING)) + + # result.addService(CompFactory.THistSvc()) + result.addService(CompFactory.Athena.xAODCnvSvc()) + result.addService( + CompFactory.ProxyProviderSvc("ProxyProviderSvc", ProviderNames=["MetaDataSvc"]) + ) + result.addService( + CompFactory.Athena.xAODEventSelector( + "EventSelector", + InputCollections=configFlags.Input.Files, + SkipEvents=configFlags.Exec.SkipEvents, + AccessMode=AccessMode, + ReadMetaDataWithPool=True, + ) + ) + evSel = result.getService("EventSelector") + + result.setAppProperty("EvtSel", evSel.getFullJobOptName()) + + msg.debug( + "Configuring Athena for reading ROOT files" + + " (via TEvent, with POOL for Metadata)... [OK]" + ) + + return result + + +if __name__ == "__main__": + from AthenaConfiguration.AllConfigFlags import ConfigFlags + import os + + asg_test_file_mc = os.environ["ASG_TEST_FILE_MC"] + ConfigFlags.Input.Files = [asg_test_file_mc] + + import sys + + if len(sys.argv) > 1: + ConfigFlags.Input.Files = [sys.argv[1]] + ConfigFlags.lock() + + AccessMode = xAODAccessMode.CLASS_ACCESS + if len(sys.argv) > 2: + AccessMode = xAODAccessMode(int(sys.argv[2])) + + from AthenaConfiguration.MainServicesConfig import MainServicesCfg + from AthenaCommon.Configurable import ConfigurableRun3Behavior + + with ConfigurableRun3Behavior(): + cfg = MainServicesCfg(ConfigFlags) + cfg.merge(xAODReadCfg(ConfigFlags, AccessMode)) + + cfg.run(10) diff --git a/HH4bAnalysis/python/__init__.py b/HH4bAnalysis/python/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/HH4bAnalysis/python/utils/__init__.py b/HH4bAnalysis/python/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/HH4bAnalysis/python/utils/argsHelper.py b/HH4bAnalysis/python/utils/argsHelper.py new file mode 100644 index 000000000..a93eb3ef9 --- /dev/null +++ b/HH4bAnalysis/python/utils/argsHelper.py @@ -0,0 +1,25 @@ +import sys + + +def checkArgs(flags, args, parser): + if "StreamDAOD_PHYSLITE" in flags.Input.ProcessingTags: + input_stream_format = "DAOD_PHYSLITE" + elif "StreamDAOD_PHYS" in flags.Input.ProcessingTags: + input_stream_format = "DAOD_PHYS" + else: + input_stream_format = "other" + + if args.daod_physlite and input_stream_format != "DAOD_PHYSLITE": + print( + f"Input file is {input_stream_format} but --daod-physlite flag was " + f"{'given' if args.daod_physlite else 'not given'}. Usage: {parser.prog} -h" + ) + sys.exit(-1) + + is_input_mc = flags.Input.isMC + if args.mc is not is_input_mc: + print( + f"Input file is {'MC' if is_input_mc else 'Data'} but --mc flag was " + f"{'given' if args.mc else 'not given'}. Usage: {parser.prog} -h" + ) + sys.exit(-1) diff --git a/HH4bAnalysis/python/utils/containerNameHelper.py b/HH4bAnalysis/python/utils/containerNameHelper.py new file mode 100644 index 000000000..08f2cc10a --- /dev/null +++ b/HH4bAnalysis/python/utils/containerNameHelper.py @@ -0,0 +1,37 @@ +# custom container names used in this framework +RECO_4_PFLOW_JETS_KEY = "Reco4PFlowJets" +RECO_10_PFLOW_JETS_KEY = "Reco10PFlowJets" +VR_JETS_KEY = "VRJets" +TRUTH_4_JETS_KEY = "Truth4Jets" +TRUTH_10_JETS_KEY = "Truth10Jets" +MUONS_KEY = "Muons" +ELECTRONS_KEY = "Electrons" +PHOTONS_KEY = "Photons" + +container_map = { + "DAOD_PHYS": { + RECO_4_PFLOW_JETS_KEY: "AntiKt4EMPFlowJets", + RECO_10_PFLOW_JETS_KEY: "AntiKt10LCTopoTrimmedPtFrac5SmallR20Jets", + VR_JETS_KEY: "AntiKtVR30Rmax4Rmin02PV0TrackJets", + TRUTH_4_JETS_KEY: "AntiKt4TruthDressedWZJets", + TRUTH_10_JETS_KEY: "AntiKt10TruthTrimmedPtFrac5SmallR20Jets", + MUONS_KEY: "Muons", + ELECTRONS_KEY: "Electrons", + PHOTONS_KEY: "Photons", + }, + "DAOD_PHYSLITE": { + RECO_4_PFLOW_JETS_KEY: "AnalysisJets", + RECO_10_PFLOW_JETS_KEY: "", + VR_JETS_KEY: "", + TRUTH_4_JETS_KEY: "AntiKt4TruthDressedWZJets", + TRUTH_10_JETS_KEY: "", + MUONS_KEY: "AnalysisMuons", + ELECTRONS_KEY: "AnalysisElectrons", + PHOTONS_KEY: "AnalysisPhotons", + }, +} + + +def getContainerName(qualitycontainerdesc, daodphyslite=False): + format_key = "DAOD_PHYSLITE" if daodphyslite else "DAOD_PHYS" + return container_map[format_key][qualitycontainerdesc] diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 41fc6ee40..4e1f81263 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -13,26 +13,26 @@ import sys from pathlib import Path from AthenaCommon import Logging -from AthenaConfiguration.AutoConfigFlags import GetFileMD from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory -from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg +from AthenaConfiguration.AutoConfigFlags import GetFileMD +from HH4bAnalysis.Config.Base import pileupConfigFiles, cache_metadata, update_metadata from HH4bAnalysis.Algs.Event import ( - EventSelectionAnalysisSequenceCfg, GeneratorAnalysisSequenceCfg, - PileupAnalysisSequenceCfg, TriggerAnalysisSequenceCfg, + PileupAnalysisSequenceCfg, + EventSelectionAnalysisSequenceCfg, ) +from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg +from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg +from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg from HH4bAnalysis.Algs.Jets import ( - FatJetAnalysisSequenceCfg, JetAnalysisSequenceCfg, + FatJetAnalysisSequenceCfg, VRJetAnalysisSequenceCfg, ) -from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg -from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg from HH4bAnalysis.Algs.Postprocessing import OverlapAnalysisSequenceCfg from HH4bAnalysis.Algs.Tree import AnalysisTreeAlgCfg -from HH4bAnalysis.Config.Base import cache_metadata, pileupConfigFiles, update_metadata from HH4bAnalysis.utils.containerNameHelper import getContainerName log = Logging.logging.getLogger("VariableDumperConfig") @@ -177,7 +177,7 @@ def AnalysisAlgsCfg( doPRW = _is_mc_phys(flags) log.info( - f"Do PRW is {doPRW}. {'Add' if doPRW else 'Skip'} pileup re-weight sequence" + f"Do PRW is {doPRW}. " f"{'Add' if doPRW else 'Skip'} pileup re-weight sequence" ) if doPRW: try: @@ -410,7 +410,7 @@ def MiniTupleCfg( ) analysisTreeBranches += getFourMomBranches(containers["vrJet"], "vrjet") analysisTreeBranches += [ - f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" + f"{containers['vrJet']}.ftag_select_{btag_wp}" f" -> vrjet_%SYS%_{btag_wp}" for btag_wp in working_points["vr"] ] @@ -442,10 +442,11 @@ def main(): # Get a ComponentAccumulator setting up the standard components # needed to run an Athena job. + from AthenaConfiguration.MainServicesConfig import MainServicesCfg + # Setting temporarily needed for Run 3 code, to generate python # Configurable objects for deduplication from AthenaCommon.Configurable import ConfigurableRun3Behavior - from AthenaConfiguration.MainServicesConfig import MainServicesCfg with ConfigurableRun3Behavior(): diff --git a/HH4bAnalysis/share/grid_submit.py b/HH4bAnalysis/share/grid_submit.py new file mode 100755 index 000000000..00c70736b --- /dev/null +++ b/HH4bAnalysis/share/grid_submit.py @@ -0,0 +1,182 @@ +#!/bin/env python + +import os +import argparse +import datetime +import subprocess + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--mc-list", help="Text file containing MC datasets") + parser.add_argument("--data-list", help="Text file containing data datasets") + parser.add_argument( + "--campaign", + default="HH4b.%Y_%m_%d", + help=( + "The name of the campaign. Will be prepended to the output dataset" + " name. Can include datetime.strftime replacement fields" + ), + ) + parser.add_argument( + "--asetup", + help="The asetup command, in case it cannot be read from the environment", + ) + # parser.add_argument("--dest-se", default="DESY-ZN_LOCALGROUPDISK", + # help="An RSE to duplicate the results to") + parser.add_argument("--excluded-site", help="Any sites to exclude when running") + parser.add_argument("--nGBperJob", default="2", help="How many GB required per job") + # parser.add_argument("--resubmit", action="store_true", + # help="Run in 'resubmission' mode. This reads in information + # from an existing task and resubmits the dead tasks. + # For this mode you don't need the mc and data lists") + + args = parser.parse_args() + + # Prepare some of the prun options here + submit_opts = { + "mergeOutput": True, + "outputs": "TREE:output-hh4b.root", + "writeInputToTxt": "IN:in.txt", + "useAthenaPackages": True, + # "noSubmit": True, # only creates tarball but doesn't submit + } + + # if args.dest-se is not None: + # submit_opts["destSE"] = args.dest-se + # if args.excluded-site is not None: + # submit_opts["excludedSite"] = args.excluded-Site + # if args.nGBperJob is not None: + # submit_opts["nGBPerJob"] = args.nGBperJob + + if args.asetup is None: + atlas_project = os.environ["AtlasProject"] + + project_dir = os.environ["{0}_DIR".format(atlas_project)] + project_version = os.environ["{0}_VERSION".format(atlas_project)] + + if project_dir.startswith("/cvmfs/atlas-nightlies.cern.ch"): + raise ValueError( + "Cannot deduce the asetup command for a nightly!" + + " Use the --asetup option" + ) + submit_opts["athenaTag"] = ",".join([atlas_project, project_version]) + else: + submit_opts["athenaTag"] = args.asetup + + nickname = getGridNickname() + if not nickname: + raise OSError( + 1, + "Could not find proxy information." + + ' Try typing "voms-proxy-init -voms atlas" and try again', + ) + + proc = subprocess.Popen( + [ + "prun", + "--outDS", + "user.{0}.NONE".format(nickname), + "--exec", + "NONE", + "--noSubmit", + "--useAthenaPackages", + "--outTarBall", + "code.tar.gz", + ] + ) + + if proc.wait() != 0: + raise OSError(proc.returncode, "Failed to create tarball") + + submit_opts["inTarBall"] = "code.tar.gz" + # submit_opts["allowTaskDuplication"] = True + + campaign = datetime.datetime.now().strftime(args.campaign) + + io_list = [] + if args.mc_list is not None: + with open(args.mc_list) as fp: + mc_list = fp.readlines() + for line in mc_list: + line = line.strip() + if line.startswith("*"): + continue + if not line: + continue + ds_name = line.rpartition(":")[2] + project, dsid, physics_short, prod_step, dtype, tags = ds_name.split(".") + io_list.append( + { + "inDS": ds_name, + "outDS": "user.{0}.{1}.{2}.{3}.{4}".format( + nickname, campaign, dsid, physics_short, tags + ), + } + ) + + if args.data_list is not None: + with open(args.data_list) as fp: + data_list = fp.readlines() + for line in data_list: + line = line.strip() + if line.startswith("*"): + continue + if not line: + continue + ds_name = line.rpartition(":")[2] + split = ds_name.split(".") + io_list.append( + { + "inDS": ds_name, + "outDS": "user.{0}.{1}.{2}.{3}".format( + nickname, campaign, split[0], split[1] + ), + } + ) + + if not io_list: + raise ValueError("No inputs defined") + + for io in io_list: + exec_cmd = "VariableDumperConfig.py --filesInput %IN --outFile {0}".format( + submit_opts["outputs"].removeprefix("TREE:") + ) + if args.mc_list: + exec_cmd = "VariableDumperConfig.py --filesInput %IN --outFile {0}".format( + submit_opts["outputs"].removeprefix("TREE:") + ) + cmd = ["prun", "--inDS", io["inDS"], "--outDS", io["outDS"], "--exec", exec_cmd] + + for k, v in submit_opts.items(): + if isinstance(v, bool): + if v: + cmd += ["--{0}".format(k)] + else: + if isinstance(v, (list, tuple)): + v = ",".join(map(str, v)) + + cmd += ["--{0}".format(k), v] + + print(" ".join(cmd)) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate() + print(out.decode("utf-8"), err.decode("utf-8")) + if proc.returncode != 0: + raise OSError(proc.returncode, err) + + +def getGridNickname(): + try: + voms_proxy_info = subprocess.check_output(["voms-proxy-info", "--all"]) + voms_proxy_info = voms_proxy_info.decode("utf-8") + nickname_index = voms_proxy_info.find("nickname") + nickname_parts = voms_proxy_info[nickname_index:].split() + nickname = nickname_parts[2] + except Exception: + nickname = "" + return nickname + + +if __name__ == "__main__": + main() diff --git a/HH4bAnalysis/share/hh4b-test b/HH4bAnalysis/share/hh4b-test new file mode 100755 index 000000000..789d18e35 --- /dev/null +++ b/HH4bAnalysis/share/hh4b-test @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +set -Eeu + + +################################################ +# mode-based switches +################################################ + +# standard samples +PHYS_TTBAR=ttbar.410470.PHYS.e6337_s3681_r13167_p5169.pool.root +declare -A DATAFILES=( + [ntuple-fast]=${PHYS_TTBAR} + [ntuple]=${PHYS_TTBAR} +) + +declare -A TESTS=( + [ntuple-fast]=ntuple-dump-fast + [ntuple]=ntuple-dump +) + +ntuple-dump() { + VariableDumperConfig.py -o --filesInput $1 --trigger-list "Run2" +} +ntuple-dump-fast() { + VariableDumperConfig.py -oc --filesInput $1 --trigger-list "Run2" +} + +################################################ +# parse arguments +################################################ + +ALL_MODES=${!TESTS[*]} + +print-usage() { + echo "usage: ${0##*/} [-h] [-d <dir>] (${ALL_MODES[*]// /|})" 1>&2 +} + +usage() { + print-usage + exit 1; +} + +help() { + print-usage + cat <<EOF + +The ${0##*/} utility will download a test DAOD file and run it. + +Options: + -d <dir>: specify directory to run in + -h: print help + +If no -d argument is given we'll create one in /tmp and work there. + +EOF + exit 1 +} + +DIRECTORY="" +DATA_URL=https://gitlab.cern.ch/dguest/hh4b-test-files/-/raw/master/ + +while getopts ":d:h" o; do + case "${o}" in + d) DIRECTORY=${OPTARG} ;; + h) help ;; + *) usage ;; + esac +done +shift $((OPTIND-1)) + +if (( $# != 1 )) ; then + usage +fi + +MODE=$1 + + +############################################ +# Check that all the modes / paths exist +############################################ +# +if [[ ! ${DATAFILES[$MODE]+x} ]]; then usage; fi +DOWNLOAD_PATH=${DATAFILES[$MODE]} +FILE=${DOWNLOAD_PATH##*/} + +if [[ ! ${TESTS[$MODE]+x} ]]; then usage; fi +RUN=${TESTS[$MODE]} + + +############################################# +# now start doing stuff +############################################# +# +if [[ -z ${DIRECTORY} ]] ; then + DIRECTORY=$(mktemp -d) + echo "running in ${DIRECTORY}" >&2 +fi + +if [[ ! -d ${DIRECTORY} ]]; then + if [[ -e ${DIRECTORY} ]] ; then + echo "${DIRECTORY} is not a directory" >&2 + exit 1 + fi + mkdir ${DIRECTORY} +fi +cd $DIRECTORY + +# get files +if [[ ! -f ${FILE} ]] ; then + echo "getting file ${FILE}" >&2 + curl -s ${DATA_URL}/${DOWNLOAD_PATH} > ${FILE} +fi + +# now run the test +$RUN $FILE + -- GitLab From 6cf961046cec25a9efb86f70668e3e3296b3284e Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 11 Aug 2022 14:49:00 +0200 Subject: [PATCH 14/33] progress --- HH4bAnalysis/CMakeLists.txt | 6 ++++-- HH4bAnalysis/src/VariableDumperAlg.cxx | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/HH4bAnalysis/CMakeLists.txt b/HH4bAnalysis/CMakeLists.txt index b78c7427c..7ff765547 100644 --- a/HH4bAnalysis/CMakeLists.txt +++ b/HH4bAnalysis/CMakeLists.txt @@ -17,7 +17,9 @@ atlas_add_library(HH4bAnalysisLib # Build the Athena component library atlas_add_component(HH4bAnalysis src/VariableDumperAlg.cxx + src/DiHiggsAnalysis.cxx src/tools/NTrkVertexCounter.cxx + src/tools/kLargestJets.cxx src/components/*.cxx LINK_LIBRARIES GaudiKernel @@ -38,12 +40,12 @@ atlas_install_scripts( share/VariableDumperConfig.py share/grid_submit.py share/hh4b-test - ) +) atlas_install_python_modules( python/Algs python/Config python/utils - ) +) # atlas_install_data( data/* ) # You can access your data from code using path resolver, e.g. diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 55ae24769..d92ee14d0 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -52,10 +52,10 @@ namespace HH4B "%SYS%", sys)); ATH_MSG_VERBOSE("Will apply sysname \"" << sysname << "\" for event"); - // Do something with Eventinfo + + // get the xAOD objects SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey); ATH_CHECK(eventInfo.isValid()); - const xAOD::ElectronContainer *electrons(nullptr); ATH_CHECK(m_electronHandle.retrieve(electrons, sys)); const xAOD::PhotonContainer *photons(nullptr); @@ -64,13 +64,14 @@ namespace HH4B ATH_CHECK(m_muonHandle.retrieve(muons, sys)); const xAOD::JetContainer *antiKt4RecoJets(nullptr); ATH_CHECK(m_jetsmallRHandle.retrieve(antiKt4RecoJets, sys)); + const xAOD::JetContainer *antiKt10RecoJets(nullptr); if (!m_jetlargeRHandle.empty()) { - const xAOD::JetContainer *antiKt10RecoJets(nullptr); ATH_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); } const xAOD::JetContainer *VRTrackJets(nullptr); ATH_CHECK(m_VRtrackjetHandle.retrieve(VRTrackJets, sys)); + for (auto jet : *antiKt4RecoJets) { const xAOD::BTagging *bjet = @@ -97,10 +98,11 @@ namespace HH4B // TODO: make configurable with which btagging WP Higgs candidates are // created + // create the analysis object DiHiggsAnalysis hh4b_analysis; hh4b_analysis.makeResolvedAnalysis(antiKt4RecoJets); hh4b_analysis.makeBoostedAnalysis(antiKt10RecoJets); - hh4b_analysis.decorateHiggsVars(*eventInfo); + hh4b_analysis.decorateHiggsVars(*eventInfo) } return StatusCode::SUCCESS; -- GitLab From 0ff77215d474e6a81cc47650f6057fd97aa752eb Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Fri, 12 Aug 2022 11:06:15 +0200 Subject: [PATCH 15/33] bug on untrimmed large R --- HH4bAnalysis/python/Algs/Jets.py | 14 +- HH4bAnalysis/share/VariableDumperAlgConfig.py | 520 ++++++++++++++++++ HH4bAnalysis/share/VariableDumperConfig.py | 56 +- HH4bAnalysis/src/VariableDumperAlg.cxx | 25 +- HH4bAnalysis/src/VariableDumperAlg.h | 4 +- 5 files changed, 570 insertions(+), 49 deletions(-) create mode 100755 HH4bAnalysis/share/VariableDumperAlgConfig.py diff --git a/HH4bAnalysis/python/Algs/Jets.py b/HH4bAnalysis/python/Algs/Jets.py index be56fec30..6ff8ee601 100644 --- a/HH4bAnalysis/python/Algs/Jets.py +++ b/HH4bAnalysis/python/Algs/Jets.py @@ -1,7 +1,7 @@ from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory -from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence +from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence def JetAnalysisSequenceCfg( @@ -30,14 +30,14 @@ def JetAnalysisSequenceCfg( "xAODBTaggingEfficiency/13TeV/2022-22-13TeV-MC20-CDI-2022-07-28_v1.root" ) # This is the container name that is available in the CDI aboce - jetBTagContaienrName = "AntiKt4EMPFlowJets" + jetBTagContainerName = "AntiKt4EMPFlowJets" for tagger_wp in workingPoints: tagger, btag_wp = tagger_wp.split("_", 1) makeFTagAnalysisSequence( jetSequence, dataType, - jetCollection=jetBTagContaienrName, + jetCollection=jetBTagContainerName, btagWP=btag_wp, btagger=tagger, generator="Pythia8", @@ -125,19 +125,19 @@ def VRJetAnalysisSequenceCfg( "xAODBTaggingEfficiency/13TeV/2021-22-13TeV-MC16-CDI-2021-12-02_v2.root" ) # This is the container name that is available in the CDI aboce - vrJetBTagContaienrName = "AntiKtVR30Rmax4Rmin02TrackJets" + vrJetBTagContainerName = "AntiKtVR30Rmax4Rmin02TrackJets" for tagger_wp in workingPoints: tagger, btag_wp = tagger_wp.split("_", 1) makeFTagAnalysisSequence( vrJetSequence, dataType, - jetCollection=vrJetBTagContaienrName, + jetCollection=vrJetBTagContainerName, btagWP=btag_wp, btagger=tagger, - generator="Pythia8", minPt=10e3, - postfix="", + postfix=btag_wp, preselection=None, + kinematicSelection=True, noEfficiency=False, legacyRecommendations=False, enableCutflow=False, diff --git a/HH4bAnalysis/share/VariableDumperAlgConfig.py b/HH4bAnalysis/share/VariableDumperAlgConfig.py new file mode 100755 index 000000000..43e64e9cb --- /dev/null +++ b/HH4bAnalysis/share/VariableDumperAlgConfig.py @@ -0,0 +1,520 @@ +#!/bin/env python + +# +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# + +# +# VariableDumperConfig.py +# A simple CA file to create a tree of variables +# + +import sys +from pathlib import Path + +from AthenaCommon import Logging +from AthenaConfiguration.AutoConfigFlags import GetFileMD +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg +from HH4bAnalysis.Algs.Event import ( + EventSelectionAnalysisSequenceCfg, + GeneratorAnalysisSequenceCfg, + PileupAnalysisSequenceCfg, + TriggerAnalysisSequenceCfg, +) +from HH4bAnalysis.Algs.Jets import ( + FatJetAnalysisSequenceCfg, + JetAnalysisSequenceCfg, + VRJetAnalysisSequenceCfg, +) +from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg +from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg +from HH4bAnalysis.Algs.Postprocessing import OverlapAnalysisSequenceCfg +from HH4bAnalysis.Algs.Tree import AnalysisTreeAlgCfg +from HH4bAnalysis.Config.Base import cache_metadata, pileupConfigFiles, update_metadata +from HH4bAnalysis.utils.containerNameHelper import getContainerName + +log = Logging.logging.getLogger("VariableDumperConfig") + + +def defineArgs(ConfigFlags): + # Generate a parser and add an output file argument, then retrieve the args + parser = ConfigFlags.getArgumentParser() + parser.add_argument( + "--outFile", + type=str, + default="analysis-variables.root", + help="Output file name", + ) + parser.add_argument( + "--btag-wps", + type=str, + nargs="*", + default=[ + "DL1dv00_FixedCutBEff_77", + "DL1dv00_FixedCutBEff_85", + ], + help="Btag working points default %(default)s", + ) + parser.add_argument( + "--vr-btag-wps", + type=str, + nargs="*", + default=[ + "DL1r_FixedCutBEff_77", + "DL1r_FixedCutBEff_85", + ], + help="VR Jets btag working points default %(default)s", + ) + parser.add_argument( + "--trigger-list", + type=str, + default="Run3", + help="Trigger list to use, default: %(default)s", + ) + parser.add_argument( + "-c", + "--meta-cache", + type=Path, + default=None, + nargs="?", + const=Path("metadata.json"), + help="use metadata cache file, defaults to %(const)s", + ) + parser.add_argument( + "-o", + "--loose", + action="store_true", + help="use loose event cleaning (to get something to pass)", + ) + return parser + + +def _is_physlite(flags): + return flags.Input.ProcessingTags == ["StreamDAOD_PHYSLITE"] + + +def _is_mc_phys(flags): + return flags.Input.isMC and not _is_physlite(flags) + + +def _get_container_names(flags): + is_daod_physlite = _is_physlite(flags) + inputs = dict( + reco4Jet=getContainerName("Reco4PFlowJets", is_daod_physlite), + reco10Jet=getContainerName("Reco10PFlowJets", is_daod_physlite), + vrJet=getContainerName("VRJets", is_daod_physlite), + muons=getContainerName("Muons", is_daod_physlite), + electrons=getContainerName("Electrons", is_daod_physlite), + photons=getContainerName("Photons", is_daod_physlite), + ) + outputs = dict( + reco4Jet=f"Analysis{inputs['reco4Jet']}_%SYS%", + muons=f"Analysis{inputs['muons']}_%SYS%", + electrons=f"Analysis{inputs['electrons']}_%SYS%", + photons=f"Analysis{inputs['photons']}_%SYS%", + ) + if inputs["reco10Jet"]: + outputs["reco10Jet"] = f"Analysis{inputs['reco10Jet']}_%SYS%" + else: + outputs["reco10Jet"] = "" + if inputs["vrJet"]: + outputs["vrJet"] = f"Analysis{inputs['vrJet']}_%SYS%" + else: + outputs["vrJet"] = "" + return {"inputs": inputs, "outputs": outputs} + + +# 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 AnalysisAlgsCfg( + flags, + btag_wps, + vr_btag_wps, + trigger_chains=[], + do_muons=True, + metadata_cache=None, + do_loose=False, +): + fileMD = GetFileMD(flags.Input.Files[0]) + if metadata_cache: + update_metadata(metadata_cache) + dataType = "mc" if flags.Input.isMC else "data" + is_daod_physlite = _is_physlite(flags) + log.info( + f"Self-configured: dataType: '{dataType}', is PHYSLITE? {is_daod_physlite}" + ) + + log.debug(f"Containers available in dataset: {flags.Input.Collections}") + + # TODO: no DL1d branches in PHYSLITE yet + if is_daod_physlite: + btag_wps = [wp.replace("DL1dv00", "DL1r") for wp in btag_wps] + + cfg = ComponentAccumulator() + + # Create SystematicsSvc explicitly: + cfg.addService(CompFactory.getComp("CP::SystematicsSvc")("SystematicsSvc")) + + log.info("Adding trigger analysis algs") + # Removes events failing trigger and adds variable to EventInfo + # if trigger passed or not, for example: + # EventInfo.trigger_name + cfg.merge(TriggerAnalysisSequenceCfg(flags, dataType, trigger_chains)) + + log.info("Add DQ event filter sequence") + # Remove events failing DQ criteria + cfg.merge( + EventSelectionAnalysisSequenceCfg(flags, dataType, grlFiles=[], loose=do_loose) + ) + + doPRW = _is_mc_phys(flags) + log.info( + f"Do PRW is {doPRW}. {'Add' if doPRW else 'Skip'} pileup re-weight sequence" + ) + if doPRW: + try: + prwFiles, lumicalcFiles = pileupConfigFiles(fileMD) + # Adds variable to EventInfo if for pileup weight, for example: + # EventInfo.PileWeight_%SYS$ + cfg.merge( + PileupAnalysisSequenceCfg( + flags, + dataType=dataType, + prwFiles=prwFiles, + lumicalcFiles=lumicalcFiles, + ) + ) + + log.info("Adding generator analysis sequence") + # Adds variable to EventInfo if for generator weight, for example: + # EventInfo.generatorWeight_%SYS% + cfg.merge(GeneratorAnalysisSequenceCfg(flags, dataType)) + + except LookupError as err: + log.error(err) + doPRW = False + + containers = _get_container_names(flags) + + log.info("Add electron seq") + cfg.merge( + ElectronAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["electrons"], + outputContainerName=containers["outputs"]["electrons"], + ) + ) + + log.info("Add photon seq") + cfg.merge( + PhotonAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["photons"], + outputContainerName=containers["outputs"]["photons"], + ) + ) + + if do_muons: + log.info("Add muon seq") + cfg.merge( + MuonAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["muons"], + outputContainerName=containers["outputs"]["muons"], + ) + ) + + log.info("Add jet seq") + cfg.merge( + JetAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["reco4Jet"], + outputContainerName=containers["outputs"]["reco4Jet"], + workingPoints=btag_wps, + is_daod_physlite=is_daod_physlite, + ) + ) + + if is_daod_physlite: + log.warning("On PHYSLITE, skip large-R jet sequence for now") + else: + log.info("Add large-R jet seq") + cfg.merge( + FatJetAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["reco10Jet"], + outputContainerName=containers["outputs"]["reco10Jet"], + ) + ) + + if is_daod_physlite: + log.warning("On PHYSLITE, skip VR jet sequence for now") + else: + log.info("Add VR jet seq") + cfg.merge( + VRJetAnalysisSequenceCfg( + flags, + dataType=dataType, + inputContainerName=containers["inputs"]["vrJet"], + outputContainerName=containers["outputs"]["vrJet"], + workingPoints=vr_btag_wps, + ) + ) + + ######################################################################## + # Begin postprocessing + ######################################################################## + + log.info("Add Overlap Removal sequence") + overlapInputNames = { + "electrons": containers["outputs"]["electrons"], + "photons": containers["outputs"]["photons"], + "jets": containers["outputs"]["reco4Jet"], + } + if do_muons: + overlapInputNames["muons"] = containers["outputs"]["muons"] + + if not is_daod_physlite: + overlapInputNames["fatJets"] = containers["outputs"]["reco10Jet"] + + overlapOutputNames = {k: f"{v}_OR" for k, v in overlapInputNames.items()} + + cfg.merge( + OverlapAnalysisSequenceCfg( + flags, + dataType=dataType, + inputNames=overlapInputNames, + outputNames=overlapOutputNames, + doFatJets=not is_daod_physlite, + doMuons=do_muons, + ) + ) + + if metadata_cache: + cache_metadata(metadata_cache) + + cfg.addEventAlgo( + CompFactory.HH4B.VariableDumperAlg( + "VariableDumper", + EventInfoKey="EventInfo", + RootStreamName="ANALYSIS", + ) + ) + + return cfg + + +def MiniTupleCfg( + flags, + outfname, + trigger_chains, + working_points, + do_muons=True, +): + cfg = ComponentAccumulator() + is_daod_physlite = _is_physlite(flags) + doPRW = _is_mc_phys(flags) + containers = _get_container_names(flags)["outputs"] + + log.debug(f"Containers requested in dataset: {containers}") + + ######################################################################## + # Create analysis mini-ntuple + ######################################################################## + + # Add an instance of THistSvc, to create the output file and associated stream. + # This is needed so that the alg can register its output TTree. + # The syntax for the output is: + # Stream name: "ANALYSIS" (default assumed by AthHistogramAlgorithm) + # Output file name: specified by setting "DATAFILE" + # File I/O option: specified by setting "OPT" and passed to the TFile constructor + # "RECREATE" will (over)write the specified file name with a new file + cfg.addService( + CompFactory.THistSvc(Output=[f"ANALYSIS DATAFILE='{outfname}', OPT='RECREATE'"]) + ) + + def getFourMomBranches(container, alias, doOR=False): + ORstr = "_OR" if doOR else "" + + branches = [] + vars = ["pt", "eta", "phi"] + if "Jets" in container: + vars.append("m") + for var in vars: + branches += [ + f"{container}{ORstr}.{var} -> {alias}{ORstr}_%SYS%_{var}", + ] + return branches + + analysisTreeBranches = [ + "EventInfo.runNumber -> runNumber", + "EventInfo.eventNumber -> eventNumber", + "EventInfo.mcEventWeights -> mcEventWeights", + "EventInfo.averageInteractionsPerCrossing -> averageInteractionsPerCrossing", + ] + + for trig_chain in trigger_chains: + cleaned = trig_chain.replace("-", "_") + if "." in trig_chain: + continue + analysisTreeBranches.append( + f"EventInfo.trigPassed_{cleaned} -> trigPassed_{cleaned}" + ) + + if doPRW: + analysisTreeBranches += [ + "EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%", + "EventInfo.generatorWeight_%SYS% -> generatorWeight_%SYS%", + ] + else: + analysisTreeBranches += [ + "EventInfo.mcEventWeights -> pileupWeight_NOSYS", + ] + + objectpairs = { + containers["electrons"]: "el", + containers["photons"]: "ph", + containers["reco4Jet"]: "recojet_antikt4", + } + if do_muons: + containers["muons"] = "mu" + + for cont, alias in objectpairs.items(): + analysisTreeBranches += getFourMomBranches(cont, alias) + analysisTreeBranches += getFourMomBranches(cont, alias, doOR=True) + + # B-jet WPs + analysisTreeBranches += [ + f"{containers['reco4Jet']}.ftag_select_{btag_wp}" + f" -> recojet_antikt4_%SYS%_{btag_wp}" + for btag_wp in working_points["ak4"] + ] + analysisTreeBranches += [ + f"{containers['reco4Jet']}_OR.ftag_select_{btag_wp}" + f" -> recojet_antikt4_OR_%SYS%_{btag_wp}" + for btag_wp in working_points["ak4"] + ] + + if not is_daod_physlite: + analysisTreeBranches += getFourMomBranches( + containers["reco10Jet"], "recojet_antikt10" + ) + analysisTreeBranches += getFourMomBranches( + containers["reco10Jet"], "recojet_antikt10", doOR=True + ) + analysisTreeBranches += getFourMomBranches(containers["vrJet"], "vrjet") + analysisTreeBranches += [ + f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" + for btag_wp in working_points["vr"] + ] + + log.info("Add tree seq") + cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) + + return cfg + + +# CA modules are intended to be executable, to facilitate easy testing. +# We define a "main function" that will run a test job if the module +# is executed rather than imported. +def main(): + # Import the job configuration flags, some of which will be autoconfigured. + # These are used for steering the job, and include e.g. the input file (list). + from AthenaConfiguration.AllConfigFlags import ConfigFlags + + # Get the arguments, defined at the top for easy browsing + parser = defineArgs(ConfigFlags) + args = ConfigFlags.fillFromArgs([], parser) + # Lock the flags so that the configuration of job subcomponents cannot + # modify them silently/unpredictably. + # Workaround for buggy glob, needed prior + # to https://gitlab.cern.ch/atlas/athena/-/merge_requests/55561 + if ConfigFlags.Input.Files[0] == "_ATHENA_GENERIC_INPUTFILE_NAME_": + ConfigFlags.Input.Files = ConfigFlags.Input.Files[1:] + log.info(f"Operating on input files {ConfigFlags.Input.Files}") + ConfigFlags.lock() + + # Get a ComponentAccumulator setting up the standard components + # needed to run an Athena job. + # Setting temporarily needed for Run 3 code, to generate python + # Configurable objects for deduplication + from AthenaCommon.Configurable import ConfigurableRun3Behavior + from AthenaConfiguration.MainServicesConfig import MainServicesCfg + + with ConfigurableRun3Behavior(): + + cfg = MainServicesCfg(ConfigFlags) + + from EventBookkeeperTools.EventBookkeeperToolsConfig import ( + BookkeeperToolCfg, + CutFlowSvcCfg, + ) + + # Create CutFlowSvc otherwise the default CutFlowSvc that has only + # one CutflowBookkeeper object, and can't deal with multiple weights + cfg.merge(CutFlowSvcCfg(ConfigFlags)) + cfg.merge(BookkeeperToolCfg(ConfigFlags)) + + # Adjust the loop manager to announce the event number less frequently. + # Makes a big difference if running over many events + if ConfigFlags.Concurrency.NumThreads > 0: + cfg.addService( + CompFactory.AthenaHiveEventLoopMgr(EventPrintoutInterval=500) + ) + else: + cfg.addService(CompFactory.AthenaEventLoopMgr(EventPrintoutInterval=500)) + + from HH4bAnalysis.Config.xAODEventSelectorConfig import xAODReadCfg + + cfg.merge(xAODReadCfg(ConfigFlags)) + + # Add our VariableDumper CA, calling the function defined above. + from HH4bAnalysis.Config.TriggerLists import TriggerLists + + trigger_chains = TriggerLists[args.trigger_list] + do_muons = not args.meta_cache + + cfg.addSequence(CompFactory.AthSequencer("HH4bSeq"), "AthAlgSeq") + cfg.merge( + AnalysisAlgsCfg( + ConfigFlags, + btag_wps=args.btag_wps, + vr_btag_wps=args.vr_btag_wps, + trigger_chains=trigger_chains, + metadata_cache=args.meta_cache, + do_muons=do_muons, + do_loose=args.loose, + ), + "HH4bSeq", + ) + cfg.merge( + MiniTupleCfg( + ConfigFlags, + outfname=args.outFile, + trigger_chains=trigger_chains, + working_points={"ak4": args.btag_wps, "vr": args.vr_btag_wps}, + do_muons=do_muons, + ), + "HH4bSeq", + ) + + # Print the full job configuration + cfg.printConfig(summariseProps=False) + + # Execute the job defined in the ComponentAccumulator. + # The number of events is specified by `args.evtMax` + return cfg.run(args.evtMax) + + +# Execute the main function if this file was executed as a script +if __name__ == "__main__": + code = main() + sys.exit(0 if code.isSuccess() else 1) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 10ee35a09..ea6380b39 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -13,26 +13,26 @@ import sys from pathlib import Path from AthenaCommon import Logging +from AthenaConfiguration.AutoConfigFlags import GetFileMD from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory -from AthenaConfiguration.AutoConfigFlags import GetFileMD -from HH4bAnalysis.Config.Base import pileupConfigFiles, cache_metadata, update_metadata +from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg from HH4bAnalysis.Algs.Event import ( + EventSelectionAnalysisSequenceCfg, GeneratorAnalysisSequenceCfg, - TriggerAnalysisSequenceCfg, PileupAnalysisSequenceCfg, - EventSelectionAnalysisSequenceCfg, + TriggerAnalysisSequenceCfg, ) -from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg -from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg -from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg from HH4bAnalysis.Algs.Jets import ( - JetAnalysisSequenceCfg, FatJetAnalysisSequenceCfg, + JetAnalysisSequenceCfg, VRJetAnalysisSequenceCfg, ) +from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg +from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg from HH4bAnalysis.Algs.Postprocessing import OverlapAnalysisSequenceCfg from HH4bAnalysis.Algs.Tree import AnalysisTreeAlgCfg +from HH4bAnalysis.Config.Base import cache_metadata, pileupConfigFiles, update_metadata from HH4bAnalysis.utils.containerNameHelper import getContainerName log = Logging.logging.getLogger("VariableDumperConfig") @@ -62,8 +62,8 @@ def defineArgs(ConfigFlags): type=str, nargs="*", default=[ - # "DL1r_FixedCutBEff_77", - # "DL1r_FixedCutBEff_85", + "DL1r_FixedCutBEff_77", + "DL1r_FixedCutBEff_85", ], help="VR Jets btag working points default %(default)s", ) @@ -172,7 +172,7 @@ def AnalysisAlgsCfg( doPRW = _is_mc_phys(flags) log.info( - f"Do PRW is {doPRW}. " f"{'Add' if doPRW else 'Skip'} pileup re-weight sequence" + f"Do PRW is {doPRW}. {'Add' if doPRW else 'Skip'} pileup re-weight sequence" ) if doPRW: try: @@ -301,6 +301,20 @@ def AnalysisAlgsCfg( if metadata_cache: cache_metadata(metadata_cache) + cfg.addEventAlgo( + CompFactory.HH4B.VariableDumperAlg( + "VariableDumper", + RootStreamName="ANALYSIS", + EventInfoKey="EventInfo", + ElectronsKey=containers["outputs"]["electrons"], + PhotonsKey=containers["outputs"]["photons"], + MuonsKey=containers["inputs"]["muons"], + SmallJetKey=containers["outputs"]["reco4Jet"], + LargeJetKey=containers["inputs"]["reco10Jet"], + VRtrackjets=containers["outputs"]["vrJet"], + ) + ) + return cfg @@ -404,10 +418,21 @@ def MiniTupleCfg( ) analysisTreeBranches += getFourMomBranches(containers["vrJet"], "vrjet") analysisTreeBranches += [ - f"{containers['vrJet']}.ftag_select_{btag_wp}" f" -> vrjet_%SYS%_{btag_wp}" + f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" for btag_wp in working_points["vr"] ] - + # analysisTreeBranches = [ + # "EventInfo.resolved_m_h1 -> resolved_m_h1", + # "EventInfo.resolved_m_h2 -> resolved_m_h2", + # "EventInfo.resolved_m_hh -> resolved_m_hh", + # "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", + # "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", + # "EventInfo.boosted_m_h1 -> boosted_m_h1", + # "EventInfo.boosted_m_h2 -> boosted_m_h2", + # "EventInfo.boosted_m_hh -> boosted_m_hh", + # "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", + # "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", + # ] log.info("Add tree seq") cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) @@ -436,19 +461,18 @@ def main(): # Get a ComponentAccumulator setting up the standard components # needed to run an Athena job. - from AthenaConfiguration.MainServicesConfig import MainServicesCfg - # Setting temporarily needed for Run 3 code, to generate python # Configurable objects for deduplication from AthenaCommon.Configurable import ConfigurableRun3Behavior + from AthenaConfiguration.MainServicesConfig import MainServicesCfg with ConfigurableRun3Behavior(): cfg = MainServicesCfg(ConfigFlags) from EventBookkeeperTools.EventBookkeeperToolsConfig import ( - CutFlowSvcCfg, BookkeeperToolCfg, + CutFlowSvcCfg, ) # Create CutFlowSvc otherwise the default CutFlowSvc that has only diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index d92ee14d0..8b282dfd1 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -72,29 +72,6 @@ namespace HH4B const xAOD::JetContainer *VRTrackJets(nullptr); ATH_CHECK(m_VRtrackjetHandle.retrieve(VRTrackJets, sys)); - for (auto jet : *antiKt4RecoJets) - { - const xAOD::BTagging *bjet = - xAOD::BTaggingUtilities::getBTagging(*jet); - - if (!bjet) - { - ATH_MSG_WARNING("btagging information not available"); - continue; - } - - double DL1dv00_pb = -1; - double DL1dv00_pc = -1; - double DL1dv00_pu = -1; - bjet->pb("DL1dv00", DL1dv00_pb); - bjet->pc("DL1dv00", DL1dv00_pc); - bjet->pu("DL1dv00", DL1dv00_pu); - ATH_MSG_WARNING("DL1dv00_pb \"" << DL1dv00_pb << "\" for jet"); - ATH_MSG_WARNING("DL1dv00_pc \"" << DL1dv00_pc << "\" for jet"); - ATH_MSG_WARNING("DL1dv00_pu \"" << DL1dv00_pu << "\" for jet"); - jet->auxdecor<double>("DL1dv00_pb") = DL1dv00_pb; - } - // TODO: make configurable with which btagging WP Higgs candidates are // created @@ -102,7 +79,7 @@ namespace HH4B DiHiggsAnalysis hh4b_analysis; hh4b_analysis.makeResolvedAnalysis(antiKt4RecoJets); hh4b_analysis.makeBoostedAnalysis(antiKt10RecoJets); - hh4b_analysis.decorateHiggsVars(*eventInfo) + hh4b_analysis.decorateHiggsVars(*eventInfo); } return StatusCode::SUCCESS; diff --git a/HH4bAnalysis/src/VariableDumperAlg.h b/HH4bAnalysis/src/VariableDumperAlg.h index ba146105b..cdb0b9f87 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.h +++ b/HH4bAnalysis/src/VariableDumperAlg.h @@ -60,7 +60,7 @@ private: "the electron collection to run on"}; CP::SysReadHandle<xAOD::PhotonContainer> m_photonHandle{ - this, "PhotosKey", "AnalysisPhotons_%SYS%", + this, "PhotonsKey", "AnalysisPhotons_%SYS%", "the photon collection to run on"}; CP::SysReadHandle<xAOD::MuonContainer> m_muonHandle{ @@ -76,7 +76,7 @@ private: "the large-R jet collection to run on"}; CP::SysReadHandle<xAOD::JetContainer> m_VRtrackjetHandle{ - this, "VRtrackjets", "VRTrackJetsBTAG_%SYS%", + this, "VRtrackjets", "VRTrackJets_%SYS%", "the VR track jet collection to run on"}; }; } -- GitLab From 367b9cef6527acc1a207ae723106b124dbbe93b6 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Fri, 12 Aug 2022 11:08:45 +0200 Subject: [PATCH 16/33] remove wrong file --- HH4bAnalysis/share/VariableDumperAlgConfig.py | 520 ------------------ 1 file changed, 520 deletions(-) delete mode 100755 HH4bAnalysis/share/VariableDumperAlgConfig.py diff --git a/HH4bAnalysis/share/VariableDumperAlgConfig.py b/HH4bAnalysis/share/VariableDumperAlgConfig.py deleted file mode 100755 index 43e64e9cb..000000000 --- a/HH4bAnalysis/share/VariableDumperAlgConfig.py +++ /dev/null @@ -1,520 +0,0 @@ -#!/bin/env python - -# -# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration -# - -# -# VariableDumperConfig.py -# A simple CA file to create a tree of variables -# - -import sys -from pathlib import Path - -from AthenaCommon import Logging -from AthenaConfiguration.AutoConfigFlags import GetFileMD -from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator -from AthenaConfiguration.ComponentFactory import CompFactory -from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg -from HH4bAnalysis.Algs.Event import ( - EventSelectionAnalysisSequenceCfg, - GeneratorAnalysisSequenceCfg, - PileupAnalysisSequenceCfg, - TriggerAnalysisSequenceCfg, -) -from HH4bAnalysis.Algs.Jets import ( - FatJetAnalysisSequenceCfg, - JetAnalysisSequenceCfg, - VRJetAnalysisSequenceCfg, -) -from HH4bAnalysis.Algs.Muons import MuonAnalysisSequenceCfg -from HH4bAnalysis.Algs.Photons import PhotonAnalysisSequenceCfg -from HH4bAnalysis.Algs.Postprocessing import OverlapAnalysisSequenceCfg -from HH4bAnalysis.Algs.Tree import AnalysisTreeAlgCfg -from HH4bAnalysis.Config.Base import cache_metadata, pileupConfigFiles, update_metadata -from HH4bAnalysis.utils.containerNameHelper import getContainerName - -log = Logging.logging.getLogger("VariableDumperConfig") - - -def defineArgs(ConfigFlags): - # Generate a parser and add an output file argument, then retrieve the args - parser = ConfigFlags.getArgumentParser() - parser.add_argument( - "--outFile", - type=str, - default="analysis-variables.root", - help="Output file name", - ) - parser.add_argument( - "--btag-wps", - type=str, - nargs="*", - default=[ - "DL1dv00_FixedCutBEff_77", - "DL1dv00_FixedCutBEff_85", - ], - help="Btag working points default %(default)s", - ) - parser.add_argument( - "--vr-btag-wps", - type=str, - nargs="*", - default=[ - "DL1r_FixedCutBEff_77", - "DL1r_FixedCutBEff_85", - ], - help="VR Jets btag working points default %(default)s", - ) - parser.add_argument( - "--trigger-list", - type=str, - default="Run3", - help="Trigger list to use, default: %(default)s", - ) - parser.add_argument( - "-c", - "--meta-cache", - type=Path, - default=None, - nargs="?", - const=Path("metadata.json"), - help="use metadata cache file, defaults to %(const)s", - ) - parser.add_argument( - "-o", - "--loose", - action="store_true", - help="use loose event cleaning (to get something to pass)", - ) - return parser - - -def _is_physlite(flags): - return flags.Input.ProcessingTags == ["StreamDAOD_PHYSLITE"] - - -def _is_mc_phys(flags): - return flags.Input.isMC and not _is_physlite(flags) - - -def _get_container_names(flags): - is_daod_physlite = _is_physlite(flags) - inputs = dict( - reco4Jet=getContainerName("Reco4PFlowJets", is_daod_physlite), - reco10Jet=getContainerName("Reco10PFlowJets", is_daod_physlite), - vrJet=getContainerName("VRJets", is_daod_physlite), - muons=getContainerName("Muons", is_daod_physlite), - electrons=getContainerName("Electrons", is_daod_physlite), - photons=getContainerName("Photons", is_daod_physlite), - ) - outputs = dict( - reco4Jet=f"Analysis{inputs['reco4Jet']}_%SYS%", - muons=f"Analysis{inputs['muons']}_%SYS%", - electrons=f"Analysis{inputs['electrons']}_%SYS%", - photons=f"Analysis{inputs['photons']}_%SYS%", - ) - if inputs["reco10Jet"]: - outputs["reco10Jet"] = f"Analysis{inputs['reco10Jet']}_%SYS%" - else: - outputs["reco10Jet"] = "" - if inputs["vrJet"]: - outputs["vrJet"] = f"Analysis{inputs['vrJet']}_%SYS%" - else: - outputs["vrJet"] = "" - return {"inputs": inputs, "outputs": outputs} - - -# 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 AnalysisAlgsCfg( - flags, - btag_wps, - vr_btag_wps, - trigger_chains=[], - do_muons=True, - metadata_cache=None, - do_loose=False, -): - fileMD = GetFileMD(flags.Input.Files[0]) - if metadata_cache: - update_metadata(metadata_cache) - dataType = "mc" if flags.Input.isMC else "data" - is_daod_physlite = _is_physlite(flags) - log.info( - f"Self-configured: dataType: '{dataType}', is PHYSLITE? {is_daod_physlite}" - ) - - log.debug(f"Containers available in dataset: {flags.Input.Collections}") - - # TODO: no DL1d branches in PHYSLITE yet - if is_daod_physlite: - btag_wps = [wp.replace("DL1dv00", "DL1r") for wp in btag_wps] - - cfg = ComponentAccumulator() - - # Create SystematicsSvc explicitly: - cfg.addService(CompFactory.getComp("CP::SystematicsSvc")("SystematicsSvc")) - - log.info("Adding trigger analysis algs") - # Removes events failing trigger and adds variable to EventInfo - # if trigger passed or not, for example: - # EventInfo.trigger_name - cfg.merge(TriggerAnalysisSequenceCfg(flags, dataType, trigger_chains)) - - log.info("Add DQ event filter sequence") - # Remove events failing DQ criteria - cfg.merge( - EventSelectionAnalysisSequenceCfg(flags, dataType, grlFiles=[], loose=do_loose) - ) - - doPRW = _is_mc_phys(flags) - log.info( - f"Do PRW is {doPRW}. {'Add' if doPRW else 'Skip'} pileup re-weight sequence" - ) - if doPRW: - try: - prwFiles, lumicalcFiles = pileupConfigFiles(fileMD) - # Adds variable to EventInfo if for pileup weight, for example: - # EventInfo.PileWeight_%SYS$ - cfg.merge( - PileupAnalysisSequenceCfg( - flags, - dataType=dataType, - prwFiles=prwFiles, - lumicalcFiles=lumicalcFiles, - ) - ) - - log.info("Adding generator analysis sequence") - # Adds variable to EventInfo if for generator weight, for example: - # EventInfo.generatorWeight_%SYS% - cfg.merge(GeneratorAnalysisSequenceCfg(flags, dataType)) - - except LookupError as err: - log.error(err) - doPRW = False - - containers = _get_container_names(flags) - - log.info("Add electron seq") - cfg.merge( - ElectronAnalysisSequenceCfg( - flags, - dataType=dataType, - inputContainerName=containers["inputs"]["electrons"], - outputContainerName=containers["outputs"]["electrons"], - ) - ) - - log.info("Add photon seq") - cfg.merge( - PhotonAnalysisSequenceCfg( - flags, - dataType=dataType, - inputContainerName=containers["inputs"]["photons"], - outputContainerName=containers["outputs"]["photons"], - ) - ) - - if do_muons: - log.info("Add muon seq") - cfg.merge( - MuonAnalysisSequenceCfg( - flags, - dataType=dataType, - inputContainerName=containers["inputs"]["muons"], - outputContainerName=containers["outputs"]["muons"], - ) - ) - - log.info("Add jet seq") - cfg.merge( - JetAnalysisSequenceCfg( - flags, - dataType=dataType, - inputContainerName=containers["inputs"]["reco4Jet"], - outputContainerName=containers["outputs"]["reco4Jet"], - workingPoints=btag_wps, - is_daod_physlite=is_daod_physlite, - ) - ) - - if is_daod_physlite: - log.warning("On PHYSLITE, skip large-R jet sequence for now") - else: - log.info("Add large-R jet seq") - cfg.merge( - FatJetAnalysisSequenceCfg( - flags, - dataType=dataType, - inputContainerName=containers["inputs"]["reco10Jet"], - outputContainerName=containers["outputs"]["reco10Jet"], - ) - ) - - if is_daod_physlite: - log.warning("On PHYSLITE, skip VR jet sequence for now") - else: - log.info("Add VR jet seq") - cfg.merge( - VRJetAnalysisSequenceCfg( - flags, - dataType=dataType, - inputContainerName=containers["inputs"]["vrJet"], - outputContainerName=containers["outputs"]["vrJet"], - workingPoints=vr_btag_wps, - ) - ) - - ######################################################################## - # Begin postprocessing - ######################################################################## - - log.info("Add Overlap Removal sequence") - overlapInputNames = { - "electrons": containers["outputs"]["electrons"], - "photons": containers["outputs"]["photons"], - "jets": containers["outputs"]["reco4Jet"], - } - if do_muons: - overlapInputNames["muons"] = containers["outputs"]["muons"] - - if not is_daod_physlite: - overlapInputNames["fatJets"] = containers["outputs"]["reco10Jet"] - - overlapOutputNames = {k: f"{v}_OR" for k, v in overlapInputNames.items()} - - cfg.merge( - OverlapAnalysisSequenceCfg( - flags, - dataType=dataType, - inputNames=overlapInputNames, - outputNames=overlapOutputNames, - doFatJets=not is_daod_physlite, - doMuons=do_muons, - ) - ) - - if metadata_cache: - cache_metadata(metadata_cache) - - cfg.addEventAlgo( - CompFactory.HH4B.VariableDumperAlg( - "VariableDumper", - EventInfoKey="EventInfo", - RootStreamName="ANALYSIS", - ) - ) - - return cfg - - -def MiniTupleCfg( - flags, - outfname, - trigger_chains, - working_points, - do_muons=True, -): - cfg = ComponentAccumulator() - is_daod_physlite = _is_physlite(flags) - doPRW = _is_mc_phys(flags) - containers = _get_container_names(flags)["outputs"] - - log.debug(f"Containers requested in dataset: {containers}") - - ######################################################################## - # Create analysis mini-ntuple - ######################################################################## - - # Add an instance of THistSvc, to create the output file and associated stream. - # This is needed so that the alg can register its output TTree. - # The syntax for the output is: - # Stream name: "ANALYSIS" (default assumed by AthHistogramAlgorithm) - # Output file name: specified by setting "DATAFILE" - # File I/O option: specified by setting "OPT" and passed to the TFile constructor - # "RECREATE" will (over)write the specified file name with a new file - cfg.addService( - CompFactory.THistSvc(Output=[f"ANALYSIS DATAFILE='{outfname}', OPT='RECREATE'"]) - ) - - def getFourMomBranches(container, alias, doOR=False): - ORstr = "_OR" if doOR else "" - - branches = [] - vars = ["pt", "eta", "phi"] - if "Jets" in container: - vars.append("m") - for var in vars: - branches += [ - f"{container}{ORstr}.{var} -> {alias}{ORstr}_%SYS%_{var}", - ] - return branches - - analysisTreeBranches = [ - "EventInfo.runNumber -> runNumber", - "EventInfo.eventNumber -> eventNumber", - "EventInfo.mcEventWeights -> mcEventWeights", - "EventInfo.averageInteractionsPerCrossing -> averageInteractionsPerCrossing", - ] - - for trig_chain in trigger_chains: - cleaned = trig_chain.replace("-", "_") - if "." in trig_chain: - continue - analysisTreeBranches.append( - f"EventInfo.trigPassed_{cleaned} -> trigPassed_{cleaned}" - ) - - if doPRW: - analysisTreeBranches += [ - "EventInfo.PileupWeight_%SYS% -> pileupWeight_%SYS%", - "EventInfo.generatorWeight_%SYS% -> generatorWeight_%SYS%", - ] - else: - analysisTreeBranches += [ - "EventInfo.mcEventWeights -> pileupWeight_NOSYS", - ] - - objectpairs = { - containers["electrons"]: "el", - containers["photons"]: "ph", - containers["reco4Jet"]: "recojet_antikt4", - } - if do_muons: - containers["muons"] = "mu" - - for cont, alias in objectpairs.items(): - analysisTreeBranches += getFourMomBranches(cont, alias) - analysisTreeBranches += getFourMomBranches(cont, alias, doOR=True) - - # B-jet WPs - analysisTreeBranches += [ - f"{containers['reco4Jet']}.ftag_select_{btag_wp}" - f" -> recojet_antikt4_%SYS%_{btag_wp}" - for btag_wp in working_points["ak4"] - ] - analysisTreeBranches += [ - f"{containers['reco4Jet']}_OR.ftag_select_{btag_wp}" - f" -> recojet_antikt4_OR_%SYS%_{btag_wp}" - for btag_wp in working_points["ak4"] - ] - - if not is_daod_physlite: - analysisTreeBranches += getFourMomBranches( - containers["reco10Jet"], "recojet_antikt10" - ) - analysisTreeBranches += getFourMomBranches( - containers["reco10Jet"], "recojet_antikt10", doOR=True - ) - analysisTreeBranches += getFourMomBranches(containers["vrJet"], "vrjet") - analysisTreeBranches += [ - f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" - for btag_wp in working_points["vr"] - ] - - log.info("Add tree seq") - cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) - - return cfg - - -# CA modules are intended to be executable, to facilitate easy testing. -# We define a "main function" that will run a test job if the module -# is executed rather than imported. -def main(): - # Import the job configuration flags, some of which will be autoconfigured. - # These are used for steering the job, and include e.g. the input file (list). - from AthenaConfiguration.AllConfigFlags import ConfigFlags - - # Get the arguments, defined at the top for easy browsing - parser = defineArgs(ConfigFlags) - args = ConfigFlags.fillFromArgs([], parser) - # Lock the flags so that the configuration of job subcomponents cannot - # modify them silently/unpredictably. - # Workaround for buggy glob, needed prior - # to https://gitlab.cern.ch/atlas/athena/-/merge_requests/55561 - if ConfigFlags.Input.Files[0] == "_ATHENA_GENERIC_INPUTFILE_NAME_": - ConfigFlags.Input.Files = ConfigFlags.Input.Files[1:] - log.info(f"Operating on input files {ConfigFlags.Input.Files}") - ConfigFlags.lock() - - # Get a ComponentAccumulator setting up the standard components - # needed to run an Athena job. - # Setting temporarily needed for Run 3 code, to generate python - # Configurable objects for deduplication - from AthenaCommon.Configurable import ConfigurableRun3Behavior - from AthenaConfiguration.MainServicesConfig import MainServicesCfg - - with ConfigurableRun3Behavior(): - - cfg = MainServicesCfg(ConfigFlags) - - from EventBookkeeperTools.EventBookkeeperToolsConfig import ( - BookkeeperToolCfg, - CutFlowSvcCfg, - ) - - # Create CutFlowSvc otherwise the default CutFlowSvc that has only - # one CutflowBookkeeper object, and can't deal with multiple weights - cfg.merge(CutFlowSvcCfg(ConfigFlags)) - cfg.merge(BookkeeperToolCfg(ConfigFlags)) - - # Adjust the loop manager to announce the event number less frequently. - # Makes a big difference if running over many events - if ConfigFlags.Concurrency.NumThreads > 0: - cfg.addService( - CompFactory.AthenaHiveEventLoopMgr(EventPrintoutInterval=500) - ) - else: - cfg.addService(CompFactory.AthenaEventLoopMgr(EventPrintoutInterval=500)) - - from HH4bAnalysis.Config.xAODEventSelectorConfig import xAODReadCfg - - cfg.merge(xAODReadCfg(ConfigFlags)) - - # Add our VariableDumper CA, calling the function defined above. - from HH4bAnalysis.Config.TriggerLists import TriggerLists - - trigger_chains = TriggerLists[args.trigger_list] - do_muons = not args.meta_cache - - cfg.addSequence(CompFactory.AthSequencer("HH4bSeq"), "AthAlgSeq") - cfg.merge( - AnalysisAlgsCfg( - ConfigFlags, - btag_wps=args.btag_wps, - vr_btag_wps=args.vr_btag_wps, - trigger_chains=trigger_chains, - metadata_cache=args.meta_cache, - do_muons=do_muons, - do_loose=args.loose, - ), - "HH4bSeq", - ) - cfg.merge( - MiniTupleCfg( - ConfigFlags, - outfname=args.outFile, - trigger_chains=trigger_chains, - working_points={"ak4": args.btag_wps, "vr": args.vr_btag_wps}, - do_muons=do_muons, - ), - "HH4bSeq", - ) - - # Print the full job configuration - cfg.printConfig(summariseProps=False) - - # Execute the job defined in the ComponentAccumulator. - # The number of events is specified by `args.evtMax` - return cfg.run(args.evtMax) - - -# Execute the main function if this file was executed as a script -if __name__ == "__main__": - code = main() - sys.exit(0 if code.isSuccess() else 1) -- GitLab From a88a634e3f9bc57002533c380c20cd0561ae45cf Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Fri, 12 Aug 2022 18:33:46 +0200 Subject: [PATCH 17/33] adapted to new master --- HH4bAnalysis/share/VariableDumperConfig.py | 28 +++++++++++----------- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 10 ++++---- HH4bAnalysis/src/VariableDumperAlg.h | 1 - 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index ea6380b39..cc042536b 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -308,9 +308,9 @@ def AnalysisAlgsCfg( EventInfoKey="EventInfo", ElectronsKey=containers["outputs"]["electrons"], PhotonsKey=containers["outputs"]["photons"], - MuonsKey=containers["inputs"]["muons"], + MuonsKey=containers["outputs"]["muons"], SmallJetKey=containers["outputs"]["reco4Jet"], - LargeJetKey=containers["inputs"]["reco10Jet"], + LargeJetKey=containers["outputs"]["reco10Jet"], VRtrackjets=containers["outputs"]["vrJet"], ) ) @@ -421,18 +421,18 @@ def MiniTupleCfg( f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" for btag_wp in working_points["vr"] ] - # analysisTreeBranches = [ - # "EventInfo.resolved_m_h1 -> resolved_m_h1", - # "EventInfo.resolved_m_h2 -> resolved_m_h2", - # "EventInfo.resolved_m_hh -> resolved_m_hh", - # "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", - # "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", - # "EventInfo.boosted_m_h1 -> boosted_m_h1", - # "EventInfo.boosted_m_h2 -> boosted_m_h2", - # "EventInfo.boosted_m_hh -> boosted_m_hh", - # "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", - # "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", - # ] + analysisTreeBranches = [ + "EventInfo.resolved_m_h1 -> resolved_m_h1", + "EventInfo.resolved_m_h2 -> resolved_m_h2", + "EventInfo.resolved_m_hh -> resolved_m_hh", + "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", + "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", + "EventInfo.boosted_m_h1 -> boosted_m_h1", + "EventInfo.boosted_m_h2 -> boosted_m_h2", + "EventInfo.boosted_m_hh -> boosted_m_hh", + "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", + "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", + ] log.info("Add tree seq") cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index c137cfcd2..41aebebfb 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -3,6 +3,8 @@ #include "tools/kLargestJets.h" #include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> +#include <TLorentzVector.h> + using namespace asg::msgUserCode; namespace HH4B @@ -113,12 +115,12 @@ namespace HH4B h2.largeRjetIndex = twoLeadingPtLargeRjetsIndices[1]; // ghost associated track jets are only on the untrimmed 1.0 jets - SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> + static const SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> m_acc_largeR_untrimmed("Parent"); - SG::AuxElement::ConstAccessor< + static const SG::AuxElement::ConstAccessor< std::vector<ElementLink<xAOD::IParticleContainer>>> m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); - SG::AuxElement::ConstAccessor<char> isBtag( + static const SG::AuxElement::ConstAccessor<char> isBtag( "ftag_select_DL1r_FixedCutBEff_77"); // loop over the two large R jets to get the btagged VR jets inside of each @@ -129,7 +131,7 @@ namespace HH4B const xAOD::Jet *thisJet = largeRjets->at(h.largeRjetIndex); // get ghost associated VR track jets from untrimmed large R jet const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); - const std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = + std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = m_acc_VRTrackJets(*thisJet_untrimmed); // get the btagged VR trackjets per large R jet for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) diff --git a/HH4bAnalysis/src/VariableDumperAlg.h b/HH4bAnalysis/src/VariableDumperAlg.h index cdb0b9f87..623342990 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.h +++ b/HH4bAnalysis/src/VariableDumperAlg.h @@ -20,7 +20,6 @@ #include <AthContainers/AuxElement.h> #include <SystematicsHandles/SysListHandle.h> #include <SystematicsHandles/SysReadHandle.h> -#include <TLorentzVector.h> #include <xAODEgamma/ElectronContainer.h> #include <xAODEgamma/PhotonContainer.h> #include <xAODEventInfo/EventInfo.h> -- GitLab From 3ad7449ea9d548d41d8daed4c2ea6aad73a4d597 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Mon, 15 Aug 2022 18:32:14 +0200 Subject: [PATCH 18/33] moved to std::partial_sort for resolved --- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 78 ++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 41aebebfb..c7a45bd7d 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -40,38 +40,70 @@ namespace HH4B // need to do this because sequence filtering destroys order std::vector<int> fourLeadingPtJetsIndices = kLargestJets(smallRjets, 4); - // get largest pt jet - h1.leadingJet = smallRjets->at(fourLeadingPtJetsIndices[0]); - - // calculate dR to other jets to find closest one - double minDR = -1; - int minDRindex = -1; - for (int jetIndex : fourLeadingPtJetsIndices) + // taken from TJ's tutorial + // https://gitlab.cern.ch/khoo/athanalysistutorial/-/blob/r22/MySecondAthAnalysis/src/DileptonFinderAlg.cxx + ConstDataVector<xAOD::JetContainer> ptSortedJets( + smallRjets->begin(), smallRjets->end(), SG::VIEW_ELEMENTS); + std::partial_sort( + ptSortedJets.begin(), // Iterator from which to start sorting + ptSortedJets.begin() + 4, // Use begin + N to sort first N + ptSortedJets.end(), // Iterator marking the end of the range to sort + [](const xAOD::IParticle *left, const xAOD::IParticle *right) + { return left->pt() > right->pt(); }); + + // get the leading b-jet for the leading Higgs candidate + h1.leadingJet = ptSortedJets[0]; + + // calculate dR to the next three leading jets and decorate jet + static const SG::AuxElement::Decorator<float> dRtoLeadingJet_dec( + "dRtoLeadingJet"); + static const SG::AuxElement::ConstAccessor<float> dRtoLeadingJet_acc( + "dRtoLeadingJet"); + + // keep only the four leading ones + ptSortedJets.erase(ptSortedJets.begin() + 4, ptSortedJets.end()); + + // decorate dR(jet,leading jet) to each jet + bool firstJet = true; + for (const xAOD::Jet *jet : ptSortedJets) { - const xAOD::Jet *thisJet = smallRjets->at(jetIndex); - double thisDRtoLeadingJet = thisJet->p4().DeltaR(h1.leadingJet->p4()); - if (thisDRtoLeadingJet > 0 or minDR > thisDRtoLeadingJet) + // easier to read than done with iterators + if (firstJet) { - minDR = thisDRtoLeadingJet; - minDRindex = jetIndex; + dRtoLeadingJet_dec(*jet) = 0; + firstJet = false; + continue; } + dRtoLeadingJet_dec(*jet) = jet->p4().DeltaR(h1.leadingJet->p4()); } - h1.subleadingJet = smallRjets->at(minDRindex); - // calculate higgs candidate four vector and dR between jets - h1.fourVector = h1.leadingJet->p4() + h1.subleadingJet->p4(); - h1.dRjets = h1.leadingJet->p4().DeltaR(h1.subleadingJet->p4()); + ConstDataVector<xAOD::JetContainer> dRsortedJets = ptSortedJets; + // find the closest one + std::partial_sort( + dRsortedJets.begin(), // Iterator from which to start sorting + dRsortedJets.begin() + 4, // Use begin + N to sort first N + dRsortedJets.end(), // Iterator marking the end of the range to sort + [](const xAOD::IParticle *left, const xAOD::IParticle *right) + { return dRtoLeadingJet_acc(*left) > dRtoLeadingJet_acc(*right); }); + + h1.subleadingJet = dRsortedJets[1]; - // get jet indices of subleading higgs candidate h2 - std::vector<int> h2_indices; - for (int jetIndex : fourLeadingPtJetsIndices) + // get the jets for h2 + if (dRsortedJets[2]->pt() > dRsortedJets[3]->pt()) { - if (jetIndex != fourLeadingPtJetsIndices[0] and jetIndex != minDRindex) - h2_indices.push_back(jetIndex); + h2.leadingJet = dRsortedJets[2]; + h2.subleadingJet = dRsortedJets[3]; + } + else + { + h2.leadingJet = dRsortedJets[3]; + h2.subleadingJet = dRsortedJets[2]; } - h2.leadingJet = smallRjets->at(h2_indices[0]); - h2.subleadingJet = smallRjets->at(h2_indices[1]); + // calculate higgs candidate four vector and dR between jets in Higgs + // candidate + h1.fourVector = h1.leadingJet->p4() + h1.subleadingJet->p4(); + h1.dRjets = dRtoLeadingJet_acc(*h1.subleadingJet); h2.fourVector = h2.leadingJet->p4() + h2.subleadingJet->p4(); h2.dRjets = h2.leadingJet->p4().DeltaR(h2.subleadingJet->p4()); -- GitLab From 82c2fa0b75ccd180a10e6dbdf9f7786fc049de41 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Wed, 17 Aug 2022 10:03:30 +0200 Subject: [PATCH 19/33] moved to std::partial_sort --- HH4bAnalysis/CMakeLists.txt | 1 - HH4bAnalysis/src/DiHiggsAnalysis.cxx | 171 +++++++++++++----------- HH4bAnalysis/src/DiHiggsAnalysis.h | 13 +- HH4bAnalysis/src/tools/kLargestJets.cxx | 49 ------- HH4bAnalysis/src/tools/kLargestJets.h | 18 --- 5 files changed, 95 insertions(+), 157 deletions(-) delete mode 100644 HH4bAnalysis/src/tools/kLargestJets.cxx delete mode 100644 HH4bAnalysis/src/tools/kLargestJets.h diff --git a/HH4bAnalysis/CMakeLists.txt b/HH4bAnalysis/CMakeLists.txt index 7ff765547..6e1c3cf1e 100644 --- a/HH4bAnalysis/CMakeLists.txt +++ b/HH4bAnalysis/CMakeLists.txt @@ -19,7 +19,6 @@ atlas_add_component(HH4bAnalysis src/VariableDumperAlg.cxx src/DiHiggsAnalysis.cxx src/tools/NTrkVertexCounter.cxx - src/tools/kLargestJets.cxx src/components/*.cxx LINK_LIBRARIES GaudiKernel diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index c7a45bd7d..79148dc32 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -1,6 +1,6 @@ #include "DiHiggsAnalysis.h" -#include "tools/kLargestJets.h" +#include "AthenaBaseComps/AthCommonMsg.h" #include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> #include <TLorentzVector.h> @@ -36,23 +36,25 @@ namespace HH4B // subleading higgs candidate HiggsCandidate h2; - // get indices of 4 largest pt jets in descending order - // need to do this because sequence filtering destroys order - std::vector<int> fourLeadingPtJetsIndices = kLargestJets(smallRjets, 4); - // taken from TJ's tutorial // https://gitlab.cern.ch/khoo/athanalysistutorial/-/blob/r22/MySecondAthAnalysis/src/DileptonFinderAlg.cxx + // + // this is a shallow copy container ConstDataVector<xAOD::JetContainer> ptSortedJets( smallRjets->begin(), smallRjets->end(), SG::VIEW_ELEMENTS); + // with std::partial_sort you only have to sort an N-sized container + // instead of sorting a ptSortedJets.size() container std::partial_sort( ptSortedJets.begin(), // Iterator from which to start sorting ptSortedJets.begin() + 4, // Use begin + N to sort first N ptSortedJets.end(), // Iterator marking the end of the range to sort [](const xAOD::IParticle *left, const xAOD::IParticle *right) - { return left->pt() > right->pt(); }); + { + return left->pt() > right->pt(); + }); // lambda function here just handy, could also be another function // get the leading b-jet for the leading Higgs candidate - h1.leadingJet = ptSortedJets[0]; + h1.m_leadingJet = ptSortedJets[0]; // calculate dR to the next three leading jets and decorate jet static const SG::AuxElement::Decorator<float> dRtoLeadingJet_dec( @@ -67,18 +69,18 @@ namespace HH4B bool firstJet = true; for (const xAOD::Jet *jet : ptSortedJets) { - // easier to read than done with iterators + // more instructive as done with iterators if (firstJet) { dRtoLeadingJet_dec(*jet) = 0; firstJet = false; continue; } - dRtoLeadingJet_dec(*jet) = jet->p4().DeltaR(h1.leadingJet->p4()); + dRtoLeadingJet_dec(*jet) = jet->p4().DeltaR(h1.m_leadingJet->p4()); } + // now find the closest one ConstDataVector<xAOD::JetContainer> dRsortedJets = ptSortedJets; - // find the closest one std::partial_sort( dRsortedJets.begin(), // Iterator from which to start sorting dRsortedJets.begin() + 4, // Use begin + N to sort first N @@ -86,33 +88,34 @@ namespace HH4B [](const xAOD::IParticle *left, const xAOD::IParticle *right) { return dRtoLeadingJet_acc(*left) > dRtoLeadingJet_acc(*right); }); - h1.subleadingJet = dRsortedJets[1]; + // first one is dr to the leading itself, therefore second one + h1.m_subleadingJet = dRsortedJets[1]; // get the jets for h2 if (dRsortedJets[2]->pt() > dRsortedJets[3]->pt()) { - h2.leadingJet = dRsortedJets[2]; - h2.subleadingJet = dRsortedJets[3]; + h2.m_leadingJet = dRsortedJets[2]; + h2.m_subleadingJet = dRsortedJets[3]; } else { - h2.leadingJet = dRsortedJets[3]; - h2.subleadingJet = dRsortedJets[2]; + h2.m_leadingJet = dRsortedJets[3]; + h2.m_subleadingJet = dRsortedJets[2]; } // calculate higgs candidate four vector and dR between jets in Higgs // candidate - h1.fourVector = h1.leadingJet->p4() + h1.subleadingJet->p4(); - h1.dRjets = dRtoLeadingJet_acc(*h1.subleadingJet); - h2.fourVector = h2.leadingJet->p4() + h2.subleadingJet->p4(); - h2.dRjets = h2.leadingJet->p4().DeltaR(h2.subleadingJet->p4()); + h1.m_fourVector = h1.m_leadingJet->p4() + h1.m_subleadingJet->p4(); + h1.m_dRjets = dRtoLeadingJet_acc(*h1.m_subleadingJet); + h2.m_fourVector = h2.m_leadingJet->p4() + h2.m_subleadingJet->p4(); + h2.m_dRjets = h2.m_leadingJet->p4().DeltaR(h2.m_subleadingJet->p4()); // write to dictionary - h_cand_vars["resolved_m_h1"] = h1.fourVector.M(); - h_cand_vars["resolved_m_h2"] = h2.fourVector.M(); - h_cand_vars["resolved_m_hh"] = (h1.fourVector + h2.fourVector).M(); - h_cand_vars["resolved_dR_jets_in_h1"] = h1.dRjets; - h_cand_vars["resolved_dR_jets_in_h2"] = h2.dRjets; + h_cand_vars["resolved_m_h1"] = h1.m_fourVector.M(); + h_cand_vars["resolved_m_h2"] = h2.m_fourVector.M(); + h_cand_vars["resolved_m_hh"] = (h1.m_fourVector + h2.m_fourVector).M(); + h_cand_vars["resolved_dR_jets_in_h1"] = h1.m_dRjets; + h_cand_vars["resolved_dR_jets_in_h2"] = h2.m_dRjets; return; }; @@ -141,12 +144,21 @@ namespace HH4B HiggsCandidate h1; // subleading higgs candidate HiggsCandidate h2; - std::vector<int> twoLeadingPtLargeRjetsIndices = - kLargestJets(largeRjets, 2); - h1.largeRjetIndex = twoLeadingPtLargeRjetsIndices[0]; - h2.largeRjetIndex = twoLeadingPtLargeRjetsIndices[1]; - // ghost associated track jets are only on the untrimmed 1.0 jets + // get the leading large R, see resvoled analysis for details + ConstDataVector<xAOD::JetContainer> ptSortedLargeRJets( + largeRjets->begin(), largeRjets->end(), SG::VIEW_ELEMENTS); + std::partial_sort( + ptSortedLargeRJets.begin(), // Iterator from which to start sorting + ptSortedLargeRJets.begin() + 2, // Use begin + N to sort first N + ptSortedLargeRJets.end(), // iterator to end + [](const xAOD::IParticle *left, const xAOD::IParticle *right) + { return left->pt() > right->pt(); }); + + h1.m_largeRJet = ptSortedLargeRJets[0]; + h2.m_largeRJet = ptSortedLargeRJets[1]; + + // ghost associated VR track jets are only on the untrimmed 1.0 jets static const SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> m_acc_largeR_untrimmed("Parent"); static const SG::AuxElement::ConstAccessor< @@ -155,74 +167,69 @@ namespace HH4B static const SG::AuxElement::ConstAccessor<char> isBtag( "ftag_select_DL1r_FixedCutBEff_77"); - // loop over the two large R jets to get the btagged VR jets inside of each - // need to do std::ref to access the actual objects h1, h2 + // loop over the Higgs Candidate large R jets to get the btagged VR jets + // inside of each, need to do std::ref to access the actual objects h1, h2 // "for (HiggsCandidate h : {h1, h2})" would make copies of h1, h2 for (HiggsCandidate &h : {std::ref(h1), std::ref(h2)}) { - const xAOD::Jet *thisJet = largeRjets->at(h.largeRjetIndex); // get ghost associated VR track jets from untrimmed large R jet - const xAOD::Jet *thisJet_untrimmed = *m_acc_largeR_untrimmed(*thisJet); + const xAOD::Jet *untrimmedLargeR = + *m_acc_largeR_untrimmed(*h.m_largeRJet); std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = - m_acc_VRTrackJets(*thisJet_untrimmed); + m_acc_VRTrackJets(*untrimmedLargeR); + // get the btagged VR trackjets per large R jet - for (ElementLink<xAOD::IParticleContainer> VRjet : VRTrackjets) - { - auto &test = VRjet; - // check if VRjet link is valid - // should we handle this differently? - if (!test.isValid()) - { - ANA_MSG_WARNING("Invalid track link found!"); - continue; - } - // VRtrack ftag sequence does not tag all of them, so take only the - // btagged ones - if (!isBtag.isAvailable(**VRjet)) - { - ANA_MSG_WARNING("Skipped non B-tagged VR jet"); - continue; - } - h.btagged_VRTrackjets.push_back(VRjet); - } - } + // remove VRjets with invalid elementlinks and non-btagged ones + // should we handle this differently? + // can't just remove in for loop, get in trouble with iterator, could do + // with while loop but std::remove_if is more efficient + VRTrackjets.erase( + std::remove_if(VRTrackjets.begin(), VRTrackjets.end(), + [](ElementLink<xAOD::IParticleContainer> &VRjet) + { + if (!VRjet.isValid()) + { + ANA_MSG_WARNING("Skipped invalid VR jet link!"); + return true; + } + if (!isBtag.isAvailable(**VRjet)) + { + ANA_MSG_DEBUG("Skipped non B-tagged VR jet"); + return true; + } + return false; + }), + VRTrackjets.end()); - // find the leading vr jets - for (HiggsCandidate &h : {std::ref(h1), std::ref(h2)}) - { // check if we have at least 2 per large R jet, otherwise exit - // (subject to change) - if (h.btagged_VRTrackjets.size() < 2) + if (VRTrackjets.size() < 2) { return; } - // cast VRjet to xAOD::jet to use kLargestJets sorting function - // we do it this way since we want to make shallow copies - ConstDataVector<xAOD::JetContainer> tmpVRjets(SG::VIEW_ELEMENTS); - for (auto VRjet : h.btagged_VRTrackjets) - { - const auto *jet = dynamic_cast<const xAOD::Jet *>(*VRjet); - tmpVRjets.push_back(jet); - } - // write leading and subleading vr jet onto HiggsCandidate objects - std::vector<int> twoLeadingVrJetIndices = - kLargestJets(tmpVRjets.asDataVector(), 2); - h.leadingJet = dynamic_cast<const xAOD::Jet *>( - *h.btagged_VRTrackjets[twoLeadingVrJetIndices[0]]); - h.subleadingJet = dynamic_cast<const xAOD::Jet *>( - *h.btagged_VRTrackjets[twoLeadingVrJetIndices[1]]); + // find the leading vr jets + std::partial_sort( + VRTrackjets.begin(), // Iterator from which to start sorting + VRTrackjets.begin() + 2, // Use begin + N to sort first N + VRTrackjets.end(), // iterator to end + [](ElementLink<xAOD::IParticleContainer> &left, + ElementLink<xAOD::IParticleContainer> &right) + { return (*left)->pt() > (*right)->pt(); }); + + h.m_leadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[0]); + h.m_subleadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[1]); + // calc variables - h.fourVector = h.leadingJet->p4() + h.subleadingJet->p4(); - h.dRjets = h.leadingJet->p4().DeltaR(h.subleadingJet->p4()); + h.m_fourVector = h.m_leadingJet->p4() + h.m_subleadingJet->p4(); + h.m_dRjets = h.m_leadingJet->p4().DeltaR(h.m_subleadingJet->p4()); } // write to dictionary - h_cand_vars["boosted_m_h1"] = h1.fourVector.M(); - h_cand_vars["boosted_m_h2"] = h2.fourVector.M(); - h_cand_vars["boosted_m_hh"] = (h1.fourVector + h2.fourVector).M(); - h_cand_vars["boosted_dR_jets_in_h1"] = h1.dRjets; - h_cand_vars["boosted_dR_jets_in_h2"] = h2.dRjets; + h_cand_vars["boosted_m_h1"] = h1.m_fourVector.M(); + h_cand_vars["boosted_m_h2"] = h2.m_fourVector.M(); + h_cand_vars["boosted_m_hh"] = (h1.m_fourVector + h2.m_fourVector).M(); + h_cand_vars["boosted_dR_jets_in_h1"] = h1.m_dRjets; + h_cand_vars["boosted_dR_jets_in_h2"] = h2.m_dRjets; return; }; @@ -233,6 +240,8 @@ namespace HH4B void DiHiggsAnalysis::decorateHiggsVars(const xAOD::EventInfo &eventInfo) { + // static const SG::AuxElement::Decorator<float> HiggsVars_dec( + // "dRtoLeadingJet"); // the range looks weird, but its just a loop over the h_cand_vars map for (const auto &[key, value] : h_cand_vars) { diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index 9ff5cd839..d28bc0bdb 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -14,17 +14,14 @@ namespace HH4B struct HiggsCandidate { // b-jets for Higgs candidate - const xAOD::Jet *leadingJet = nullptr; - const xAOD::Jet *subleadingJet = nullptr; + const xAOD::Jet *m_leadingJet = nullptr; + const xAOD::Jet *m_subleadingJet = nullptr; // four vector of Higgs candidate - TLorentzVector fourVector; + TLorentzVector m_fourVector; // dR between leading and subleading jet - double dRjets = -1; - + double m_dRjets = -1; // for boosted analysis - int largeRjetIndex = -1; - // btagged ghost associated VR track jets inside the large R jet - std::vector<ElementLink<xAOD::IParticleContainer>> btagged_VRTrackjets; + const xAOD::Jet *m_largeRJet = nullptr; }; class DiHiggsAnalysis : HiggsCandidate diff --git a/HH4bAnalysis/src/tools/kLargestJets.cxx b/HH4bAnalysis/src/tools/kLargestJets.cxx deleted file mode 100644 index b2d21cddd..000000000 --- a/HH4bAnalysis/src/tools/kLargestJets.cxx +++ /dev/null @@ -1,49 +0,0 @@ -#include "queue" -#include "xAODJet/JetContainer.h" - -// efficient algorithm to find k largest elements in size n vector with -// efficiency O(n log k) -// see https://stackoverflow.com/a/38391603 - -// returns jet indices in descending order of the largest k found pt's -std::vector<int> kLargestJets(const xAOD::JetContainer *jets, int k_) -{ - // Priority queues are a type of container adaptors, specifically designed - // such that its first element is always the greatest of the elements it - // contains. Using std::greater<T> causes the smallest element to appear as - // the top(). - std::priority_queue<std::pair<double, int>, - std::vector<std::pair<double, int>>, - std::greater<std::pair<double, int>>> - queue; - long unsigned int k = k_; // number of indices we need - - // loop over jets - const xAOD::Jet *thisJet; - double thisJetPt; - for (long unsigned int i = 0; i < jets->size(); i++) - { - thisJet = jets->at(i); - thisJetPt = thisJet->pt(); - // fill queue with first k values - if (queue.size() < k) - // push inserts element into queue and sorts it - queue.push(std::pair<double, int>(thisJetPt, i)); - // if smallest element in queue is smaller than thisJetPt, replace - else if (queue.top().first < thisJetPt) - { - queue.pop(); - queue.push(std::pair<double, int>(thisJetPt, i)); - } - } - - // return vector indices in descending order of the largest k found elements - k = queue.size(); - std::vector<int> res(k); - for (long unsigned int i = 0; i < k; ++i) - { - res[k - i - 1] = queue.top().second; - queue.pop(); - } - return res; -} diff --git a/HH4bAnalysis/src/tools/kLargestJets.h b/HH4bAnalysis/src/tools/kLargestJets.h deleted file mode 100644 index a5e004508..000000000 --- a/HH4bAnalysis/src/tools/kLargestJets.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef HH4BANALYSIS_K_LARGEST_JETS -#define HH4BANALYSIS_K_LARGEST_JETS - -#include "vector" -#include "xAODJet/JetContainer.h" - -// efficient algorithm to find k largest elements in size n vector with -// efficienvy O(n log k). see https://stackoverflow.com/a/38391603 - -// it works something like this : -// jet_with_pt's {2, 8, 7, 5, 9, 3, 6, 1, 10, 4}; -// kLargestJets(jets,5) returns -// [8,4,1,2,6] - -// returns jet indices in descending order of the largest k found pt's -std::vector<int> kLargestJets(const xAOD::JetContainer *jets, int k_); - -#endif \ No newline at end of file -- GitLab From 2b4a80d82fc11a52d0548a005efd6af44c4379c7 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 18 Aug 2022 09:53:32 +0200 Subject: [PATCH 20/33] moved to std::unordered_map --- HH4bAnalysis/share/VariableDumperConfig.py | 2 +- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 24 ++++++++++++++-------- HH4bAnalysis/src/DiHiggsAnalysis.h | 8 +++++--- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index cc042536b..8de653f2b 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -505,7 +505,7 @@ def main(): ConfigFlags, btag_wps=args.btag_wps, vr_btag_wps=args.vr_btag_wps, - trigger_chains=trigger_chains, + trigger_chains=[trigger_chains], metadata_cache=args.meta_cache, do_muons=do_muons, do_loose=args.loose, diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 79148dc32..df4719059 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -4,13 +4,13 @@ #include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> #include <TLorentzVector.h> - +// for ANA_MSG_BLAH using namespace asg::msgUserCode; namespace HH4B { int initValue = -1; - std::map<std::string, double> h_cand_vars{ + std::unordered_map<std::string, float> h_cand_vars{ {"resolved_m_h1", initValue}, {"resolved_m_h2", initValue}, {"resolved_m_hh", initValue}, @@ -233,19 +233,25 @@ namespace HH4B return; }; - std::map<std::string, double> DiHiggsAnalysis::getHiggsVars() + std::unordered_map<std::string, float> DiHiggsAnalysis::getHiggsVars() { return h_cand_vars; }; void DiHiggsAnalysis::decorateHiggsVars(const xAOD::EventInfo &eventInfo) { - // static const SG::AuxElement::Decorator<float> HiggsVars_dec( - // "dRtoLeadingJet"); + // static const SG::AuxElement::Decorator<float> HiggsVars_dec; + // the range looks weird, but its just a loop over the h_cand_vars map + + // 1) for (const auto &[key, value] : h_cand_vars) { - eventInfo.auxdecor<double>(key) = value; - } - }; -} + SG::AuxElement::Decorator<float> HiggsVars_dec(key); + HiggsVars_dec(eventInfo) = value; + }; + + // 2) + // eventInfo.auxdecor<float>(key) = value; + } +}; diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index d28bc0bdb..a619838b1 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -9,7 +9,9 @@ namespace HH4B { // dictionary holding the final vars - extern std::map<std::string, double> h_cand_vars; + // unordered_map is faster than map as it does the lookup with a hash and not + // by string comparison + extern std::unordered_map<std::string, float> h_cand_vars; struct HiggsCandidate { @@ -19,7 +21,7 @@ namespace HH4B // four vector of Higgs candidate TLorentzVector m_fourVector; // dR between leading and subleading jet - double m_dRjets = -1; + float m_dRjets = -1; // for boosted analysis const xAOD::Jet *m_largeRJet = nullptr; }; @@ -32,7 +34,7 @@ public: // do boosted Analysis void makeBoostedAnalysis(const xAOD::JetContainer *largeRjets); // returns h_cand_vars for other purposes - std::map<std::string, double> getHiggsVars(); + std::unordered_map<std::string, float> getHiggsVars(); // decorates the h_cand_vars to the eventInfo void decorateHiggsVars(const xAOD::EventInfo &eventInfo); }; -- GitLab From 03c9d664504e778707a2dec700b6ecbe643495e3 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 18 Aug 2022 11:43:14 +0200 Subject: [PATCH 21/33] remove inheritance --- HH4bAnalysis/src/DiHiggsAnalysis.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index a619838b1..2df509332 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -26,7 +26,7 @@ namespace HH4B const xAOD::Jet *m_largeRJet = nullptr; }; - class DiHiggsAnalysis : HiggsCandidate + class DiHiggsAnalysis { public: // do resolved Analysis -- GitLab From 6eea6f46ff26f35556b88391bea8e6f8a0cf30f2 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 18 Aug 2022 15:42:29 +0200 Subject: [PATCH 22/33] move to Math/Vector4D.h --- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 17 ++++++++++------- HH4bAnalysis/src/DiHiggsAnalysis.h | 16 +++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index f399f66ce..07c31e5c7 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -1,9 +1,9 @@ #include "DiHiggsAnalysis.h" #include "AthenaBaseComps/AthCommonMsg.h" +#include "Math/GenVector/VectorUtil.h" #include <AsgMessaging/MessageCheck.h> #include <AthContainers/ConstDataVector.h> -#include <TLorentzVector.h> // for ANA_MSG_BLAH using namespace asg::msgUserCode; @@ -76,7 +76,8 @@ namespace HH4B firstJet = false; continue; } - dRtoLeadingJet_dec(*jet) = jet->p4().DeltaR(h1.m_leadingJet->p4()); + dRtoLeadingJet_dec(*jet) = ROOT::Math::VectorUtil::DeltaR( + jet->jetP4(), h1.m_leadingJet->jetP4()); } // now find the closest one @@ -105,10 +106,11 @@ namespace HH4B // calculate higgs candidate four vector and dR between jets in Higgs // candidate - h1.m_fourVector = h1.m_leadingJet->p4() + h1.m_subleadingJet->p4(); + h1.m_fourVector = h1.m_leadingJet->jetP4() + h1.m_subleadingJet->jetP4(); h1.m_dRjets = dRtoLeadingJet_acc(*h1.m_subleadingJet); - h2.m_fourVector = h2.m_leadingJet->p4() + h2.m_subleadingJet->p4(); - h2.m_dRjets = h2.m_leadingJet->p4().DeltaR(h2.m_subleadingJet->p4()); + h2.m_fourVector = h2.m_leadingJet->jetP4() + h2.m_subleadingJet->jetP4(); + h2.m_dRjets = ROOT::Math::VectorUtil::DeltaR(h2.m_leadingJet->jetP4(), + h2.m_subleadingJet->jetP4()); // write to dictionary m_diHiggs_vars["resolved_m_h1"] = h1.m_fourVector.M(); @@ -220,8 +222,9 @@ namespace HH4B h.m_subleadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[1]); // calc variables - h.m_fourVector = h.m_leadingJet->p4() + h.m_subleadingJet->p4(); - h.m_dRjets = h.m_leadingJet->p4().DeltaR(h.m_subleadingJet->p4()); + h.m_fourVector = h.m_leadingJet->jetP4() + h.m_subleadingJet->jetP4(); + h.m_dRjets = ROOT::Math::VectorUtil::DeltaR(h.m_leadingJet->jetP4(), + h.m_subleadingJet->jetP4()); } // write to dictionary diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index 0636c22d7..d3b966f8e 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -2,17 +2,23 @@ #define HH4B_DIHIGGSANALYSIS #include "xAODJet/JetContainer.h" +#include <Math/Vector4D.h> #include <xAODEventInfo/EventInfo.h> namespace HH4B { + // dictionary holding the final vars + // unordered_map is faster than map as it does the lookup with a hash and not + // by string comparison + extern std::unordered_map<std::string, float> m_diHiggs_vars; + struct HiggsCandidate { // b-jets for Higgs candidate const xAOD::Jet *m_leadingJet = nullptr; const xAOD::Jet *m_subleadingJet = nullptr; // four vector of Higgs candidate - TLorentzVector m_fourVector; + ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float>> m_fourVector; // dR between leading and subleading jet float m_dRjets = -1; // for boosted analysis @@ -26,14 +32,10 @@ public: void makeResolvedAnalysis(const xAOD::JetContainer &smallRjets); // do boosted Analysis void makeBoostedAnalysis(const xAOD::JetContainer &largeRjets); - // returns m_diHiggs_vars for other purposes + // returns h_cand_vars for other purposes std::unordered_map<std::string, float> getHiggsVars(); - // decorates the m_diHiggs_vars to the eventInfo + // decorates the h_cand_vars to the eventInfo void decorateHiggsVars(const xAOD::EventInfo &eventInfo); - // dictionary holding the final vars - // unordered_map is faster than map as it does the lookup with a hash and - // not by string comparison - extern std::unordered_map<std::string, float> m_diHiggs_vars; }; } #endif -- GitLab From 7c279d4bcd9676b6e3102a4ed5845b38bc22731e Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 18 Aug 2022 16:50:40 +0200 Subject: [PATCH 23/33] move to own di-higgs alg --- HH4bAnalysis/share/VariableDumperConfig.py | 13 ++++------ HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx | 24 ++++++++++++------- HH4bAnalysis/src/DiHiggsAnalysisAlg.h | 6 ++--- .../src/components/HH4bAnalysis_entries.cxx | 2 ++ 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 7cb827f22..8579d87a3 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -318,16 +318,11 @@ def AnalysisAlgsCfg( cache_metadata(metadata_cache) cfg.addEventAlgo( - CompFactory.HH4B.VariableDumperAlg( - "VariableDumper", - RootStreamName="ANALYSIS", + CompFactory.HH4B.DiHiggsAnalysisAlg( + "DiHiggsAnalysis", EventInfoKey="EventInfo", - ElectronsKey=containers["outputs"]["electrons"], - PhotonsKey=containers["outputs"]["photons"], - MuonsKey=containers["outputs"]["muons"], - SmallJetKey=containers["outputs"]["reco4Jet"], - LargeJetKey=containers["outputs"]["reco10Jet"], - VRtrackjets=containers["outputs"]["vrJet"], + SmallJetKey=containers["outputs"]["reco4Jet"].replace("%SYS%", "NOSYS"), + LargeJetKey=containers["outputs"]["reco10Jet"].replace("%SYS%", "NOSYS"), ) ) diff --git a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx index 9f0aac71e..c5a1abf9a 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx @@ -20,20 +20,29 @@ namespace HH4B ISvcLocator *pSvcLocator) : AthHistogramAlgorithm(name, pSvcLocator) { - declareProperty("doBoostedAnalysis", m_doBoostedAnalysis); declareProperty("doResolvedAnalysis", m_doResolvedAnalysis); + declareProperty("doBoostedAnalysis", m_doBoostedAnalysis); } StatusCode DiHiggsAnalysisAlg ::initialize() { ATH_MSG_DEBUG("Initialising " << name()); - DiHiggsAnalysis getVarsObject; - getVarsObject.getHiggsVars(); + DiHiggsAnalysis hh4b_analysis; + hh4b_analysis.getHiggsVars(); + + // std::unordered_map<std::string, SG::AuxElement::Decorator<float>> + // m_diHiggs_decos; + for (const auto &[key, value] : hh4b_analysis.getHiggsVars()) + { + // SG::AuxElement::Decorator<float> HiggsVars_dec(key); + // m_diHiggs_decos[key] = HiggsVars_dec; + std::cout << key; + }; ATH_CHECK(m_EventInfoKey.initialize()); - ATH_CHECK(m_smallJetKey.initialize()); - ATH_CHECK(m_largeJetKey.initialize()); + ATH_CHECK(m_SmallJetKey.initialize()); + ATH_CHECK(m_LargeJetKey.initialize()); return StatusCode::SUCCESS; } @@ -43,10 +52,9 @@ namespace HH4B ATH_MSG_DEBUG("Executing " << name()); // get the xAOD objects - SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey); - SG::ReadHandle<xAOD::JetContainer> antiKt4RecoJets(m_smallJetKey); - SG::ReadHandle<xAOD::JetContainer> antiKt10RecoJets(m_largeJetKey); + SG::ReadHandle<xAOD::JetContainer> antiKt4RecoJets(m_SmallJetKey); + SG::ReadHandle<xAOD::JetContainer> antiKt10RecoJets(m_LargeJetKey); ATH_CHECK(eventInfo.isValid()); ATH_CHECK(antiKt4RecoJets.isValid()); ATH_CHECK(antiKt10RecoJets.isValid()); diff --git a/HH4bAnalysis/src/DiHiggsAnalysisAlg.h b/HH4bAnalysis/src/DiHiggsAnalysisAlg.h index b9817dc51..fd047aab4 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysisAlg.h +++ b/HH4bAnalysis/src/DiHiggsAnalysisAlg.h @@ -44,15 +44,15 @@ private: // decorators for the Higgs variables std::unordered_map<std::string, SG::AuxElement::Decorator<float>> - m_hhDecors; + m_diHiggs_decos; // Member variables for configuration SG::ReadHandleKey<xAOD::EventInfo> m_EventInfoKey{ this, "EventInfoKey", "EventInfo", "EventInfo container to dump"}; - SG::ReadHandleKey<xAOD::JetContainer> m_smallJetKey{ + SG::ReadHandleKey<xAOD::JetContainer> m_SmallJetKey{ this, "SmallJetKey", "", "the small-R jet collection to run on"}; - SG::ReadHandleKey<xAOD::JetContainer> m_largeJetKey{ + SG::ReadHandleKey<xAOD::JetContainer> m_LargeJetKey{ this, "LargeJetKey", "", "the large-R jet collection to run on"}; bool m_doResolvedAnalysis; diff --git a/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx b/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx index 69411715b..8b6e9279f 100644 --- a/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx +++ b/HH4bAnalysis/src/components/HH4bAnalysis_entries.cxx @@ -1,7 +1,9 @@ +#include "../DiHiggsAnalysisAlg.h" #include "../VariableDumperAlg.h" #include "../tools/NTrkVertexCounter.h" using namespace HH4B; +DECLARE_COMPONENT(DiHiggsAnalysisAlg) DECLARE_COMPONENT(NTrkVertexCounter) DECLARE_COMPONENT(VariableDumperAlg) -- GitLab From 4f82cc13f6a50d4d28e5913961aac594da1464d5 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Fri, 19 Aug 2022 10:17:46 +0200 Subject: [PATCH 24/33] create decorators at init --- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 24 +------------------- HH4bAnalysis/src/DiHiggsAnalysis.h | 22 ++++++++++++++----- HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx | 29 ++++++++++--------------- 3 files changed, 30 insertions(+), 45 deletions(-) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 07c31e5c7..b4c1c3e60 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -9,19 +9,6 @@ using namespace asg::msgUserCode; namespace HH4B { - float initValue = -1; - std::unordered_map<std::string, float> m_diHiggs_vars{ - {"resolved_m_h1", initValue}, - {"resolved_m_h2", initValue}, - {"resolved_m_hh", initValue}, - {"resolved_dR_jets_in_h1", initValue}, - {"resolved_dR_jets_in_h2", initValue}, - {"boosted_m_h1", initValue}, - {"boosted_m_h2", initValue}, - {"boosted_m_hh", initValue}, - {"boosted_dR_jets_in_h1", initValue}, - {"boosted_dR_jets_in_h2", initValue}, - }; void DiHiggsAnalysis::makeResolvedAnalysis(const xAOD::JetContainer &smallRjets) @@ -243,18 +230,9 @@ namespace HH4B void DiHiggsAnalysis::decorateHiggsVars(const xAOD::EventInfo &eventInfo) { - // static const SG::AuxElement::Decorator<float> HiggsVars_dec; - - // the range looks weird, but its just a loop over the m_diHiggs_vars map - - // 1) for (const auto &[key, value] : m_diHiggs_vars) { - SG::AuxElement::Decorator<float> HiggsVars_dec(key); - HiggsVars_dec(eventInfo) = value; + eventInfo.auxdecor<float>(key) = value; }; - - // 2) - // eventInfo.auxdecor<float>(key) = value; } }; diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index d3b966f8e..280582e62 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -7,11 +7,6 @@ namespace HH4B { - // dictionary holding the final vars - // unordered_map is faster than map as it does the lookup with a hash and not - // by string comparison - extern std::unordered_map<std::string, float> m_diHiggs_vars; - struct HiggsCandidate { // b-jets for Higgs candidate @@ -36,6 +31,23 @@ public: std::unordered_map<std::string, float> getHiggsVars(); // decorates the h_cand_vars to the eventInfo void decorateHiggsVars(const xAOD::EventInfo &eventInfo); + // DiHiggs variables init value + float m_initValue = -1; + // map holding the final vars + // unordered_map is faster than map as it does the lookup with a hash and + // not by string comparison + std::unordered_map<std::string, float> m_diHiggs_vars{ + {"resolved_m_h1", m_initValue}, + {"resolved_m_h2", m_initValue}, + {"resolved_m_hh", m_initValue}, + {"resolved_dR_jets_in_h1", m_initValue}, + {"resolved_dR_jets_in_h2", m_initValue}, + {"boosted_m_h1", m_initValue}, + {"boosted_m_h2", m_initValue}, + {"boosted_m_hh", m_initValue}, + {"boosted_dR_jets_in_h1", m_initValue}, + {"boosted_dR_jets_in_h2", m_initValue}, + }; }; } #endif diff --git a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx index c5a1abf9a..0ba1386dd 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx @@ -2,18 +2,11 @@ Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration */ -/// @author Victor Ruelas - -// -// includes -// +/// @author Frederic Renner #include "DiHiggsAnalysisAlg.h" #include "DiHiggsAnalysis.h" -// -// method implementations -// namespace HH4B { DiHiggsAnalysisAlg ::DiHiggsAnalysisAlg(const std::string &name, @@ -28,16 +21,13 @@ namespace HH4B { ATH_MSG_DEBUG("Initialising " << name()); - DiHiggsAnalysis hh4b_analysis; - hh4b_analysis.getHiggsVars(); + DiHiggsAnalysis analysisObject; - // std::unordered_map<std::string, SG::AuxElement::Decorator<float>> - // m_diHiggs_decos; - for (const auto &[key, value] : hh4b_analysis.getHiggsVars()) + // create the decorators here once for the whole alg + for (const auto &[key, value] : analysisObject.m_diHiggs_vars) { - // SG::AuxElement::Decorator<float> HiggsVars_dec(key); - // m_diHiggs_decos[key] = HiggsVars_dec; - std::cout << key; + SG::AuxElement::Decorator<float> HiggsVars_dec(key); + m_diHiggs_decos.emplace(key, HiggsVars_dec); }; ATH_CHECK(m_EventInfoKey.initialize()); @@ -66,7 +56,12 @@ namespace HH4B DiHiggsAnalysis hh4b_analysis; hh4b_analysis.makeResolvedAnalysis(*antiKt4RecoJets); hh4b_analysis.makeBoostedAnalysis(*antiKt10RecoJets); - hh4b_analysis.decorateHiggsVars(*eventInfo); + + for (const auto &[key, value] : hh4b_analysis.getHiggsVars()) + { + SG::AuxElement::Decorator<float> HiggsVars_dec = m_diHiggs_decos.at(key); + HiggsVars_dec(*eventInfo) = value; + }; return StatusCode::SUCCESS; } -- GitLab From 8a5d60bb3e0bff6fd6d12b3ab7771ddf149d6329 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Mon, 22 Aug 2022 10:32:17 +0200 Subject: [PATCH 25/33] added analysis peer btagging working point --- HH4bAnalysis/share/VariableDumperConfig.py | 37 +++-- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 155 +++++++++++++++------ HH4bAnalysis/src/DiHiggsAnalysis.h | 38 +++-- HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx | 49 +++++-- HH4bAnalysis/src/DiHiggsAnalysisAlg.h | 8 +- 5 files changed, 199 insertions(+), 88 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 8579d87a3..aef94be08 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -323,6 +323,10 @@ def AnalysisAlgsCfg( EventInfoKey="EventInfo", SmallJetKey=containers["outputs"]["reco4Jet"].replace("%SYS%", "NOSYS"), LargeJetKey=containers["outputs"]["reco10Jet"].replace("%SYS%", "NOSYS"), + doResolvedAnalysis=True, + doBoostedAnalysis=True, + btag_wps=btag_wps, + vr_btag_wps=vr_btag_wps, ) ) @@ -432,18 +436,29 @@ def MiniTupleCfg( f"{containers['vrJet']}.ftag_select_{btag_wp} -> vrjet_%SYS%_{btag_wp}" for btag_wp in working_points["vr"] ] - analysisTreeBranches = [ - "EventInfo.resolved_m_h1 -> resolved_m_h1", - "EventInfo.resolved_m_h2 -> resolved_m_h2", - "EventInfo.resolved_m_hh -> resolved_m_hh", - "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", - "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", - "EventInfo.boosted_m_h1 -> boosted_m_h1", - "EventInfo.boosted_m_h2 -> boosted_m_h2", - "EventInfo.boosted_m_hh -> boosted_m_hh", - "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", - "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", + + # Di-Higgs Variables + analysisTreeBranches += [ + f"EventInfo.resolved_m_h1_{btag_wp} -> resolved_m_h1_{btag_wp}" + for btag_wp in working_points["ak4"] ] + analysisTreeBranches += [ + f"EventInfo.boosted_m_h1_{btag_wp} -> boosted_m_h1_{btag_wp}" + for btag_wp in working_points["vr"] + ] + + # analysisTreeBranches = [ + # "EventInfo.resolved_m_h1 -> resolved_m_h1", + # "EventInfo.resolved_m_h2 -> resolved_m_h2", + # "EventInfo.resolved_m_hh -> resolved_m_hh", + # "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", + # "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", + # "EventInfo.boosted_m_h1 -> boosted_m_h1", + # "EventInfo.boosted_m_h2 -> boosted_m_h2", + # "EventInfo.boosted_m_hh -> boosted_m_hh", + # "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", + # "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", + # ] log.info("Add tree seq") cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index b4c1c3e60..eced91fd6 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -8,10 +8,46 @@ using namespace asg::msgUserCode; namespace HH4B + { + std::vector<std::string> + getHiggsVarsNames(std::vector<std::string> &btag_wps, + std::vector<std::string> &vr_btag_wps) + { + std::vector<std::string> vars; + for (std::string wp : btag_wps) + { + vars.push_back("resolved_m_h1_" + wp); + vars.push_back("resolved_m_h2_" + wp); + vars.push_back("resolved_m_hh_" + wp); + vars.push_back("resolved_dR_jets_in_h1_" + wp); + vars.push_back("resolved_dR_jets_in_h2_" + wp); + } + for (std::string wp : vr_btag_wps) + { + vars.push_back("boosted_m_h1_" + wp); + vars.push_back("boosted_m_h2_" + wp); + vars.push_back("boosted_m_hh_" + wp); + vars.push_back("boosted_dR_jets_in_h1_" + wp); + vars.push_back("boosted_dR_jets_in_h2_" + wp); + } + return vars; + } + + void DiHiggsAnalysis::initHiggsVarsMap(std::vector<std::string> &higgsVars) + { + float initValue = -1; + for (std::string var : higgsVars) + { + m_higgsVarsMap.insert_or_assign(var, initValue); + } + return; + } + void - DiHiggsAnalysis::makeResolvedAnalysis(const xAOD::JetContainer &smallRjets) + DiHiggsAnalysis::makeResolvedAnalysis(const xAOD::JetContainer &smallRjets, + std::string wp) { // check if we have at least 4 jets if (smallRjets.size() < 4) @@ -23,25 +59,54 @@ namespace HH4B // subleading higgs candidate HiggsCandidate h2; + // this is a shallow copy container + ConstDataVector<xAOD::JetContainer> bTaggedJets(SG::VIEW_ELEMENTS); + + static const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + + wp); + // remove non-btagged jets of designated wp + // (fancy std::remove_if from boosted analysis only works with vectors) + for (const xAOD::Jet *jet : smallRjets) + { + // the ftag sequence does not tag all of them + if (!isBtag.isAvailable(*jet)) + { + ANA_MSG_DEBUG("Skipped non B-tagged jet"); + continue; + } + // keep only btagged jets with a designated wp + if (isBtag(*jet)) + { + bTaggedJets.push_back(jet); + } + } + + // check if we have at least 4 btagged jets + if (bTaggedJets.size() < 4) + { + return; + } + + ConstDataVector<xAOD::JetContainer> ptSortedBtaggedJets( + bTaggedJets.begin(), bTaggedJets.end(), SG::VIEW_ELEMENTS); + // taken from TJ's tutorial // https://gitlab.cern.ch/khoo/athanalysistutorial/-/blob/r22/MySecondAthAnalysis/src/DileptonFinderAlg.cxx // - // this is a shallow copy container - ConstDataVector<xAOD::JetContainer> ptSortedJets( - smallRjets.begin(), smallRjets.end(), SG::VIEW_ELEMENTS); // with std::partial_sort you only have to sort an N-sized container - // instead of sorting a ptSortedJets.size() container + // instead of sorting a ptSortedBtaggedJets.size() container std::partial_sort( - ptSortedJets.begin(), // Iterator from which to start sorting - ptSortedJets.begin() + 4, // Use begin + N to sort first N - ptSortedJets.end(), // Iterator marking the end of the range to sort + ptSortedBtaggedJets.begin(), // Iterator from which to start sorting + ptSortedBtaggedJets.begin() + 4, // Use begin + N to sort first N + ptSortedBtaggedJets.end(), // Iterator marking the end of range to sort [](const xAOD::IParticle *left, const xAOD::IParticle *right) { return left->pt() > right->pt(); - }); // lambda function here just handy, could also be another function + }); // lambda function here just handy, could also be another + // function that returns bool // get the leading b-jet for the leading Higgs candidate - h1.m_leadingJet = ptSortedJets[0]; + h1.m_leadingJet = ptSortedBtaggedJets[0]; // calculate dR to the next three leading jets and decorate jet static const SG::AuxElement::Decorator<float> dRtoLeadingJet_dec( @@ -50,13 +115,14 @@ namespace HH4B "dRtoLeadingJet"); // keep only the four leading ones - ptSortedJets.erase(ptSortedJets.begin() + 4, ptSortedJets.end()); + ptSortedBtaggedJets.erase(ptSortedBtaggedJets.begin() + 4, + ptSortedBtaggedJets.end()); // decorate dR(jet,leading jet) to each jet bool firstJet = true; - for (const xAOD::Jet *jet : ptSortedJets) + for (const xAOD::Jet *jet : ptSortedBtaggedJets) { - // more instructive as done with iterators + // more instructive than done with iterators if (firstJet) { dRtoLeadingJet_dec(*jet) = 0; @@ -68,7 +134,7 @@ namespace HH4B } // now find the closest one - ConstDataVector<xAOD::JetContainer> dRsortedJets = ptSortedJets; + ConstDataVector<xAOD::JetContainer> dRsortedJets = ptSortedBtaggedJets; std::partial_sort( dRsortedJets.begin(), // Iterator from which to start sorting dRsortedJets.begin() + 4, // Use begin + N to sort first N @@ -99,18 +165,20 @@ namespace HH4B h2.m_dRjets = ROOT::Math::VectorUtil::DeltaR(h2.m_leadingJet->jetP4(), h2.m_subleadingJet->jetP4()); - // write to dictionary - m_diHiggs_vars["resolved_m_h1"] = h1.m_fourVector.M(); - m_diHiggs_vars["resolved_m_h2"] = h2.m_fourVector.M(); - m_diHiggs_vars["resolved_m_hh"] = (h1.m_fourVector + h2.m_fourVector).M(); - m_diHiggs_vars["resolved_dR_jets_in_h1"] = h1.m_dRjets; - m_diHiggs_vars["resolved_dR_jets_in_h2"] = h2.m_dRjets; + // write to map + m_higgsVarsMap["resolved_m_h1_" + wp] = h1.m_fourVector.M(); + m_higgsVarsMap["resolved_m_h2_" + wp] = h2.m_fourVector.M(); + m_higgsVarsMap["resolved_m_hh_" + wp] = + (h1.m_fourVector + h2.m_fourVector).M(); + m_higgsVarsMap["resolved_dR_jets_in_h1_" + wp] = h1.m_dRjets; + m_higgsVarsMap["resolved_dR_jets_in_h2_" + wp] = h2.m_dRjets; return; }; void - DiHiggsAnalysis::makeBoostedAnalysis(const xAOD::JetContainer &largeRjets) + DiHiggsAnalysis::makeBoostedAnalysis(const xAOD::JetContainer &largeRjets, + std::string wp) { // TODO: list @@ -134,9 +202,10 @@ namespace HH4B // subleading higgs candidate HiggsCandidate h2; - // get the leading large R, see resvoled analysis for details + // get the leading large R in a shallow copy container ConstDataVector<xAOD::JetContainer> ptSortedLargeRJets( largeRjets.begin(), largeRjets.end(), SG::VIEW_ELEMENTS); + // for details on sorting see resolved std::partial_sort( ptSortedLargeRJets.begin(), // Iterator from which to start sorting ptSortedLargeRJets.begin() + 2, // Use begin + N to sort first N @@ -153,12 +222,12 @@ namespace HH4B static const SG::AuxElement::ConstAccessor< std::vector<ElementLink<xAOD::IParticleContainer>>> m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); - static const SG::AuxElement::ConstAccessor<char> isBtag( - "ftag_select_DL1r_FixedCutBEff_77"); + static const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + + wp); - // loop over the Higgs Candidate large R jets to get the btagged VR jets - // inside of each, need to do std::ref to access the actual objects h1, h2 - // "for (HiggsCandidate h : {h1, h2})" would make copies of h1, h2 + // loop over the Higgs Candidate large R jets, get the btagged VR jets + // inside of each, need to do std::ref to access the actual objects h1, + // h2. "for (HiggsCandidate h : {h1, h2})" would make copies of h1, h2 for (HiggsCandidate &h : {std::ref(h1), std::ref(h2)}) { // get ghost associated VR track jets from untrimmed large R jet @@ -170,8 +239,6 @@ namespace HH4B // get the btagged VR trackjets per large R jet // remove VRjets with invalid elementlinks and non-btagged ones // should we handle this differently? - // can't just remove in for loop, get in trouble with iterator, could do - // with while loop but std::remove_if is more efficient VRTrackjets.erase( std::remove_if(VRTrackjets.begin(), VRTrackjets.end(), [](ElementLink<xAOD::IParticleContainer> &VRjet) @@ -181,11 +248,17 @@ namespace HH4B ANA_MSG_WARNING("Skipped invalid VR jet link!"); return true; } + // the ftag sequence does not tag all of them if (!isBtag.isAvailable(**VRjet)) { ANA_MSG_DEBUG("Skipped non B-tagged VR jet"); return true; } + // keep only btagged jets with a designated wp + if (!isBtag(**VRjet)) + { + return true; + } return false; }), VRTrackjets.end()); @@ -214,25 +287,19 @@ namespace HH4B h.m_subleadingJet->jetP4()); } - // write to dictionary - m_diHiggs_vars["boosted_m_h1"] = h1.m_fourVector.M(); - m_diHiggs_vars["boosted_m_h2"] = h2.m_fourVector.M(); - m_diHiggs_vars["boosted_m_hh"] = (h1.m_fourVector + h2.m_fourVector).M(); - m_diHiggs_vars["boosted_dR_jets_in_h1"] = h1.m_dRjets; - m_diHiggs_vars["boosted_dR_jets_in_h2"] = h2.m_dRjets; + // write to map + m_higgsVarsMap["boosted_m_h1_" + wp] = h1.m_fourVector.M(); + m_higgsVarsMap["boosted_m_h2_" + wp] = h2.m_fourVector.M(); + m_higgsVarsMap["boosted_m_hh_" + wp] = + (h1.m_fourVector + h2.m_fourVector).M(); + m_higgsVarsMap["boosted_dR_jets_in_h1_" + wp] = h1.m_dRjets; + m_higgsVarsMap["boosted_dR_jets_in_h2_" + wp] = h2.m_dRjets; return; }; - std::unordered_map<std::string, float> DiHiggsAnalysis::getHiggsVars() + std::unordered_map<std::string, float> DiHiggsAnalysis::getHiggsVarsMap() { - return m_diHiggs_vars; + return m_higgsVarsMap; }; - void DiHiggsAnalysis::decorateHiggsVars(const xAOD::EventInfo &eventInfo) - { - for (const auto &[key, value] : m_diHiggs_vars) - { - eventInfo.auxdecor<float>(key) = value; - }; - } }; diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index 280582e62..55596aec4 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -7,12 +7,18 @@ namespace HH4B { + + // make Higgs vars names list with attached btagging working points + std::vector<std::string> + getHiggsVarsNames(std::vector<std::string> &btag_wps, + std::vector<std::string> &vr_btag_wps); + struct HiggsCandidate { // b-jets for Higgs candidate const xAOD::Jet *m_leadingJet = nullptr; const xAOD::Jet *m_subleadingJet = nullptr; - // four vector of Higgs candidate + // four vector of Higgs candidate, (this is faster than TLorentzVector) ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float>> m_fourVector; // dR between leading and subleading jet float m_dRjets = -1; @@ -23,31 +29,21 @@ namespace HH4B class DiHiggsAnalysis { public: + // initialize vars in m_higgsVarsMap + void initHiggsVarsMap(std::vector<std::string> &higgsVars); // do resolved Analysis - void makeResolvedAnalysis(const xAOD::JetContainer &smallRjets); + void makeResolvedAnalysis(const xAOD::JetContainer &smallRjets, + std::string wp); // do boosted Analysis - void makeBoostedAnalysis(const xAOD::JetContainer &largeRjets); + void makeBoostedAnalysis(const xAOD::JetContainer &largeRjets, + std::string wp); // returns h_cand_vars for other purposes - std::unordered_map<std::string, float> getHiggsVars(); - // decorates the h_cand_vars to the eventInfo - void decorateHiggsVars(const xAOD::EventInfo &eventInfo); - // DiHiggs variables init value - float m_initValue = -1; - // map holding the final vars + std::unordered_map<std::string, float> getHiggsVarsMap(); + // map holding the final vars (like dict in python) + // access/write like : m_diHiggs_vars[var]; // unordered_map is faster than map as it does the lookup with a hash and // not by string comparison - std::unordered_map<std::string, float> m_diHiggs_vars{ - {"resolved_m_h1", m_initValue}, - {"resolved_m_h2", m_initValue}, - {"resolved_m_hh", m_initValue}, - {"resolved_dR_jets_in_h1", m_initValue}, - {"resolved_dR_jets_in_h2", m_initValue}, - {"boosted_m_h1", m_initValue}, - {"boosted_m_h2", m_initValue}, - {"boosted_m_hh", m_initValue}, - {"boosted_dR_jets_in_h1", m_initValue}, - {"boosted_dR_jets_in_h2", m_initValue}, - }; + std::unordered_map<std::string, float> m_higgsVarsMap; }; } #endif diff --git a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx index 0ba1386dd..3ab13395e 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx @@ -15,19 +15,21 @@ namespace HH4B { declareProperty("doResolvedAnalysis", m_doResolvedAnalysis); declareProperty("doBoostedAnalysis", m_doBoostedAnalysis); + declareProperty("btag_wps", m_btag_wps); + declareProperty("vr_btag_wps", m_vr_btag_wps); } StatusCode DiHiggsAnalysisAlg ::initialize() { ATH_MSG_DEBUG("Initialising " << name()); - DiHiggsAnalysis analysisObject; - - // create the decorators here once for the whole alg - for (const auto &[key, value] : analysisObject.m_diHiggs_vars) + // get to be used Higgs vars to create the final decorators here so they + // are created once per alg and not per event + m_higgsVars = getHiggsVarsNames(m_btag_wps, m_vr_btag_wps); + for (std::string var : m_higgsVars) { - SG::AuxElement::Decorator<float> HiggsVars_dec(key); - m_diHiggs_decos.emplace(key, HiggsVars_dec); + SG::AuxElement::Decorator<float> HiggsVars_dec(var); + m_diHiggs_decos.emplace(var, HiggsVars_dec); }; ATH_CHECK(m_EventInfoKey.initialize()); @@ -39,6 +41,11 @@ namespace HH4B StatusCode DiHiggsAnalysisAlg ::execute() { + // jump out if no analysis is selected + if (!m_doResolvedAnalysis or !m_doResolvedAnalysis) + { + return StatusCode::SUCCESS; + } ATH_MSG_DEBUG("Executing " << name()); // get the xAOD objects @@ -54,15 +61,35 @@ namespace HH4B // create the analysis object DiHiggsAnalysis hh4b_analysis; - hh4b_analysis.makeResolvedAnalysis(*antiKt4RecoJets); - hh4b_analysis.makeBoostedAnalysis(*antiKt10RecoJets); + // write defaults (-1) into the Higgs variable map + hh4b_analysis.initHiggsVarsMap(m_higgsVars); + + // which analyses to do + if (m_doResolvedAnalysis) + { + for (std::string wp : m_btag_wps) + { + hh4b_analysis.makeResolvedAnalysis(*antiKt4RecoJets, wp); + } + } + if (m_doBoostedAnalysis) + { + for (std::string wp : m_vr_btag_wps) + { + hh4b_analysis.makeBoostedAnalysis(*antiKt10RecoJets, wp); + } + } - for (const auto &[key, value] : hh4b_analysis.getHiggsVars()) + // get higgs vars map (behaves like dict in python) + std::unordered_map<std::string, float> higgsVarsMap = + hh4b_analysis.getHiggsVarsMap(); + // loop over decorators + for (const auto &[var, value] : higgsVarsMap) { - SG::AuxElement::Decorator<float> HiggsVars_dec = m_diHiggs_decos.at(key); + SG::AuxElement::Decorator<float> HiggsVars_dec = m_diHiggs_decos.at(var); HiggsVars_dec(*eventInfo) = value; }; return StatusCode::SUCCESS; } -} \ No newline at end of file +} diff --git a/HH4bAnalysis/src/DiHiggsAnalysisAlg.h b/HH4bAnalysis/src/DiHiggsAnalysisAlg.h index fd047aab4..bd204fe36 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysisAlg.h +++ b/HH4bAnalysis/src/DiHiggsAnalysisAlg.h @@ -55,10 +55,16 @@ private: SG::ReadHandleKey<xAOD::JetContainer> m_LargeJetKey{ this, "LargeJetKey", "", "the large-R jet collection to run on"}; + // whether the algorithm should do one of the following analyses bool m_doResolvedAnalysis; bool m_doBoostedAnalysis; + // btagging working points for 0.4 jets + std::vector<std::string> m_btag_wps; + // btagging working points for the variable radius track jets in 1.0 jets + std::vector<std::string> m_vr_btag_wps; + // list of to be used Higgs vars + std::vector<std::string> m_higgsVars; }; - } #endif -- GitLab From 99f7d9240ecc70ccdae2b157c4456e47825a5ad6 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Mon, 22 Aug 2022 17:37:39 +0200 Subject: [PATCH 26/33] added config, some boosted cuts --- HH4bAnalysis/python/Algs/DiHiggsAnalysis.py | 49 ++++++++++++++++ HH4bAnalysis/share/VariableDumperConfig.py | 58 +++++++++---------- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 64 ++++++++++++++------- 3 files changed, 118 insertions(+), 53 deletions(-) create mode 100644 HH4bAnalysis/python/Algs/DiHiggsAnalysis.py diff --git a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py new file mode 100644 index 000000000..1c9c72296 --- /dev/null +++ b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py @@ -0,0 +1,49 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def DiHiggsAnalysisAlgCfg( + SmallJetKey, + LargeJetKey, + btag_wps, + vr_btag_wps, +): + + cfg = ComponentAccumulator() + cfg.addEventAlgo( + CompFactory.HH4B.DiHiggsAnalysisAlg( + "DiHiggsAnalysis", + EventInfoKey="EventInfo", + SmallJetKey=SmallJetKey, + LargeJetKey=LargeJetKey, + doResolvedAnalysis=True, + doBoostedAnalysis=True, + btag_wps=btag_wps, + vr_btag_wps=vr_btag_wps, + ) + ) + return cfg + + +def DiHiggsAnalysisAddBranches(working_points): + analysisTreeBranches = [] + vars = [ + "m_h1", + "m_h2", + "m_hh", + "dR_jets_in_h1", + "dR_jets_in_h2", + ] + # looks like resolved_DL1r_FixedCutBEff_77_m_hh + for btag_wp in working_points["ak4"]: + for var in vars: + analysisTreeBranches += [ + f"EventInfo.resolved_{var}_{btag_wp} -> resolved_{btag_wp}_{var}" + ] + # actually needs if, if boosted will be configurable + for btag_wp in working_points["vr"]: + for var in vars: + analysisTreeBranches += [ + f"EventInfo.boosted_{var}_{btag_wp} -> boosted_{btag_wp}_{var}" + ] + return analysisTreeBranches diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index aef94be08..58f4a074d 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -16,6 +16,10 @@ from AthenaCommon import Logging from AthenaConfiguration.AutoConfigFlags import GetFileMD from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory +from HH4bAnalysis.Algs.DiHiggsAnalysis import ( + DiHiggsAnalysisAddBranches, + DiHiggsAnalysisAlgCfg, +) from HH4bAnalysis.Algs.Electrons import ElectronAnalysisSequenceCfg from HH4bAnalysis.Algs.Event import ( EventSelectionAnalysisSequenceCfg, @@ -91,6 +95,11 @@ def defineArgs(ConfigFlags): action="store_true", help="use loose event cleaning (to get something to pass)", ) + parser.add_argument( + "--do_dihiggs_analysis", + action="store_true", + help="use loose event cleaning (to get something to pass)", + ) return parser @@ -161,6 +170,7 @@ def AnalysisAlgsCfg( do_PRW=False, prw_files=[], lumicalc_files=[], + do_dihiggs_analysis=False, ): if metadata_cache: update_metadata(metadata_cache) @@ -317,18 +327,18 @@ def AnalysisAlgsCfg( if metadata_cache: cache_metadata(metadata_cache) - cfg.addEventAlgo( - CompFactory.HH4B.DiHiggsAnalysisAlg( - "DiHiggsAnalysis", - EventInfoKey="EventInfo", - SmallJetKey=containers["outputs"]["reco4Jet"].replace("%SYS%", "NOSYS"), - LargeJetKey=containers["outputs"]["reco10Jet"].replace("%SYS%", "NOSYS"), - doResolvedAnalysis=True, - doBoostedAnalysis=True, - btag_wps=btag_wps, - vr_btag_wps=vr_btag_wps, + if do_dihiggs_analysis: + cfg.merge( + DiHiggsAnalysisAlgCfg( + SmallJetKey=containers["outputs"]["reco4Jet"].replace("%SYS%", "NOSYS"), + LargeJetKey=containers["outputs"]["reco10Jet"].replace( + "%SYS%", + "NOSYS", + ), + btag_wps=btag_wps, + vr_btag_wps=vr_btag_wps, + ) ) - ) return cfg @@ -340,6 +350,7 @@ def MiniTupleCfg( working_points, do_muons=True, do_PRW=False, + do_dihiggs_analysis=False, ): cfg = ComponentAccumulator() is_daod_physlite = _is_physlite(flags) @@ -437,28 +448,9 @@ def MiniTupleCfg( for btag_wp in working_points["vr"] ] - # Di-Higgs Variables - analysisTreeBranches += [ - f"EventInfo.resolved_m_h1_{btag_wp} -> resolved_m_h1_{btag_wp}" - for btag_wp in working_points["ak4"] - ] - analysisTreeBranches += [ - f"EventInfo.boosted_m_h1_{btag_wp} -> boosted_m_h1_{btag_wp}" - for btag_wp in working_points["vr"] - ] + if do_dihiggs_analysis: + analysisTreeBranches += DiHiggsAnalysisAddBranches(working_points) - # analysisTreeBranches = [ - # "EventInfo.resolved_m_h1 -> resolved_m_h1", - # "EventInfo.resolved_m_h2 -> resolved_m_h2", - # "EventInfo.resolved_m_hh -> resolved_m_hh", - # "EventInfo.resolved_dR_jets_in_h1 -> resolved_dR_jets_in_h1", - # "EventInfo.resolved_dR_jets_in_h2 -> resolved_dR_jets_in_h2", - # "EventInfo.boosted_m_h1 -> boosted_m_h1", - # "EventInfo.boosted_m_h2 -> boosted_m_h2", - # "EventInfo.boosted_m_hh -> boosted_m_hh", - # "EventInfo.boosted_dR_jets_in_h1 -> boosted_dR_jets_in_h1", - # "EventInfo.boosted_dR_jets_in_h2 -> boosted_dR_jets_in_h2", - # ] log.info("Add tree seq") cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) @@ -574,6 +566,7 @@ def main(): do_PRW=do_PRW, prw_files=prw_files, lumicalc_files=lumicalc_files, + do_dihiggs_analysis=args.do_dihiggs_analysis, ), "HH4bSeq", ) @@ -585,6 +578,7 @@ def main(): working_points={"ak4": args.btag_wps, "vr": args.vr_btag_wps}, do_muons=do_muons, do_PRW=do_PRW, + do_dihiggs_analysis=args.do_dihiggs_analysis, ), "HH4bSeq", ) diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index eced91fd6..62edba6b1 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -37,7 +37,7 @@ namespace HH4B void DiHiggsAnalysis::initHiggsVarsMap(std::vector<std::string> &higgsVars) { - float initValue = -1; + float initValue = -1.; for (std::string var : higgsVars) { m_higgsVarsMap.insert_or_assign(var, initValue); @@ -61,7 +61,7 @@ namespace HH4B // this is a shallow copy container ConstDataVector<xAOD::JetContainer> bTaggedJets(SG::VIEW_ELEMENTS); - + // accessor for the btagging info on the jet static const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + wp); // remove non-btagged jets of designated wp @@ -180,18 +180,6 @@ namespace HH4B DiHiggsAnalysis::makeBoostedAnalysis(const xAOD::JetContainer &largeRjets, std::string wp) { - // TODO: list - - // cuts - // recommended by ftag : Remove the event if any of your signal jets have - // relativeDeltaRToVRJet < 1.0. - // least pt of large R's 250 - // largest pt jet large R at least 450 - // eta < 2.0 - - // delta eta between large r jets - // make btagging configurable - // check if we have at least 2 large R jets if (largeRjets.size() < 2) { @@ -213,6 +201,21 @@ namespace HH4B [](const xAOD::IParticle *left, const xAOD::IParticle *right) { return left->pt() > right->pt(); }); + // cuts from + // https://cds.cern.ch/record/2708599/files/ATL-COM-PHYS-2020-083.pdf don't + // use "or" here as the || operator is short-circuited in c++, which means + // in the OR checking case it stops checking conditions once one becomes + // true + if (ptSortedLargeRJets[0]->pt() < 450. || + ptSortedLargeRJets[1]->pt() < 250. || + ptSortedLargeRJets[0]->eta() > 2.0 || + ptSortedLargeRJets[0]->m() < 50. || ptSortedLargeRJets[1]->m() < 50. || + std::abs(ptSortedLargeRJets[0]->eta() - ptSortedLargeRJets[0]->eta()) > + 1.3) + { + return; + } + h1.m_largeRJet = ptSortedLargeRJets[0]; h2.m_largeRJet = ptSortedLargeRJets[1]; @@ -222,8 +225,13 @@ namespace HH4B static const SG::AuxElement::ConstAccessor< std::vector<ElementLink<xAOD::IParticleContainer>>> m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); - static const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + - wp); + // accessor for the btagging info on the jet + const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + wp); + // recommended by ftag : Remove the event if any of your signal jets have + // relativeDeltaRToVRJet < 1.0. + const SG::AuxElement::ConstAccessor<float> relativeDeltaRToVRJet( + "relativeDeltaRToVRJet"); + bool isRelativeDeltaRToVRJet = false; // loop over the Higgs Candidate large R jets, get the btagged VR jets // inside of each, need to do std::ref to access the actual objects h1, @@ -237,11 +245,16 @@ namespace HH4B m_acc_VRTrackJets(*untrimmedLargeR); // get the btagged VR trackjets per large R jet - // remove VRjets with invalid elementlinks and non-btagged ones - // should we handle this differently? + // remove_if is efficient, because you don't have to copy things + // somewhere else + // remove VRjets with invalid ElementLinks and non-btagged + // ones, should we handle this differently? VRTrackjets.erase( std::remove_if(VRTrackjets.begin(), VRTrackjets.end(), - [](ElementLink<xAOD::IParticleContainer> &VRjet) + [&isRelativeDeltaRToVRJet, &relativeDeltaRToVRJet, + &isBtag] // need to "capture" external variables for + // the lambda function + (ElementLink<xAOD::IParticleContainer> & VRjet) { if (!VRjet.isValid()) { @@ -259,12 +272,21 @@ namespace HH4B { return true; } + // recommended by ftag : Remove the event if any of + // your signal jets have + // relativeDeltaRToVRJet < 1.0. + if (relativeDeltaRToVRJet(**VRjet) < 1.0) + { + isRelativeDeltaRToVRJet = true; + } + return false; }), VRTrackjets.end()); - // check if we have at least 2 per large R jet, otherwise exit - if (VRTrackjets.size() < 2) + // check if we have at least 2 per large R jet and no + // isRelativeDeltaRToVRJet + if (VRTrackjets.size() < 2 || isRelativeDeltaRToVRJet) { return; } -- GitLab From 3075fc21cc317220e701ff27ea30544eedf21abb Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Mon, 22 Aug 2022 17:47:19 +0200 Subject: [PATCH 27/33] fixing pipeline --- HH4bAnalysis/share/VariableDumperConfig.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 58f4a074d..9dcd59a37 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -559,7 +559,7 @@ def main(): ConfigFlags, btag_wps=args.btag_wps, vr_btag_wps=args.vr_btag_wps, - trigger_chains=[trigger_chains], + trigger_chains=trigger_chains, metadata_cache=args.meta_cache, do_muons=do_muons, do_loose=args.loose, @@ -574,7 +574,7 @@ def main(): MiniTupleCfg( ConfigFlags, outfname=args.outFile, - trigger_chains=[trigger_chains], + trigger_chains=trigger_chains, working_points={"ak4": args.btag_wps, "vr": args.vr_btag_wps}, do_muons=do_muons, do_PRW=do_PRW, -- GitLab From 2686e2e7454732d64b82b09dadbbedc658308efa Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Wed, 24 Aug 2022 11:28:33 +0200 Subject: [PATCH 28/33] improve config --- HH4bAnalysis/python/Algs/DiHiggsAnalysis.py | 36 +++++++++++-------- .../python/Config/AnalysisAlgsConfig.py | 2 ++ HH4bAnalysis/share/VariableDumperConfig.py | 1 + HH4bAnalysis/src/DiHiggsAnalysis.cxx | 8 ++--- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py index 1c9c72296..19bbf1680 100644 --- a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py +++ b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py @@ -5,10 +5,11 @@ from AthenaConfiguration.ComponentFactory import CompFactory def DiHiggsAnalysisAlgCfg( SmallJetKey, LargeJetKey, + doResolvedAnalysis, + doBoostedAnalysis, btag_wps, vr_btag_wps, ): - cfg = ComponentAccumulator() cfg.addEventAlgo( CompFactory.HH4B.DiHiggsAnalysisAlg( @@ -16,12 +17,18 @@ def DiHiggsAnalysisAlgCfg( EventInfoKey="EventInfo", SmallJetKey=SmallJetKey, LargeJetKey=LargeJetKey, - doResolvedAnalysis=True, - doBoostedAnalysis=True, + doResolvedAnalysis=doResolvedAnalysis, + doBoostedAnalysis=doBoostedAnalysis, btag_wps=btag_wps, vr_btag_wps=vr_btag_wps, ) ) + # make them global to use them in the tree config + global globDoResolvedAnalysis + globDoResolvedAnalysis = doResolvedAnalysis + global globDoBoostedAnalysis + globDoBoostedAnalysis = doBoostedAnalysis + return cfg @@ -35,15 +42,16 @@ def DiHiggsAnalysisAddBranches(working_points): "dR_jets_in_h2", ] # looks like resolved_DL1r_FixedCutBEff_77_m_hh - for btag_wp in working_points["ak4"]: - for var in vars: - analysisTreeBranches += [ - f"EventInfo.resolved_{var}_{btag_wp} -> resolved_{btag_wp}_{var}" - ] - # actually needs if, if boosted will be configurable - for btag_wp in working_points["vr"]: - for var in vars: - analysisTreeBranches += [ - f"EventInfo.boosted_{var}_{btag_wp} -> boosted_{btag_wp}_{var}" - ] + if globDoResolvedAnalysis: + for btag_wp in working_points["ak4"]: + for var in vars: + analysisTreeBranches += [ + f"EventInfo.resolved_{var}_{btag_wp} -> resolved_{btag_wp}_{var}" + ] + if globDoBoostedAnalysis: + for btag_wp in working_points["vr"]: + for var in vars: + analysisTreeBranches += [ + f"EventInfo.boosted_{var}_{btag_wp} -> boosted_{btag_wp}_{var}" + ] return analysisTreeBranches diff --git a/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py b/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py index 68f743893..b2c61cc9d 100644 --- a/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py +++ b/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py @@ -198,6 +198,8 @@ def AnalysisAlgsCfg( "%SYS%", "NOSYS", ), + doResolvedAnalysis=True, + doBoostedAnalysis=True, btag_wps=btag_wps, vr_btag_wps=vr_btag_wps, ) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 5654b7533..69478dbe3 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -35,6 +35,7 @@ def defineArgs(ConfigFlags): type=str, nargs="*", default=[ + "DL1dv00_FixedCutBEff_70", "DL1dv00_FixedCutBEff_77", "DL1dv00_FixedCutBEff_85", ], diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index 62edba6b1..c26d40d29 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -202,10 +202,10 @@ namespace HH4B { return left->pt() > right->pt(); }); // cuts from - // https://cds.cern.ch/record/2708599/files/ATL-COM-PHYS-2020-083.pdf don't - // use "or" here as the || operator is short-circuited in c++, which means - // in the OR checking case it stops checking conditions once one becomes - // true + // https://cds.cern.ch/record/2708599/files/ATL-COM-PHYS-2020-083.pdf + // don't use "or" here as the || operator is short-circuited in c++, which + // means in the OR checking case it stops checking conditions once one + // becomes true if (ptSortedLargeRJets[0]->pt() < 450. || ptSortedLargeRJets[1]->pt() < 250. || ptSortedLargeRJets[0]->eta() > 2.0 || -- GitLab From f67fbd182dca2b8dc9ee82265ab6d630b439a088 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 25 Aug 2022 10:06:50 +0200 Subject: [PATCH 29/33] added vr jet counters --- HH4bAnalysis/python/Algs/DiHiggsAnalysis.py | 9 +- .../python/Config/AnalysisAlgsConfig.py | 3 +- HH4bAnalysis/src/DiHiggsAnalysis.cxx | 179 +++++++++++------- HH4bAnalysis/src/DiHiggsAnalysis.h | 9 +- HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx | 8 - 5 files changed, 124 insertions(+), 84 deletions(-) diff --git a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py index 19bbf1680..f99f1824f 100644 --- a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py +++ b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py @@ -41,7 +41,7 @@ def DiHiggsAnalysisAddBranches(working_points): "dR_jets_in_h1", "dR_jets_in_h2", ] - # looks like resolved_DL1r_FixedCutBEff_77_m_hh + if globDoResolvedAnalysis: for btag_wp in working_points["ak4"]: for var in vars: @@ -49,9 +49,16 @@ def DiHiggsAnalysisAddBranches(working_points): f"EventInfo.resolved_{var}_{btag_wp} -> resolved_{btag_wp}_{var}" ] if globDoBoostedAnalysis: + vars += [ + "h1_nGhostAssocVrJets", + "h1_nBtaggedGhostAssocVrTrackJets", + "h2_nGhostAssocVrJets", + "h2_nBtaggedGhostAssocVrTrackJets", + ] for btag_wp in working_points["vr"]: for var in vars: analysisTreeBranches += [ f"EventInfo.boosted_{var}_{btag_wp} -> boosted_{btag_wp}_{var}" ] + return analysisTreeBranches diff --git a/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py b/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py index b2c61cc9d..d9c3ef979 100644 --- a/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py +++ b/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py @@ -195,8 +195,7 @@ def AnalysisAlgsCfg( DiHiggsAnalysisAlgCfg( SmallJetKey=containers["outputs"]["reco4Jet"].replace("%SYS%", "NOSYS"), LargeJetKey=containers["outputs"]["reco10Jet"].replace( - "%SYS%", - "NOSYS", + "%SYS%", "NOSYS" ), doResolvedAnalysis=True, doBoostedAnalysis=True, diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.cxx b/HH4bAnalysis/src/DiHiggsAnalysis.cxx index c26d40d29..408cf6d7e 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysis.cxx @@ -31,6 +31,10 @@ namespace HH4B vars.push_back("boosted_m_hh_" + wp); vars.push_back("boosted_dR_jets_in_h1_" + wp); vars.push_back("boosted_dR_jets_in_h2_" + wp); + vars.push_back("boosted_h1_nGhostAssocVrJets_" + wp); + vars.push_back("boosted_h1_nBtaggedGhostAssocVrTrackJets_" + wp); + vars.push_back("boosted_h2_nGhostAssocVrJets_" + wp); + vars.push_back("boosted_h2_nBtaggedGhostAssocVrTrackJets_" + wp); } return vars; } @@ -166,13 +170,13 @@ namespace HH4B h2.m_subleadingJet->jetP4()); // write to map + // clang-format off m_higgsVarsMap["resolved_m_h1_" + wp] = h1.m_fourVector.M(); m_higgsVarsMap["resolved_m_h2_" + wp] = h2.m_fourVector.M(); - m_higgsVarsMap["resolved_m_hh_" + wp] = - (h1.m_fourVector + h2.m_fourVector).M(); + m_higgsVarsMap["resolved_m_hh_" + wp] = (h1.m_fourVector + h2.m_fourVector).M(); m_higgsVarsMap["resolved_dR_jets_in_h1_" + wp] = h1.m_dRjets; m_higgsVarsMap["resolved_dR_jets_in_h2_" + wp] = h2.m_dRjets; - + // clang-format on return; }; @@ -206,12 +210,15 @@ namespace HH4B // don't use "or" here as the || operator is short-circuited in c++, which // means in the OR checking case it stops checking conditions once one // becomes true - if (ptSortedLargeRJets[0]->pt() < 450. || - ptSortedLargeRJets[1]->pt() < 250. || + if (ptSortedLargeRJets[0]->pt() < 250. || // + ptSortedLargeRJets[1]->pt() < 250. || // ptSortedLargeRJets[0]->eta() > 2.0 || - ptSortedLargeRJets[0]->m() < 50. || ptSortedLargeRJets[1]->m() < 50. || - std::abs(ptSortedLargeRJets[0]->eta() - ptSortedLargeRJets[0]->eta()) > - 1.3) + ptSortedLargeRJets[1]->eta() > 2.0 + // ||Â ptSortedLargeRJets[0]->m() < 50. + // || ptSortedLargeRJets[1]->m() < 50. + // || std::abs(ptSortedLargeRJets[0]->eta() - + // ptSortedLargeRJets[0]->eta()) > 1.3 + ) { return; } @@ -219,17 +226,20 @@ namespace HH4B h1.m_largeRJet = ptSortedLargeRJets[0]; h2.m_largeRJet = ptSortedLargeRJets[1]; + // @note create needed accessors // ghost associated VR track jets are only on the untrimmed 1.0 jets static const SG::AuxElement::ConstAccessor<ElementLink<xAOD::JetContainer>> m_acc_largeR_untrimmed("Parent"); static const SG::AuxElement::ConstAccessor< std::vector<ElementLink<xAOD::IParticleContainer>>> m_acc_VRTrackJets("GhostAntiKtVR30Rmax4Rmin02PV0TrackJets"); - // accessor for the btagging info on the jet - const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + wp); + // accessor for the btagging info on the jet, no static because forwarded + // to function + static const SG::AuxElement::ConstAccessor<char> isBtag("ftag_select_" + + wp); // recommended by ftag : Remove the event if any of your signal jets have // relativeDeltaRToVRJet < 1.0. - const SG::AuxElement::ConstAccessor<float> relativeDeltaRToVRJet( + static const SG::AuxElement::ConstAccessor<float> relativeDeltaRToVRJet( "relativeDeltaRToVRJet"); bool isRelativeDeltaRToVRJet = false; @@ -244,78 +254,104 @@ namespace HH4B std::vector<ElementLink<xAOD::IParticleContainer>> VRTrackjets = m_acc_VRTrackJets(*untrimmedLargeR); - // get the btagged VR trackjets per large R jet + // filter VR jets // remove_if is efficient, because you don't have to copy things // somewhere else - // remove VRjets with invalid ElementLinks and non-btagged - // ones, should we handle this differently? + int nGhostAssocVrJets = 0; VRTrackjets.erase( - std::remove_if(VRTrackjets.begin(), VRTrackjets.end(), - [&isRelativeDeltaRToVRJet, &relativeDeltaRToVRJet, - &isBtag] // need to "capture" external variables for - // the lambda function - (ElementLink<xAOD::IParticleContainer> & VRjet) - { - if (!VRjet.isValid()) - { - ANA_MSG_WARNING("Skipped invalid VR jet link!"); - return true; - } - // the ftag sequence does not tag all of them - if (!isBtag.isAvailable(**VRjet)) - { - ANA_MSG_DEBUG("Skipped non B-tagged VR jet"); - return true; - } - // keep only btagged jets with a designated wp - if (!isBtag(**VRjet)) - { - return true; - } - // recommended by ftag : Remove the event if any of - // your signal jets have - // relativeDeltaRToVRJet < 1.0. - if (relativeDeltaRToVRJet(**VRjet) < 1.0) - { - isRelativeDeltaRToVRJet = true; - } - - return false; - }), + std::remove_if( + VRTrackjets.begin(), VRTrackjets.end(), + [&nGhostAssocVrJets, + &isRelativeDeltaRToVRJet] // need to "capture" external + // variables for the lambda function + (ElementLink<xAOD::IParticleContainer> & VRjet) + { + // count only the ftagged ones + if ((*VRjet)->pt() > 10.) + { + nGhostAssocVrJets += 1; + } + if (!VRjet.isValid()) + { + ANA_MSG_WARNING("Skipped invalid VR jet link!"); + return true; + } + // the ftag sequence does not tag all of them + if (!isBtag.isAvailable(**VRjet)) + { + ANA_MSG_DEBUG("Skipped non B-tagged VR jet"); + return true; + } + // keep only btagged jets with a designated wp + // (the ftag sequence also cuts on 10GeV) + if (!isBtag(**VRjet)) + { + return true; + } + // recommended by ftag : Remove the event if any of + // your signal jets have + // relativeDeltaRToVRJet < 1.0. + if (relativeDeltaRToVRJet(**VRjet) < 1.0) + { + isRelativeDeltaRToVRJet = true; + } + + return false; + }), VRTrackjets.end()); + h.m_nGhostAssocVrJets = nGhostAssocVrJets; + h.m_nBtaggedGhostAssocVrJets = VRTrackjets.size(); + // check if we have at least 2 per large R jet and no - // isRelativeDeltaRToVRJet + // isRelativeDeltaRToVRJet < 1.0 if (VRTrackjets.size() < 2 || isRelativeDeltaRToVRJet) { - return; + h.m_doDecorate = false; + } + else + { + // find the leading vr jets + std::partial_sort( + VRTrackjets.begin(), // Iterator from which to start sorting + VRTrackjets.begin() + 2, // Use begin + N to sort first N + VRTrackjets.end(), // iterator to end + [](ElementLink<xAOD::IParticleContainer> &left, + ElementLink<xAOD::IParticleContainer> &right) + { return (*left)->pt() > (*right)->pt(); }); + + h.m_leadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[0]); + h.m_subleadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[1]); + + // calc variables + h.m_fourVector = h.m_leadingJet->jetP4() + h.m_subleadingJet->jetP4(); + h.m_dRjets = ROOT::Math::VectorUtil::DeltaR( + h.m_leadingJet->jetP4(), h.m_subleadingJet->jetP4()); } - - // find the leading vr jets - std::partial_sort( - VRTrackjets.begin(), // Iterator from which to start sorting - VRTrackjets.begin() + 2, // Use begin + N to sort first N - VRTrackjets.end(), // iterator to end - [](ElementLink<xAOD::IParticleContainer> &left, - ElementLink<xAOD::IParticleContainer> &right) - { return (*left)->pt() > (*right)->pt(); }); - - h.m_leadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[0]); - h.m_subleadingJet = dynamic_cast<const xAOD::Jet *>(*VRTrackjets[1]); - - // calc variables - h.m_fourVector = h.m_leadingJet->jetP4() + h.m_subleadingJet->jetP4(); - h.m_dRjets = ROOT::Math::VectorUtil::DeltaR(h.m_leadingJet->jetP4(), - h.m_subleadingJet->jetP4()); } // write to map - m_higgsVarsMap["boosted_m_h1_" + wp] = h1.m_fourVector.M(); - m_higgsVarsMap["boosted_m_h2_" + wp] = h2.m_fourVector.M(); - m_higgsVarsMap["boosted_m_hh_" + wp] = - (h1.m_fourVector + h2.m_fourVector).M(); - m_higgsVarsMap["boosted_dR_jets_in_h1_" + wp] = h1.m_dRjets; - m_higgsVarsMap["boosted_dR_jets_in_h2_" + wp] = h2.m_dRjets; + if (h1.m_doDecorate) + { + m_higgsVarsMap["boosted_m_h1_" + wp] = h1.m_fourVector.M(); + m_higgsVarsMap["boosted_dR_jets_in_h1_" + wp] = h1.m_dRjets; + } + if (h2.m_doDecorate) + { + m_higgsVarsMap["boosted_m_h2_" + wp] = h2.m_fourVector.M(); + m_higgsVarsMap["boosted_dR_jets_in_h2_" + wp] = h2.m_dRjets; + } + if (h1.m_doDecorate && h2.m_doDecorate) + { + m_higgsVarsMap["boosted_m_hh_" + wp] = + (h1.m_fourVector + h2.m_fourVector).M(); + } + // clang-format off + m_higgsVarsMap["boosted_h1_nGhostAssocVrJets_" + wp] = h1.m_nGhostAssocVrJets; + m_higgsVarsMap["boosted_h1_nBtaggedGhostAssocVrTrackJets_" + wp] = h1.m_nBtaggedGhostAssocVrJets; + m_higgsVarsMap["boosted_h2_nGhostAssocVrJets_" + wp] = h2.m_nGhostAssocVrJets; + m_higgsVarsMap["boosted_h2_nBtaggedGhostAssocVrTrackJets_" + wp] = h2.m_nBtaggedGhostAssocVrJets; + // clang-format on return; }; @@ -323,5 +359,4 @@ namespace HH4B { return m_higgsVarsMap; }; - }; diff --git a/HH4bAnalysis/src/DiHiggsAnalysis.h b/HH4bAnalysis/src/DiHiggsAnalysis.h index 55596aec4..8d21acdc4 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysis.h +++ b/HH4bAnalysis/src/DiHiggsAnalysis.h @@ -22,8 +22,15 @@ namespace HH4B ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float>> m_fourVector; // dR between leading and subleading jet float m_dRjets = -1; + // for boosted analysis const xAOD::Jet *m_largeRJet = nullptr; + // Nr of ghost associated Vr Jets + int m_nGhostAssocVrJets = -1; + // Nr of btagged ghost associated Vr Jets + int m_nBtaggedGhostAssocVrJets = -1; + // don't decorate if requirements are not met + bool m_doDecorate = true; }; class DiHiggsAnalysis @@ -37,7 +44,7 @@ public: // do boosted Analysis void makeBoostedAnalysis(const xAOD::JetContainer &largeRjets, std::string wp); - // returns h_cand_vars for other purposes + // returns m_higgsVarsMap for other purposes std::unordered_map<std::string, float> getHiggsVarsMap(); // map holding the final vars (like dict in python) // access/write like : m_diHiggs_vars[var]; diff --git a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx index 3ab13395e..2d87230a8 100644 --- a/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx +++ b/HH4bAnalysis/src/DiHiggsAnalysisAlg.cxx @@ -41,11 +41,6 @@ namespace HH4B StatusCode DiHiggsAnalysisAlg ::execute() { - // jump out if no analysis is selected - if (!m_doResolvedAnalysis or !m_doResolvedAnalysis) - { - return StatusCode::SUCCESS; - } ATH_MSG_DEBUG("Executing " << name()); // get the xAOD objects @@ -56,9 +51,6 @@ namespace HH4B ATH_CHECK(antiKt4RecoJets.isValid()); ATH_CHECK(antiKt10RecoJets.isValid()); - // TODO: make configurable with which btagging WP Higgs candidates are - // created - // create the analysis object DiHiggsAnalysis hh4b_analysis; // write defaults (-1) into the Higgs variable map -- GitLab From 6ed3d25b1572e88417e5b3e8535eff63ebcae9f9 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 25 Aug 2022 10:25:38 +0200 Subject: [PATCH 30/33] Update HH4bAnalysis/src/VariableDumperAlg.cxx --- HH4bAnalysis/src/VariableDumperAlg.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index 067117406..de1a0e8f1 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -51,7 +51,6 @@ namespace HH4B std::string sysname; ATH_CHECK(m_systematicsList.service().makeSystematicsName(sysname, "%SYS%", sys)); - ATH_MSG_VERBOSE("Will apply sysname \"" << sysname << "\" for event"); // get the xAOD objects @@ -65,8 +64,6 @@ namespace HH4B ATH_CHECK(m_muonHandle.retrieve(muons, sys)); const xAOD::JetContainer *antiKt4RecoJets(nullptr); ATH_CHECK(m_jetsmallRHandle.retrieve(antiKt4RecoJets, sys)); - const xAOD::JetContainer *antiKt10RecoJets(nullptr); - if (!m_jetlargeRHandle.empty()) { ATH_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); -- GitLab From 44c1f978218f48cdb6a092721645f3ab7e1693a8 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 25 Aug 2022 10:26:42 +0200 Subject: [PATCH 31/33] Deleted .asetup.save --- .asetup.save | 79 ---------------------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 .asetup.save diff --git a/.asetup.save b/.asetup.save deleted file mode 100644 index 530699c42..000000000 --- a/.asetup.save +++ /dev/null @@ -1,79 +0,0 @@ -#Release cmake - -export LANG="C" -export LC_ALL="C" -export COOL_ORA_ENABLE_ADAPTIVE_OPT="Y" -export ASETUP_PRINTLEVEL="0" -export BINARY_TAG="x86_64-centos7-gcc11-opt" -export CMTCONFIG="x86_64-centos7-gcc11-opt" -export ASETUP_SYSBIN=`mktemp -d /tmp/freder/.asetup-sysbin-XXXXXX_$$` -source $AtlasSetup/scripts/sys_exe-alias.sh '' -if [ -n "${MAKEFLAGS:+x}" ]; then - asetup_flags=`echo ${MAKEFLAGS} | \grep ' -l'` - if [ -z "${asetup_flags}" ]; then - export MAKEFLAGS="${MAKEFLAGS} -l32" - fi -else - export MAKEFLAGS="-j32 -l32" -fi -source /cvmfs/sft.cern.ch/lcg/releases/gcc/11.2.0-8a51a/x86_64-centos7/setup.sh -export CC=`\env which gcc 2>/dev/null` -[[ -z $CC ]] && unset CC -export CXX=`\env which g++ 2>/dev/null` -[[ -z $CXX ]] && unset CXX -export FC=`\env which gfortran 2>/dev/null` -[[ -z $FC ]] && unset FC -export CMAKE_NO_VERBOSE="1" -type lsetup >/dev/null 2>/dev/null -if [ $? -ne 0 ]; then - source ${ATLAS_LOCAL_ROOT_BASE}/user/atlasLocalSetup.sh --quiet -fi -source $ATLAS_LOCAL_ROOT_BASE/packageSetups/localSetup.sh --quiet "cmake 3.21.3" -if [ -z "${AtlasSetup:+x}" ]; then - export AtlasSetup="/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/AtlasSetup/V02-00-44/AtlasSetup" - export AtlasSetupVersion="AtlasSetup-02-00-44" -fi -export FRONTIER_LOG_LEVEL="warning" -export ATLAS_POOLCOND_PATH="/cvmfs/atlas-condb.cern.ch/repo/conditions" -export ATLAS_DB_AREA="/cvmfs/atlas.cern.ch/repo/sw/database" -export DBRELEASE_OVERRIDE="current" -export AtlasBaseDir="/cvmfs/atlas.cern.ch/repo/sw/software/22.2" -export LCG_RELEASE_BASE="/cvmfs/atlas.cern.ch/repo/sw/software/22.2/sw/lcg/releases" -export AtlasBuildStamp="2022-07-29T0001" -export AtlasReleaseType="stable" -export AtlasBuildBranch="22.2" -export AtlasProject="AthAnalysis" -export TDAQ_RELEASE_BASE="/cvmfs/atlas.cern.ch/repo/sw/tdaq/offline" -export ATLAS_RELEASE_BASE="/cvmfs/atlas.cern.ch/repo/sw/software/22.2" -export AtlasArea="/cvmfs/atlas.cern.ch/repo/sw/software/22.2/AthAnalysis/22.2.84" -export AtlasVersion="22.2.84" -source /cvmfs/atlas.cern.ch/repo/sw/software/22.2/AthAnalysis/22.2.84/InstallArea/x86_64-centos7-gcc11-opt/setup.sh -asetup_status=$? -if [ ${asetup_status} -ne 0 ]; then - \echo "AtlasSetup(ERROR): sourcing release setup script (/cvmfs/atlas.cern.ch/repo/sw/software/22.2/AthAnalysis/22.2.84/InstallArea/x86_64-centos7-gcc11-opt/setup.sh) failed" -fi -export TestArea="/lustre/fs22/group/atlas/freder/hh/hh4b-analysis" -alias_sys_exe emacs -echo $LD_LIBRARY_PATH | egrep "LCG_[^/:]*/curl/" >/dev/null -if [ $? -eq 0 ]; then - alias_sys_exe_envU git -fi -\expr 1 \* 1 + 1 >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo -e '\nMaking workaround-alias for expr on this *OLD* machine'; alias_sys_exe expr -fi -export PATH="${ASETUP_SYSBIN}:${PATH}" - -#Release Summary as follows: -#Release base=/cvmfs/atlas.cern.ch/repo/sw/software/22.2 -#Release project=AthAnalysis -#Release releaseNum=22.2.84 -#Release asconfig=x86_64-centos7-gcc11-opt - -# Execute user-specified epilog - -source /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/swConfig/asetup/asetupEpilog.sh -script_status=$? -if [ ${script_status} -ne 0 ]; then - \echo "AtlasSetup(ERROR): User-specified epilog (source /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/swConfig/asetup/asetupEpilog.sh) reported failure (error ${script_status})" -fi -- GitLab From b75942c65b15f12bb77d71de55c57c7f5d979a20 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 25 Aug 2022 10:30:56 +0200 Subject: [PATCH 32/33] fix pipeline --- HH4bAnalysis/src/VariableDumperAlg.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/HH4bAnalysis/src/VariableDumperAlg.cxx b/HH4bAnalysis/src/VariableDumperAlg.cxx index de1a0e8f1..6297167c6 100644 --- a/HH4bAnalysis/src/VariableDumperAlg.cxx +++ b/HH4bAnalysis/src/VariableDumperAlg.cxx @@ -64,6 +64,7 @@ namespace HH4B ATH_CHECK(m_muonHandle.retrieve(muons, sys)); const xAOD::JetContainer *antiKt4RecoJets(nullptr); ATH_CHECK(m_jetsmallRHandle.retrieve(antiKt4RecoJets, sys)); + const xAOD::JetContainer *antiKt10RecoJets(nullptr); if (!m_jetlargeRHandle.empty()) { ATH_CHECK(m_jetlargeRHandle.retrieve(antiKt10RecoJets, sys)); -- GitLab From 4c2f1ddc004ef79104cb9f70842b4766ce18c471 Mon Sep 17 00:00:00 2001 From: Frederic Renner <frederic.renner@cern.ch> Date: Thu, 25 Aug 2022 12:32:22 +0200 Subject: [PATCH 33/33] put analaysis config onto ConfigFlags --- HH4bAnalysis/python/Algs/DiHiggsAnalysis.py | 18 ++++++------------ .../python/Config/AnalysisAlgsConfig.py | 3 +-- HH4bAnalysis/python/Config/MiniTupleConfig.py | 2 +- HH4bAnalysis/share/VariableDumperConfig.py | 19 +++++++++++++++++-- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py index f99f1824f..32c38b549 100644 --- a/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py +++ b/HH4bAnalysis/python/Algs/DiHiggsAnalysis.py @@ -3,10 +3,9 @@ from AthenaConfiguration.ComponentFactory import CompFactory def DiHiggsAnalysisAlgCfg( + flags, SmallJetKey, LargeJetKey, - doResolvedAnalysis, - doBoostedAnalysis, btag_wps, vr_btag_wps, ): @@ -17,22 +16,17 @@ def DiHiggsAnalysisAlgCfg( EventInfoKey="EventInfo", SmallJetKey=SmallJetKey, LargeJetKey=LargeJetKey, - doResolvedAnalysis=doResolvedAnalysis, - doBoostedAnalysis=doBoostedAnalysis, + doResolvedAnalysis=flags.do_resolved_analysis, + doBoostedAnalysis=flags.do_boosted_analysis, btag_wps=btag_wps, vr_btag_wps=vr_btag_wps, ) ) - # make them global to use them in the tree config - global globDoResolvedAnalysis - globDoResolvedAnalysis = doResolvedAnalysis - global globDoBoostedAnalysis - globDoBoostedAnalysis = doBoostedAnalysis return cfg -def DiHiggsAnalysisAddBranches(working_points): +def DiHiggsAnalysisAddBranches(flags, working_points): analysisTreeBranches = [] vars = [ "m_h1", @@ -42,13 +36,13 @@ def DiHiggsAnalysisAddBranches(working_points): "dR_jets_in_h2", ] - if globDoResolvedAnalysis: + if flags.do_resolved_analysis: for btag_wp in working_points["ak4"]: for var in vars: analysisTreeBranches += [ f"EventInfo.resolved_{var}_{btag_wp} -> resolved_{btag_wp}_{var}" ] - if globDoBoostedAnalysis: + if flags.do_boosted_analysis: vars += [ "h1_nGhostAssocVrJets", "h1_nBtaggedGhostAssocVrTrackJets", diff --git a/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py b/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py index d9c3ef979..1f2d2bc4e 100644 --- a/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py +++ b/HH4bAnalysis/python/Config/AnalysisAlgsConfig.py @@ -193,12 +193,11 @@ def AnalysisAlgsCfg( if do_dihiggs_analysis: cfg.merge( DiHiggsAnalysisAlgCfg( + flags, SmallJetKey=containers["outputs"]["reco4Jet"].replace("%SYS%", "NOSYS"), LargeJetKey=containers["outputs"]["reco10Jet"].replace( "%SYS%", "NOSYS" ), - doResolvedAnalysis=True, - doBoostedAnalysis=True, btag_wps=btag_wps, vr_btag_wps=vr_btag_wps, ) diff --git a/HH4bAnalysis/python/Config/MiniTupleConfig.py b/HH4bAnalysis/python/Config/MiniTupleConfig.py index f7db7866d..608cc6f58 100644 --- a/HH4bAnalysis/python/Config/MiniTupleConfig.py +++ b/HH4bAnalysis/python/Config/MiniTupleConfig.py @@ -113,7 +113,7 @@ def MiniTupleCfg( ] if do_dihiggs_analysis: - analysisTreeBranches += DiHiggsAnalysisAddBranches(working_points) + analysisTreeBranches += DiHiggsAnalysisAddBranches(flags, working_points) log.info("Add tree seq") cfg.merge(AnalysisTreeAlgCfg(flags, branches=analysisTreeBranches)) diff --git a/HH4bAnalysis/share/VariableDumperConfig.py b/HH4bAnalysis/share/VariableDumperConfig.py index 69478dbe3..63228893f 100755 --- a/HH4bAnalysis/share/VariableDumperConfig.py +++ b/HH4bAnalysis/share/VariableDumperConfig.py @@ -1,7 +1,7 @@ #!/bin/env python # -# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration # # @@ -78,8 +78,21 @@ def defineArgs(ConfigFlags): parser.add_argument( "--do_dihiggs_analysis", action="store_true", - help="use loose event cleaning (to get something to pass)", + help="run DiHiggs anaylysis", + ) + parser.add_argument( + "--do_resolved_analysis", + action="store_true", + default=True, + help="activate resolved analysis", ) + parser.add_argument( + "--do_boosted_analysis", + action="store_true", + default=True, + help="activate boosted", + ) + return parser @@ -126,6 +139,8 @@ def main(): fileMD = GetFileMD(ConfigFlags.Input.Files[0]) ConfigFlags.addFlag("Input.AMITag", fileMD.get("AMITag", "")) + ConfigFlags.addFlag("do_resolved_analysis", args.do_resolved_analysis) + ConfigFlags.addFlag("do_boosted_analysis", args.do_boosted_analysis) ConfigFlags.lock() -- GitLab