ATLAS Offline Software
Loading...
Searching...
No Matches
METMuonAssociator.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6
7// METMuonAssociator.cxx
8// Implementation file for class METMuonAssociator
9//
10// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
11//
12// Author: P Loch, S Resconi, TJ Khoo, AS Mete
14
15// METReconstruction includes
18
19// Muon EDM
21
22// Tracking EDM
23#include "xAODTracking/Vertex.h"
24
25// DeltaR calculation
27
28
31
32namespace met {
33
34 using namespace xAOD;
35
36 //accessor for PV
37 const static SG::ConstAccessor<char> PVMatchedAcc("matchedToPV");
38
39 // Constructors
44 {
45 }
46
47 // Athena algtool's Hooks
50 {
52 ATH_MSG_VERBOSE ("Initializing " << name() << "...");
53 ATH_CHECK( m_muContKey.initialize());
54 if (m_useFELinks) {
59 }
60
62
63 return StatusCode::SUCCESS;
64 }
65
66 // executeTool
69 {
70 ATH_MSG_VERBOSE ("In execute: " << name() << "...");
71
73 if (!muonCont.isValid()) {
74 ATH_MSG_WARNING("Unable to retrieve input muon container " << m_muContKey.key());
75 return StatusCode::FAILURE;
76 }
77
78 ATH_MSG_DEBUG("Successfully retrieved muon collection");
79 if (fillAssocMap(metMap,muonCont.cptr()).isFailure()) {
80 ATH_MSG_WARNING("Unable to fill map with muon container " << m_muContKey.key());
81 return StatusCode::FAILURE;
82 }
83 return StatusCode::SUCCESS;
84 }
85
86 // *********************************************************************************************************
87 // Get constituents
89 std::vector<const xAOD::IParticle*>& tclist,
90 const met::METAssociator::ConstitHolder& /*constits*/) const
91 {
92 const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
93 const CaloCluster* muclus = mu->cluster();
94 if(muclus && m_doMuonClusterMatch) {
95 ATH_MSG_VERBOSE("Muon " << mu->index() << " with pt " << mu->pt()
96 << ", eta " << mu->eta()
97 << ", phi " << mu->phi()
98 << " has cluster with "
99 << "eta " << muclus->calEta()
100 << ", phi " << muclus->calPhi()
101 << ", E " << muclus->calE()
102 << " formed of " << muclus->size() << " cells.");
103 ATH_MSG_VERBOSE("Muon Eloss type: " << mu->energyLossType()
104 << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
105 << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
106 << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
107
109 for(const auto& matchel : tcLinkAcc(*muclus)) {
110 if(!matchel.isValid()) {continue;} // In case of thinned cluster collection
111 ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
112 if((*matchel)->e()>1e-9) { // +ve E
113 tclist.push_back(*matchel);
114 }
115 }
116 } // muon has linked cluster
117
118 return StatusCode::SUCCESS;
119 }
120
122 std::vector<const xAOD::IParticle*>& constlist,
123 const met::METAssociator::ConstitHolder& constits) const
124 {
125 const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
126 const TrackParticle* idtrack = mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
127 if(idtrack && acceptTrack(idtrack,constits.pv) && isGoodEoverP(idtrack)) {
128 // if(idtrack && acceptTrack(idtrack,pv)) {
129 ATH_MSG_VERBOSE("Accept muon track " << idtrack << " px, py = " << idtrack->p4().Px() << ", " << idtrack->p4().Py());
130 ATH_MSG_VERBOSE("Muon ID track ptr: " << idtrack);
131 constlist.push_back(idtrack);
132 // if(mu->pt()>10e3 && (mu->muonType()==xAOD::Muon::Combined || mu->muonType()==xAOD::Muon::SegmentTagged)) {
133 // mutracks.push_back(idtrack);
134 // }
135 }
136 return StatusCode::SUCCESS;
137 }
138
139 // *********************************************************************************************************
140 // Get constituents
142 std::vector<const xAOD::IParticle*>& pfolist,
143 const met::METAssociator::ConstitHolder& constits,
144 std::map<const IParticle*,MissingETBase::Types::constvec_t>& /*momenta*/) const
145 {
146 const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
147 const TrackParticle* idtrack = mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
148 const CaloCluster* muclus = mu->cluster();
149
150 ATH_MSG_VERBOSE("Muon " << mu->index() << " with pt " << mu->pt()
151 << ", eta " << mu->eta()
152 << ", phi " << mu->phi());
153 if(muclus) {
154 ATH_MSG_VERBOSE(" has cluster with "
155 << "eta " << muclus->calEta()
156 << ", phi " << muclus->calPhi()
157 << ", E " << muclus->calE()
158 << " formed of " << muclus->size() << " cells.");
159 }
160 ATH_MSG_VERBOSE("Muon Eloss type: " << mu->energyLossType()
161 << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
162 << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
163 << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
164
165 // One loop over PFOs
166 for(const auto *const pfo : *constits.pfoCont) {
167 if(pfo->isCharged()) {
168 // get charged PFOs by matching the muon ID track
169 // We set a small -ve pt for cPFOs that were rejected
170 // by the ChargedHadronSubtractionTool
171 const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
172 if(idtrack && pfo->track(0) == idtrack && PVMatchedAcc(*pfo) &&
173 ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) )
174 ) {
175 ATH_MSG_VERBOSE("Accept muon PFO " << pfo << " px, py = " << pfo->p4().Px() << ", " << pfo->p4().Py());
176 ATH_MSG_VERBOSE("Muon PFO index: " << pfo->index() << ", pt: " << pfo->pt() << ", eta: " << pfo->eta() << ", phi: " << pfo->phi() );
177 ATH_MSG_VERBOSE("Muon ID Track index: " << idtrack->index() << ", pt: " << idtrack->pt() << ", eta: " << idtrack->eta() << ", phi: " << idtrack->phi() );
178 pfolist.push_back(pfo);
179 break;
180 } // track match
181 } else {
182 // get neutral PFOs by matching the muon cluster
183 if(muclus && m_doMuonClusterMatch) {
184
186 for(const auto& matchel : tcLinkAcc(*muclus)) {
187 if(!matchel.isValid()) {
188 ATH_MSG_DEBUG("Invalid muon-cluster elementLink");
189 } else {
190 if((*matchel)->e()>FLT_MIN && pfo->cluster(0) == *matchel) { // +ve E && matches cluster
191 ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
192 pfolist.push_back(pfo);
193 }
194 }
195 }
196 } // muon has linked cluster
197 }
198 } // end of cluster loop
199
200 return StatusCode::SUCCESS;
201 }
202
203
205 std::vector<const xAOD::IParticle*>& felist,
206 const met::METAssociator::ConstitHolder& constits,
207 std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
208 {
209 const xAOD::Muon *mu = static_cast<const xAOD::Muon*>(obj);
210 if (m_useFELinks)
211 ATH_CHECK( extractFEsFromLinks(mu, felist,constits) );
212 else
213 ATH_CHECK( extractFEs(mu, felist, constits) );
214
215 return StatusCode::SUCCESS;
216 }
217
218 StatusCode METMuonAssociator::extractFEsFromLinks(const xAOD::Muon* mu, //TODO to be tested
219 std::vector<const xAOD::IParticle*>& felist,
220 const met::METAssociator::ConstitHolder& constits) const
221 {
222 ATH_MSG_DEBUG("Extract FEs From Links for " << mu->type() << " with pT " << mu->pt());
223
224 std::vector<FELink_t> nFELinks;
225 std::vector<FELink_t> cFELinks;
226
229 nFELinks=neutralFEReadDecorHandle(*mu);
230 cFELinks=chargedFEReadDecorHandle(*mu);
231
232 // Charged FEs
233 for (const FELink_t& feLink : cFELinks) {
234 if (!feLink.isValid()) continue;
235 const xAOD::FlowElement* fe_init = *feLink;
236 for (const auto *const fe : *constits.feCont){
237 if (fe->index() == fe_init->index() && fe->isCharged()){ //index-based match between JetETmiss and CHSFlowElements collections
238 const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
239 if( fe->isCharged() && PVMatchedAcc(*fe)&& ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) ) ) {
240 ATH_MSG_DEBUG("Accept cFE with pt " << fe->pt() << ", e " << fe->e() << ", eta " << fe->eta() << ", phi " << fe->phi() );
241 felist.push_back(fe);
242 }
243 }
244 }
245 } // end cFE loop
246
247 // Neutral FEs
248 for (const FELink_t& feLink : nFELinks) {
249 if (!feLink.isValid()) continue;
250 const xAOD::FlowElement* fe_init = *feLink;
251 for (const auto *const fe : *constits.feCont){
252 if (fe->index() == fe_init->index() && !fe->isCharged()){ //index-based match between JetETmiss and CHSFlowElements collections
253 if( ( !fe->isCharged()&& fe->e() > FLT_MIN ) ){
254 ATH_MSG_DEBUG("Accept nFE with pt " << fe->pt() << ", e " << fe->e() << ", eta " << fe->eta() << ", phi " << fe->phi() << " in sum.");
255 felist.push_back(fe);
256 }
257 }
258 }
259 } // end nFE links loop
260
261
262 return StatusCode::SUCCESS;
263 }
264
266 std::vector<const xAOD::IParticle*>& felist,
267 const met::METAssociator::ConstitHolder& constits) const
268 {
269 const TrackParticle* idtrack = mu->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
270 const CaloCluster* muclus = mu->cluster();
271 ATH_MSG_VERBOSE("Muon " << mu->index() << " with pt " << mu->pt()
272 << ", eta " << mu->eta()
273 << ", phi " << mu->phi());
274 if(muclus) {
275 ATH_MSG_VERBOSE(" has cluster with "
276 << "eta " << muclus->calEta()
277 << ", phi " << muclus->calPhi()
278 << ", E " << muclus->calE()
279 << " formed of " << muclus->size() << " cells.");
280 }
281 ATH_MSG_VERBOSE("Muon Eloss type: " << mu->energyLossType()
282 << " Eloss: " << mu->floatParameter(xAOD::Muon::EnergyLoss)
283 << " MeasuredEloss: " << mu->floatParameter(xAOD::Muon::MeasEnergyLoss)
284 << " FSR E: " << mu->floatParameter(xAOD::Muon::FSR_CandidateEnergy) );
285
286 // One loop over PFOs
287 for(const xAOD::FlowElement* fe : *constits.feCont) {
288 if(fe->isCharged()) {
289 // get charged FEs by matching the muon ID track
290 // We set a small -ve pt for cPFOs that were rejected
291 // by the ChargedHadronSubtractionTool
292 const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
293 if(idtrack && fe->chargedObject(0) == idtrack && PVMatchedAcc(*fe) &&
294 ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) )
295 ) {
296 ATH_MSG_VERBOSE("Accept muon PFO (FE) " << fe << " px, py = " << fe->p4().Px() << ", " << fe->p4().Py());
297 ATH_MSG_VERBOSE("Muon PFO index: " << fe->index() << ", pt: " << fe->pt() << ", eta: " << fe->eta() << ", phi: " << fe->phi() );
298 ATH_MSG_VERBOSE("Muon ID Track index: " << idtrack->index() << ", pt: " << idtrack->pt() << ", eta: " << idtrack->eta() << ", phi: " << idtrack->phi() );
299 felist.push_back(fe);
300 break;
301 } // track match
302 } else {
303 // get neutral PFOs by matching the muon cluster
304 if(muclus && m_doMuonClusterMatch) {
305
307 for(const auto& matchel : tcLinkAcc(*muclus)) {
308 if(!matchel.isValid()) {
309 ATH_MSG_DEBUG("Invalid muon-cluster elementLink");
310 } else {
311 if((*matchel)->e()>FLT_MIN && fe->otherObject(0) == *matchel) { // +ve E && matches cluster
312 ATH_MSG_VERBOSE("Tool found cluster " << (*matchel)->index() << " with pt " << (*matchel)->pt() );
313 felist.push_back(fe);
314 }
315 }
316 }
317 } // muon has linked cluster
318 }
319 } // end of cluster loop
320
321 return StatusCode::SUCCESS;
322 }
323
324 // add HR implementation from release 21.2
325 // extractFE for W precision-type measurements
327 std::vector<const xAOD::IParticle*> hardObjs,
328 std::vector<const xAOD::IParticle*>& felist,
329 const met::METAssociator::ConstitHolder& constits,
330 std::map<const IParticle*,MissingETBase::Types::constvec_t> & /*momenta*/,
331 float& UEcorr) const
332 {
333 if(obj->type() != xAOD::Type::ObjectType::Muon){
334 UEcorr=0.0;
335 felist={};
336 return StatusCode::SUCCESS;
337 }
338 const xAOD::Muon* mu = static_cast<const xAOD::Muon*>(obj);
339
340 // Get PFOs associated to muons
341 for(const auto fe : *constits.feCont) {
342 if( fe->isCharged()) { // Fill list with charged PFOs (using muon tracks)
343 if( mu && P4Helpers::isInDeltaR(*fe, *mu, m_Drcone, m_useRapidity) && PVMatchedAcc(*fe) &&
344 ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) ) ){
345 felist.push_back(fe);
346 }
347 }
348 else{ // Fill list with neutral PFOs (using muon clusters)
349 if( mu && P4Helpers::isInDeltaR(*fe, *mu, m_Drcone, m_useRapidity) ){
350 felist.push_back(fe);
351 }
352 } // neutral PFO condition
353 } // loop over all PFOs
354
355 // Calculating UE energy correction for a given lepton (using mu)
356 if(mu){
357 // Vectoral sum of all FE
358 TLorentzVector HR; // uncorrected HR (initialized with 0,0,0,0 automatically)
359 for(const auto fe_itr : *constits.feCont) {
360 if( fe_itr->pt() < 0 || fe_itr->e() < 0 ) { // sanity check
361 continue;
362 }
363
364 //remove charged FE that are not matched to the PV
365 if(fe_itr->isCharged() && !PVMatchedAcc(*fe_itr)){
366 continue;
367 }
368 HR += fe_itr->p4();
369 }
370
371 // Create vectors of muons
372 std::vector<const xAOD::Muon*> v_mu;
373 for(const auto& obj_i : hardObjs) {
374 if(obj_i->pt()<5e3 && obj_i->type() != xAOD::Type::Muon) { // sanity check
375 continue;
376 }
377 const xAOD::Muon* mu_curr = static_cast<const xAOD::Muon*>(obj_i); // current muon
378 v_mu.push_back(mu_curr);
379 }
380
381
382 // Subtracting PFOs matched to muons from HR
383 for(const auto fe_i : *constits.feCont) { // charged and neutral PFOs
384 if( fe_i->pt() < 0 || fe_i->e() < 0 ) { // sanity check
385 continue;
386 }
387 for(const auto& mu_i : v_mu) { // loop over muons
388 double dR = P4Helpers::deltaR( fe_i->eta(), fe_i->phi(), mu_i->eta(), mu_i->phi() );
389 if( dR < m_Drcone ) { // if PFO is in a cone around muon
390 HR -= fe_i->p4();
391 break;
392 } // cone requirement
393 } // over v_mu
394 } // over PFOs
395
396 // Save v_mu as a vector TLV (as commonn type for electrons and muons)
397 std::vector<TLorentzVector> v_muTLV;
398 v_muTLV.reserve(v_mu.size());
399 for(const auto& mu_i : v_mu) { // loop over v_mu
400 v_muTLV.push_back( mu_i->p4() );
401 }
402
403 // Save current mu as TLV
404 TLorentzVector muTLV = mu->p4();
405
406 // Get UE correction
407 ATH_CHECK( GetUEcorr(constits, v_muTLV, muTLV, HR, m_Drcone, m_MinDistCone, UEcorr) );
408 } // available mu requirement
409
410
411 return StatusCode::SUCCESS;
412 }
413}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ElementLink< xAOD::MuonContainer > MuonLink_t
ElementLink< xAOD::FlowElementContainer > FELink_t
Handle class for reading a decoration on an object.
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
size_t index() const
Return the index of this element within its container.
Helper class to provide constant type-safe access to aux data.
Handle class for reading a decoration on an object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
virtual StatusCode fillAssocMap(xAOD::MissingETAssociationMap *metMap, const xAOD::IParticleContainer *hardObjs) const
std::string m_chargedFELinksKey
METAssociator(const std::string &name)
bool isGoodEoverP(const xAOD::TrackParticle *trk) const
std::string m_neutralFELinksKey
StatusCode GetUEcorr(const met::METAssociator::ConstitHolder &constits, std::vector< TLorentzVector > &v_clus, TLorentzVector &clus, TLorentzVector &HR, const float Drcone, const float MinDistCone, float &UEcorr) const
bool acceptTrack(const xAOD::TrackParticle *trk, const xAOD::Vertex *pv) const
StatusCode extractTracks(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &constlist, const met::METAssociator::ConstitHolder &constits) const final
StatusCode extractFE(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits, std::map< const xAOD::IParticle *, MissingETBase::Types::constvec_t > &momenta) const final
METMuonAssociator()
Default constructor:
SG::ReadDecorHandleKey< xAOD::MuonContainer > m_neutralFEReadDecorKey
Gaudi::Property< bool > m_doMuonClusterMatch
SG::ReadDecorHandleKey< xAOD::MuonContainer > m_chargedFEReadDecorKey
StatusCode executeTool(xAOD::MissingETContainer *metCont, xAOD::MissingETAssociationMap *metMap) const final
StatusCode extractPFO(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &pfolist, const met::METAssociator::ConstitHolder &constits, std::map< const xAOD::IParticle *, MissingETBase::Types::constvec_t > &momenta) const final
StatusCode extractFEHR(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > hardObjs, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits, std::map< const xAOD::IParticle *, MissingETBase::Types::constvec_t > &momenta, float &UEcorr) const final
SG::ReadHandleKey< xAOD::MuonContainer > m_muContKey
StatusCode extractFEs(const xAOD::Muon *mu, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits) const
StatusCode extractTopoClusters(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &tclist, const met::METAssociator::ConstitHolder &constits) const final
static constexpr float m_Drcone
StatusCode extractFEsFromLinks(const xAOD::Muon *mu, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits) const
static constexpr float m_MinDistCone
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
SG::ReadDecorHandleKey< xAOD::CaloClusterContainer > m_elementLinkName
flt_t calPhi() const
Get in signal state CALIBRATED.
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
flt_t calEta() const
Get in signal state CALIBRATED.
flt_t calE() const
Geet Energy in signal state CALIBRATED.
virtual double pt() const override
virtual double phi() const override
The azimuthal angle ( ) of the particle.
virtual double eta() const override
The pseudorapidity ( ) of the particle.
const xAOD::IParticle * chargedObject(std::size_t i) const
const xAOD::IParticle * otherObject(std::size_t i) const
virtual FourMom_t p4() const override
The full 4-momentum of the particle.
Class providing the definition of the 4-vector interface.
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
const Trk::Track * track() const
Returns a pointer (which can be NULL) to the Trk::Track which was used to make this TrackParticle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .)
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
static const SG::ConstAccessor< char > PVMatchedAcc("matchedToPV")
@ Muon
The object is a muon.
Definition ObjectType.h:48
bool isInDeltaR(const xAOD::IParticle &p1, const xAOD::IParticle &p2, double dR, bool useRapidity=true)
Check if 2 xAOD::IParticle are in a cone.
double deltaR(double rapidity1, double phi1, double rapidity2, double phi2)
from bare bare rapidity,phi
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition FlowElement.h:16
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Muon_v1 Muon
Reference the current persistent version:
MissingETAssociationMap_v1 MissingETAssociationMap
Version control by type defintion.
const xAOD::FlowElementContainer * feCont
const xAOD::PFOContainer * pfoCont