ATLAS Offline Software
EGInvariantMassTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // EGInvariantMassTool.cxx
7 // Author: Giovanni Marchiori (giovanni.marchiori@cern.ch)
9 
11 #include "xAODEgamma/Electron.h"
12 #include "xAODMuon/Muon.h"
13 #include <cmath>
14 using std::abs;
15 using std::sqrt;
16 
17 #include "TLorentzVector.h"
18 
19 namespace DerivationFramework {
20 
23 {
24  if (m_sgName.key().empty()) {
25  ATH_MSG_ERROR("No SG name provided for the output of EGInvariantMassTool!");
26  return StatusCode::FAILURE;
27  }
29 
30  if (!m_container1Name.key().empty()) {
31  ATH_CHECK(m_container1Name.initialize());
32  }
33  if (!m_container2Name.key().empty()) {
34  ATH_CHECK(m_container2Name.initialize());
35  }
36  if (!m_pt1BranchName.key().empty()) {
38  }
39  if (!m_eta1BranchName.key().empty()) {
41  }
42  if (!m_phi1BranchName.key().empty()) {
44  }
45  if (!m_pt2BranchName.key().empty()) {
47  }
48  if (!m_eta2BranchName.key().empty()) {
50  }
51  if (!m_phi2BranchName.key().empty()) {
53  }
54 
55  ATH_CHECK(initializeParser({ m_expression1, m_expression2 }));
56 
57  return StatusCode::SUCCESS;
58 }
59 
61 EGInvariantMassTool::addBranches(const EventContext& ctx) const
62 {
63 
64  SG::WriteHandle<std::vector<float>> writeHandle{ m_sgName, ctx };
65 
66  // create the vector which will hold the values invariant masses
67  auto masses = std::make_unique<std::vector<float>>();
68  // compute the invariant mass values
70 
71  ATH_CHECK(writeHandle.record(std::move(masses)));
72 
73  return StatusCode::SUCCESS;
74 }
75 
78  std::vector<float>& masses) const
79 {
80  // Get optional payload
81  const std::vector<float>* pt1 = nullptr;
82  if (!m_pt1BranchName.key().empty()) {
84  pt1 = readHandle.ptr();
85  }
86  const std::vector<float>* pt2 = nullptr;
87  if (!m_pt2BranchName.key().empty()) {
89  pt2 = readHandle.ptr();
90  }
91 
92  const std::vector<float>* eta1 = nullptr;
93  if (!m_eta1BranchName.key().empty()) {
95  eta1 = readHandle.ptr();
96  }
97  const std::vector<float>* eta2 = nullptr;
98  if (!m_eta2BranchName.key().empty()) {
100  eta2 = readHandle.ptr();
101  }
102 
103  const std::vector<float>* phi1 = nullptr;
104  if (!m_phi1BranchName.key().empty()) {
106  phi1 = readHandle.ptr();
107  }
108  const std::vector<float>* phi2 = nullptr;
109  if (!m_phi2BranchName.key().empty()) {
111  phi2 = readHandle.ptr();
112  }
113  // Get the input particles
115  ctx };
117  ctx };
118  const xAOD::IParticleContainer* particles1 = inputParticles1.ptr();
119  const xAOD::IParticleContainer* particles2 = inputParticles2.ptr();
120 
121  // get the positions of the elements which pass the requirement
122  std::vector<int> entries1 = m_parser[kParser1]->evaluateAsVector();
123  unsigned int nEntries1 = entries1.size();
124  std::vector<int> entries2 = m_parser[kParser2]->evaluateAsVector();
125  unsigned int nEntries2 = entries2.size();
126 
127  // if there are no particles in one of the two lists to combine,
128  // just leave the function
129  if (nEntries1 == 0 || nEntries2 == 0) {
130  return StatusCode::SUCCESS;
131  }
132 
133  // check the sizes are compatible
134  if (particles1->size() != nEntries1) {
135  ATH_MSG_ERROR("Branch sizes incompatible - returning zero");
136  return StatusCode::FAILURE;
137  }
138  if (particles2->size() != nEntries2) {
139  ATH_MSG_ERROR("Branch sizes incompatible - returning zero");
140  return StatusCode::FAILURE;
141  }
142  if ((pt1 && pt1->size() != nEntries1) ||
143  ((!m_doTransverseMass || (m_mindR > 0.0)) && eta1 &&
144  eta1->size() != nEntries1) ||
145  (phi1 && phi1->size() != nEntries1)) {
146  ATH_MSG_ERROR("Branch sizes incompatible - returning zero");
147  return StatusCode::FAILURE;
148  }
149  if ((pt2 && pt2->size() != nEntries2) ||
150  ((!m_doTransverseMass || (m_mindR > 0.0)) && eta2 &&
151  eta2->size() != nEntries2) ||
152  (phi2 && phi2->size() != nEntries2)) {
153  ATH_MSG_ERROR("Branch sizes incompatible - returning zero");
154  return StatusCode::FAILURE;
155  }
156 
157  // Double loop to get the pairs for which the mass should be calculated
158  unsigned int outerIt, innerIt;
159  std::vector<std::vector<int>> pairs;
160  for (outerIt = 0; outerIt < nEntries1; ++outerIt) {
161  for (innerIt = 0; innerIt < nEntries2; ++innerIt) {
162  std::vector<int> tmpPair;
163  if (entries1[outerIt] == 1 && entries2[innerIt] == 1) {
164  tmpPair.push_back(outerIt);
165  tmpPair.push_back(innerIt);
166  pairs.push_back(tmpPair);
167  }
168  }
169  }
170 
171  // since IParticle interface does not provide charge() method
172  // we need to identify the particle type in case we want to check
173  // its charge (through a type cast)
174  xAOD::Type::ObjectType type1 = xAOD::Type::Other;
175  xAOD::Type::ObjectType type2 = xAOD::Type::Other;
176  if (m_checkCharge) {
177  type1 = ((*particles1)[0])->type();
178  type2 = ((*particles2)[0])->type();
179  if ((type1 != xAOD::Type::Electron && type1 != xAOD::Type::Muon) ||
180  (type2 != xAOD::Type::Electron && type2 != xAOD::Type::Muon)) {
182  "Cannot check charge for particles not of type electron or muon");
183  return StatusCode::FAILURE;
184  }
185  }
186 
187  for (const auto& pair : pairs) {
188  unsigned int first = pair[0];
189  unsigned int second = pair[1];
190  float apt1 = pt1 ? (*pt1)[first] : ((*particles1)[first])->p4().Pt();
191  float apt2 = pt2 ? (*pt2)[second] : ((*particles2)[second])->p4().Pt();
192  float aeta1(-999.), aeta2(-999.);
193  if (!m_doTransverseMass || (m_mindR > 0.0)) {
194  aeta1 = eta1 ? (*eta1)[first] : ((*particles1)[first])->p4().Eta();
195  aeta2 = eta2 ? (*eta2)[second] : ((*particles2)[second])->p4().Eta();
196  }
197  float aphi1 = phi1 ? (*phi1)[first] : ((*particles1)[first])->p4().Phi();
198  float aphi2 = phi2 ? (*phi2)[second] : ((*particles2)[second])->p4().Phi();
199 
200  if (m_mindR > 0.0) {
201  float deta = aeta1 - aeta2;
202  float dphi = abs(aphi1 - aphi2);
203  if (dphi > TMath::Pi()) {
204  dphi = TMath::TwoPi() - dphi;
205  }
206  if (sqrt(deta * deta + dphi * dphi) < m_mindR) {
207  continue;
208  }
209  }
210 
211  if (m_checkCharge) {
212  float q1(0.), q2(0.);
213  if (type1 == xAOD::Type::Electron) {
214  q1 = ((xAOD::Electron*)((*particles1)[first]))->charge();
215  } else if (type1 == xAOD::Type::Muon) {
216  q1 = ((xAOD::Muon*)((*particles1)[first]))
217  ->primaryTrackParticle()
218  ->charge();
219  }
220  if (type2 == xAOD::Type::Electron) {
221  q2 = ((xAOD::Electron*)((*particles2)[second]))->charge();
222  } else if (type2 == xAOD::Type::Muon) {
223  q2 = ((xAOD::Muon*)((*particles2)[second]))
224  ->primaryTrackParticle()
225  ->charge();
226  }
227  if (q1 * q2 > 0.) {
228  continue;
229  }
230  }
231  TLorentzVector v1, v2, v;
232  if (m_doTransverseMass) {
233  v1.SetPtEtaPhiM(apt1, 0., aphi1, m_mass1Hypothesis);
234  v2.SetPtEtaPhiM(apt2, 0., aphi2, m_mass2Hypothesis);
235  } else {
236  v1.SetPtEtaPhiM(apt1, aeta1, aphi1, m_mass1Hypothesis);
237  v2.SetPtEtaPhiM(apt2, aeta2, aphi2, m_mass2Hypothesis);
238  }
239  float mass = (v1 + v2).M();
240  masses.push_back(mass);
241  }
242  return StatusCode::SUCCESS;
243 }
244 } // end namespace DerivationFramework
DerivationFramework::EGInvariantMassTool::m_phi1BranchName
SG::ReadHandleKey< std::vector< float > > m_phi1BranchName
Definition: EGInvariantMassTool.h:78
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
ParticleGun_SamplingFraction.eta2
eta2
Definition: ParticleGun_SamplingFraction.py:96
DerivationFramework::EGInvariantMassTool::m_container2Name
SG::ReadHandleKey< xAOD::IParticleContainer > m_container2Name
Definition: EGInvariantMassTool.h:57
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
ObjectType
ObjectType
Definition: BaseObject.h:11
Muon.h
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
DerivationFramework::kParser2
@ kParser2
Definition: EGInvariantMassTool.h:28
DerivationFramework::EGInvariantMassTool::m_checkCharge
Gaudi::Property< bool > m_checkCharge
Definition: EGInvariantMassTool.h:109
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
xAOD::eta1
setEt setPhi setE277 setWeta2 eta1
Definition: TrigEMCluster_v1.cxx:41
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
DerivationFramework::EGInvariantMassTool::m_mass2Hypothesis
Gaudi::Property< float > m_mass2Hypothesis
Definition: EGInvariantMassTool.h:107
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
DerivationFramework::kParser1
@ kParser1
Definition: EGInvariantMassTool.h:27
python.CreateTierZeroArgdict.pairs
pairs
Definition: CreateTierZeroArgdict.py:201
DerivationFramework::EGInvariantMassTool::getInvariantMasses
StatusCode getInvariantMasses(const EventContext &ctx, std::vector< float > &) const
Definition: EGInvariantMassTool.cxx:77
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
DerivationFramework::EGInvariantMassTool::initialize
virtual StatusCode initialize() override final
Definition: EGInvariantMassTool.cxx:22
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
DerivationFramework
THE reconstruction tool.
Definition: ParticleSortingAlg.h:24
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
DataVector
Derived DataVector<T>.
Definition: DataVector.h:795
DerivationFramework::EGInvariantMassTool::m_expression1
Gaudi::Property< std::string > m_expression1
Definition: EGInvariantMassTool.h:44
DerivationFramework::EGInvariantMassTool::m_doTransverseMass
Gaudi::Property< bool > m_doTransverseMass
Definition: EGInvariantMassTool.h:110
EGInvariantMassTool.h
DerivationFramework::EGInvariantMassTool::m_mass1Hypothesis
Gaudi::Property< float > m_mass1Hypothesis
Definition: EGInvariantMassTool.h:106
DerivationFramework::EGInvariantMassTool::m_pt2BranchName
SG::ReadHandleKey< std::vector< float > > m_pt2BranchName
Definition: EGInvariantMassTool.h:85
DerivationFramework::EGInvariantMassTool::addBranches
virtual StatusCode addBranches(const EventContext &ctx) const override final
Definition: EGInvariantMassTool.cxx:61
DerivationFramework::EGInvariantMassTool::m_phi2BranchName
SG::ReadHandleKey< std::vector< float > > m_phi2BranchName
Definition: EGInvariantMassTool.h:99
xAOD::Electron_v1
Definition: Electron_v1.h:34
Muon
struct TBPatternUnitContext Muon
ReadCellNoiseFromCoolCompare.v2
v2
Definition: ReadCellNoiseFromCoolCompare.py:364
python.PyAthena.v
v
Definition: PyAthena.py:154
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
DerivationFramework::EGInvariantMassTool::m_pt1BranchName
SG::ReadHandleKey< std::vector< float > > m_pt1BranchName
Definition: EGInvariantMassTool.h:64
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DerivationFramework::EGInvariantMassTool::m_container1Name
SG::ReadHandleKey< xAOD::IParticleContainer > m_container1Name
Definition: EGInvariantMassTool.h:51
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Electron.h
DerivationFramework::EGInvariantMassTool::m_expression2
Gaudi::Property< std::string > m_expression2
Definition: EGInvariantMassTool.h:45
DerivationFramework::EGInvariantMassTool::m_eta1BranchName
SG::ReadHandleKey< std::vector< float > > m_eta1BranchName
Definition: EGInvariantMassTool.h:71
DerivationFramework::EGInvariantMassTool::m_mindR
Gaudi::Property< float > m_mindR
Definition: EGInvariantMassTool.h:108
DerivationFramework::EGInvariantMassTool::m_eta2BranchName
SG::ReadHandleKey< std::vector< float > > m_eta2BranchName
Definition: EGInvariantMassTool.h:92
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
DerivationFramework::EGInvariantMassTool::m_sgName
SG::WriteHandleKey< std::vector< float > > m_sgName
Definition: EGInvariantMassTool.h:46
SUSY_SimplifiedModel_PreInclude.masses
dictionary masses
Definition: SUSY_SimplifiedModel_PreInclude.py:7