ATLAS Offline Software
Loading...
Searching...
No Matches
DileptonOSSFInvariantMassWindowSelectorAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7
9
10using ROOT::Math::PtEtaPhiEVector;
11
12namespace CP {
13
29
30 // Compute invariant mass of two reco leptons
31 template <typename T>
32 static float mll_reco(const T* lep0, const T* lep1) {
33 return (lep0->p4() + lep1->p4()).M();
34 }
35
36 // Compute invariant mass of two truth particles, optionally using dressed kinematics
37 static float mll_truth(const xAOD::TruthParticle* lep0,
38 const xAOD::TruthParticle* lep1,
39 bool useDressed) {
40 if (!useDressed)
41 return (lep0->p4() + lep1->p4()).M();
42
43 static const SG::ConstAccessor<float> acc_pt ("pt_dressed");
44 static const SG::ConstAccessor<float> acc_eta("eta_dressed");
45 static const SG::ConstAccessor<float> acc_phi("phi_dressed");
46 static const SG::ConstAccessor<float> acc_e ("e_dressed");
47
48 PtEtaPhiEVector v0, v1;
49 v0.SetCoordinates(acc_pt(*lep0), acc_eta(*lep0), acc_phi(*lep0), acc_e(*lep0));
50 v1.SetCoordinates(acc_pt(*lep1), acc_eta(*lep1), acc_phi(*lep1), acc_e(*lep1));
51 return (v0 + v1).M();
52 }
53
54 // Check whether mll falls inside the window
56 return mll > m_mll_lower && mll < m_mll_upper;
57 }
58
60
61 for (const auto &sys : m_systematicsList.systematicsVector()) {
62
63 const xAOD::EventInfo *evtInfo = nullptr;
64 ANA_CHECK(m_eventInfoHandle.retrieve(evtInfo, sys));
65
66 m_decoration.setBool(*evtInfo, false, sys);
67
68 if (m_preselection && !m_preselection.getBool(*evtInfo, sys))
69 continue;
70
71 bool decision = false;
72
73 if (m_electronsHandle && !decision) {
74 const xAOD::ElectronContainer *electrons = nullptr;
75 ANA_CHECK(m_electronsHandle.retrieve(electrons, sys));
76 for (size_t i = 0; i < electrons->size() && !decision; ++i) {
77 const xAOD::Electron* e0 = (*electrons)[i];
78 if (m_electronSelection && !m_electronSelection.getBool(*e0, sys)) continue;
79 for (size_t j = i + 1; j < electrons->size() && !decision; ++j) {
80 const xAOD::Electron* e1 = (*electrons)[j];
81 if (m_electronSelection && !m_electronSelection.getBool(*e1, sys)) continue;
82 if (e0->charge() == e1->charge()) continue;
83 decision = inWindow(mll_reco(e0, e1));
84 }
85 }
86 }
87
88 if (m_muonsHandle && !decision) {
89 const xAOD::MuonContainer *muons = nullptr;
90 ANA_CHECK(m_muonsHandle.retrieve(muons, sys));
91 for (size_t i = 0; i < muons->size() && !decision; ++i) {
92 const xAOD::Muon* m0 = (*muons)[i];
93 if (m_muonSelection && !m_muonSelection.getBool(*m0, sys)) continue;
94 for (size_t j = i + 1; j < muons->size() && !decision; ++j) {
95 const xAOD::Muon* m1 = (*muons)[j];
96 if (m_muonSelection && !m_muonSelection.getBool(*m1, sys)) continue;
97 if (m0->charge() == m1->charge()) continue;
98 decision = inWindow(mll_reco(m0, m1));
99 }
100 }
101 }
102
103 if (m_electronsTruthHandle && !decision) {
104 const xAOD::TruthParticleContainer *truthElectrons = nullptr;
105 ANA_CHECK(m_electronsTruthHandle.retrieve(truthElectrons, sys));
106 for (size_t i = 0; i < truthElectrons->size() && !decision; ++i) {
107 const xAOD::TruthParticle* e0 = (*truthElectrons)[i];
108 if (m_electronTruthSelection && !m_electronTruthSelection.getBool(*e0, sys)) continue;
109 for (size_t j = i + 1; j < truthElectrons->size() && !decision; ++j) {
110 const xAOD::TruthParticle* e1 = (*truthElectrons)[j];
111 if (m_electronTruthSelection && !m_electronTruthSelection.getBool(*e1, sys)) continue;
112 if (e0->charge() == e1->charge()) continue;
113 decision = inWindow(mll_truth(e0, e1, m_useDressedProperties));
114 }
115 }
116 }
117
118 if (m_muonsTruthHandle && !decision) {
119 const xAOD::TruthParticleContainer *truthMuons = nullptr;
120 ANA_CHECK(m_muonsTruthHandle.retrieve(truthMuons, sys));
121 for (size_t i = 0; i < truthMuons->size() && !decision; ++i) {
122 const xAOD::TruthParticle* m0 = (*truthMuons)[i];
123 if (m_muonTruthSelection && !m_muonTruthSelection.getBool(*m0, sys)) continue;
124 for (size_t j = i + 1; j < truthMuons->size() && !decision; ++j) {
125 const xAOD::TruthParticle* m1 = (*truthMuons)[j];
126 if (m_muonTruthSelection && !m_muonTruthSelection.getBool(*m1, sys)) continue;
127 if (m0->charge() == m1->charge()) continue;
128 decision = inWindow(mll_truth(m0, m1, m_useDressedProperties));
129 }
130 }
131 }
132
133 if (m_veto) decision = !decision;
134 m_decoration.setBool(*evtInfo, decision, sys);
135 }
136
137 return StatusCode::SUCCESS;
138 }
139
140} // namespace CP
#define ANA_CHECK(EXP)
check whether the given expression was successful
CP::SysReadHandle< xAOD::TruthParticleContainer > m_electronsTruthHandle
Gaudi::Property< bool > m_veto
whether to veto events instead of selecting them
Gaudi::Property< bool > m_useDressedProperties
use dressed kinematics
CP::SysReadHandle< xAOD::TruthParticleContainer > m_muonsTruthHandle
size_type size() const noexcept
Returns the number of elements in the collection.
Helper class to provide constant type-safe access to aux data.
float charge() const
double charge() const
Physical charge.
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
Select isolated Photons, Electrons and Muons.
static float mll_reco(const T *lep0, const T *lep1)
static float mll_truth(const xAOD::TruthParticle *lep0, const xAOD::TruthParticle *lep1, bool useDressed)
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
TruthParticle_v1 TruthParticle
Typedef to implementation.
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
Electron_v1 Electron
Definition of the current "egamma version".