ATLAS Offline Software
Loading...
Searching...
No Matches
MuonCreatorTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// MuonCreatorTool
7// Creates xAOD::Muon objects from muon candidates
8//
10
11#include "MuonCreatorTool.h"
12
25#include "SortInDetCandidates.h"
32#include "TrkTrack/Track.h"
42
43namespace {
44 static const SG::Accessor<int> acc_nUnspoiledCscHits("nUnspoiledCscHits");
45 static const SG::Accessor<float> acc_MuonSpectrometerPt("MuonSpectrometerPt");
46 static const SG::Accessor<float> acc_InnerDetectorPt("InnerDetectorPt");
47 static const SG::Accessor<unsigned int> acc_numEnergyLossPerTrack("numEnergyLossPerTrack");
48
49 static const SG::Accessor<float> acc_ET_Core("ET_Core");
50 static const SG::Accessor<float> acc_ET_EMCore("ET_EMCore");
51 static const SG::Accessor<float> acc_ET_TileCore("ET_TileCore");
52 static const SG::Accessor<float> acc_ET_HECCore("ET_HECCore");
53} // namespace
54namespace MuonCombined {
55
57 if (m_buildStauContainer) ATH_MSG_DEBUG(" building Stau container ");
58
59 ATH_CHECK(m_idHelperSvc.retrieve());
60 ATH_CHECK(m_printer.retrieve());
61 ATH_CHECK(m_muonPrinter.retrieve());
62 ATH_CHECK(m_caloExtTool.retrieve());
63 ATH_CHECK(m_edmHelperSvc.retrieve());
64 ATH_CHECK(m_particleCreator.retrieve());
66 ATH_CHECK(m_muonDressingTool.retrieve());
67 ATH_CHECK(m_caloMgrKey.initialize());
68 ATH_CHECK(m_trackQuery.retrieve());
69 if (!m_momentumBalanceTool.empty())
71 else
72 m_momentumBalanceTool.disable();
73 if (!m_scatteringAngleTool.empty())
75 else
76 m_scatteringAngleTool.disable();
77 if (!m_selectorTool.empty())
78 ATH_CHECK(m_selectorTool.retrieve());
79 else
80 m_selectorTool.disable();
81 if (!m_meanMDTdADCTool.empty())
82 ATH_CHECK(m_meanMDTdADCTool.retrieve());
83 else
84 m_meanMDTdADCTool.disable();
85
87
88 ATH_MSG_INFO("ET_Core calculation: doNoiseCut, sigma - " << !m_caloNoiseKey.empty() << " " << m_sigmaCaloNoiseCut);
89
90 if (!m_doSA) {
92 ATH_CHECK(m_propagator.retrieve());
93 } else {
94 m_caloMaterialProvider.disable();
95 m_propagator.disable();
96 }
98 ATH_CHECK(m_trackSummaryTool.retrieve());
99
101 for (const std::string &a_key : m_copyFloatSummaryKeys ) {
102 m_copyFloatSummaryAccessors.push_back(std::make_unique< SG::Accessor<float> >(a_key));
103 }
105 for (const std::string &a_key : m_copyCharSummaryKeys ) {
106 m_copyCharSummaryAccessors.push_back(std::make_unique< SG::Accessor<uint8_t> >(a_key));
107 }
108
109 return StatusCode::SUCCESS;
110 }
111 void MuonCreatorTool::create(const EventContext& ctx, const MuonCandidateCollection* muonCandidates,
112 const std::vector<const InDetCandidateToTagMap*>& tagMaps, OutputData& outputData) const {
113 // Create containers for resolved candidates (always of type VIEW_ELEMENTS)
114 InDetCandidateTagsMap resolvedInDetCandidates;
115 // std::vector<const MuonCombined::InDetCandidate*> resolvedInDetCandidates;
116 std::vector<const MuonCombined::MuonCandidate*> resolvedMuonCandidates;
117
118 // Resolve Overlap
120 resolveOverlaps(ctx, muonCandidates, tagMaps, resolvedInDetCandidates, resolvedMuonCandidates);
121 else{
122 selectStaus(resolvedInDetCandidates, tagMaps);
123 }
124
125 unsigned int numIdCan = resolvedInDetCandidates.size();
126 unsigned int numMuCan = muonCandidates ? muonCandidates->size() : 0;
127 ATH_MSG_DEBUG("Creating xAOD::Muons from: " << numIdCan << " indet candidates and " << numMuCan << " muon candidates ");
128
129 if (!m_buildStauContainer && muonCandidates)
130 ATH_MSG_DEBUG("MuonCandidates : overlap removal " << muonCandidates->size() << " in, " << resolvedMuonCandidates.size()
131 << " out");
132
133 // Create a container for resolved candidates (always of type VIEW_ELEMENTS)
134 for (InDetCandidateTags& can : resolvedInDetCandidates) {
135 ATH_MSG_DEBUG("New InDetCandidate");
136 xAOD::Muon* muon = create(ctx, can, outputData);
137 if (!muon) {
138 ATH_MSG_DEBUG("no muon found");
139 } else {
140 ATH_MSG_DEBUG("muon found");
141 }
142 ATH_MSG_DEBUG("Creation of Muon from InDetCandidates done");
143 }
144 if (!m_requireIDTracks) { // only build SA muons if ID tracks are not required
145 for (const MuonCombined::MuonCandidate* can : resolvedMuonCandidates) {
146 ATH_MSG_DEBUG("New MuonCandidate");
147 create(ctx, *can, outputData);
148 ATH_MSG_DEBUG("Creation of Muon from MuonCandidates done");
149 }
150 }
151
152 if (msgLvl(MSG::DEBUG) || m_printSummary) {
153 ATH_MSG_INFO("Printing muon container:");
154 ATH_MSG_INFO(m_muonPrinter->print(*outputData.muonContainer));
155 ATH_MSG_INFO("Done");
156 }
157 if (msgLvl(MSG::VERBOSE) && outputData.clusterContainer) {
158 ATH_MSG_VERBOSE("Associated clusters : " << outputData.clusterContainer->size());
159 }
160 }
161
162 xAOD::Muon* MuonCreatorTool::create(const EventContext& ctx, const MuonCandidate& candidate, OutputData& outputData) const {
163 // skip all muons without extrapolated track
164 if (m_requireMSOEforSA && !candidate.extrapolatedTrack()) {
165 ATH_MSG_DEBUG("MuonCreatorTool::create(...) No extrapolated track - aborting. Will not create Muon.");
166 return nullptr; // Do we really want to do this?
167 }
168
169 // Create the xAOD object:
170 xAOD::Muon* muon = outputData.muonContainer->push_back(std::make_unique<xAOD::Muon>());
171 decorateDummyValues(ctx, *muon, outputData);
172
173 muon->setAuthor(xAOD::Muon::Author::MuidSA);
174 muon->setMuonType(xAOD::Muon::MuonType::MuonStandAlone);
175 muon->addAllAuthor(xAOD::Muon::Author::MuidSA);
176
177 // create candidate from SA muon only
178 addMuonCandidate(ctx, candidate, *muon, outputData);
179
180 using TrackParticleType = xAOD::Muon::TrackParticleType;
181 if (m_requireMSOEforSA && !muon->trackParticle(TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle)) {
182 ATH_MSG_DEBUG("Creation of track particle for SA muon failed, removing it");
183 outputData.muonContainer->pop_back();
184 return nullptr;
185 }
186
187 if (!dressMuon(*muon)) {
188 ATH_MSG_WARNING("Failed to dress muon");
189 outputData.muonContainer->pop_back();
190 return nullptr;
191 }
192
193 const xAOD::TrackParticle* track = muon->trackParticle(TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle);
194 if (!track) track = muon->primaryTrackParticle();
195 std::unique_ptr<Trk::CaloExtension> caloExtension = m_caloExtTool->caloExtension(ctx, *track);
196 if (m_requireCaloDepositForSA && !caloExtension) {
197 ATH_MSG_DEBUG("failed to get a calo extension for this SA muon, discard it");
198 outputData.muonContainer->pop_back();
199 return nullptr;
200 }
201 if (m_requireCaloDepositForSA && caloExtension->caloLayerIntersections().empty()) {
202 ATH_MSG_DEBUG("failed to retrieve any calo layers for this SA muon, discard it");
203 outputData.muonContainer->pop_back();
204 return nullptr;
205 }
206 // check if there is a cluster container, if yes collect the cells around the
207 // muon and fill Etcore variables for muon
208 if (caloExtension && m_useCaloCells) collectCells(ctx, *muon, outputData.clusterContainer, caloExtension.get());
209
210 return muon;
211 }
212
213 void MuonCreatorTool::decorateDummyValues(const EventContext& ctx, xAOD::Muon& muon, OutputData& outputData) const {
214 // Set variables to zero by calling the functions with null pointers.
215 addCaloTag(muon, nullptr);
216 addCombinedFit(ctx, muon, nullptr, outputData);
217 addStatisticalCombination(ctx, muon, nullptr, nullptr, outputData);
218 addMuGirl(ctx, muon, nullptr, outputData);
219 addSegmentTag(ctx, muon, nullptr, outputData);
220
222 acc_nUnspoiledCscHits(muon) = 0;
223 acc_MuonSpectrometerPt(muon) = -1;
224 acc_InnerDetectorPt(muon) = -1;
225
226 acc_ET_Core(muon) = 0;
227 acc_ET_EMCore(muon) = 0;
228 acc_ET_TileCore(muon) = 0;
229 acc_ET_HECCore(muon) = 0;
230
231 fillEnergyLossFromTrack(muon, nullptr);
232 }
233 xAOD::Muon* MuonCreatorTool::create(const EventContext& ctx, InDetCandidateTags& candidate, OutputData& outputData) const {
234 // no tags, no muon
235 if (candidate.second.empty()) {
236 ATH_MSG_DEBUG("MuonCreatorTool::create(...) - InDetCandidate with empty combinedDataTags. Aborting. Will not create Muon.");
237 return nullptr;
238 }
239 const std::vector<const TagBase*>& tags = candidate.second;
240 if (tags.size() == 1 && !m_buildStauContainer) {
241 const MuGirlLowBetaTag* muGirlLowBetaTag = dynamic_cast<const MuGirlLowBetaTag*>(tags[0]);
242 if (muGirlLowBetaTag) {
243 ATH_MSG_DEBUG("Track has only a MuGirlLowBetaTag but Staus are not being built, so will not create muon");
244 return nullptr;
245 }
246 }
247
248 // Create the xAOD object:
249 xAOD::Muon* muon = new xAOD::Muon();
250 outputData.muonContainer->push_back(muon);
251 muon->setMuonSegmentLinks(std::vector<ElementLink<xAOD::MuonSegmentContainer>>{});
252
253 // now we need to sort the tags to get the best muon
254
255 // set the link to the ID track particle
256 muon->setTrackParticleLink(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle, candidate.first->indetTrackParticleLink());
257 ATH_MSG_DEBUG("Adding InDet Track: pt " << candidate.first->indetTrackParticle().pt() << " eta "
258 << candidate.first->indetTrackParticle().eta() << " phi "
259 << candidate.first->indetTrackParticle().phi());
260
261 ATH_MSG_DEBUG("creating Muon with " << tags.size() << " tags ");
262 // loop over the tags
263
264 decorateDummyValues(ctx, *muon, outputData);
265 bool first = true;
266 for (const MuonCombined::TagBase* tag : tags) {
267 ATH_MSG_DEBUG("Handling tag: type " << tag->type());
268
269 // staus
271 const MuGirlLowBetaTag* muGirlLowBetaTag = dynamic_cast<const MuGirlLowBetaTag*>(tag);
272
273 if (muGirlLowBetaTag) {
274 ATH_MSG_DEBUG("MuonCreatorTool MuGirlLowBetaTag ");
275
276 muon->setAuthor(tag->author());
277 muon->setMuonType(tag->type());
278
279 if (tag->type() == xAOD::Muon::MuonType::Combined) {
280 ATH_MSG_DEBUG("MuonCreatorTool MuGirlLowBetaTag combined");
281
282 // Create the xAOD object:
283 if (outputData.slowMuonContainer) {
284 xAOD::SlowMuon* slowMuon = outputData.slowMuonContainer->push_back(std::make_unique<xAOD::SlowMuon>());
285
286 addMuGirlLowBeta(ctx, *muon, muGirlLowBetaTag, slowMuon,
287 outputData); // CHECK to see what variables are created here.
288
289 ATH_MSG_DEBUG("slowMuon muonContainer size " << outputData.muonContainer->size());
290 ElementLink<xAOD::MuonContainer> muonLink(*outputData.muonContainer, outputData.muonContainer->size() - 1);
291 if (slowMuon && muonLink.isValid()) {
292 ATH_MSG_DEBUG("slowMuon muonLink valid");
293 slowMuon->setMuonLink(muonLink);
294 }
295 }
296 }
297 }
298 } else {
299 // Don't want staus in muon branch
300 const MuGirlLowBetaTag* muGirlLowBetaTag = dynamic_cast<const MuGirlLowBetaTag*>(tag);
301 if (muGirlLowBetaTag) continue;
302
303 // set author info
304 if (first) {
305 ATH_MSG_DEBUG("MuonCreatorTool first muon tag: author=" << tag->author() << " type=" << tag->type());
306 muon->setAuthor(tag->author());
307 muon->setMuonType(tag->type());
308 // Overrride type if InDet track is SiAssociated.
309 if (candidate.first->isSiliconAssociated()) {
310 muon->setMuonType(xAOD::Muon::MuonType::SiliconAssociatedForwardMuon);
311 }
312 first = false;
313 }
314
315 muon->addAllAuthor(tag->author());
316
317 // this is not too elegant, maybe rethink implementation
318 xAOD::Muon::MuonType type = tag->type();
319 if (type == xAOD::Muon::MuonType::Combined) {
320 // work out type of tag
321 const CombinedFitTag* cbFitTag = dynamic_cast<const CombinedFitTag*>(tag);
322 const StacoTag* stacoTag = dynamic_cast<const StacoTag*>(tag);
323 const MuGirlTag* muGirlTag = dynamic_cast<const MuGirlTag*>(tag);
324
325 addCombinedFit(ctx, *muon, cbFitTag, outputData);
326 addMuGirl(ctx, *muon, muGirlTag, outputData);
327 addStatisticalCombination(ctx, *muon, candidate.first, stacoTag, outputData);
328 if (!(cbFitTag || stacoTag || muGirlTag)) { ATH_MSG_WARNING("Unknown combined tag "); }
329
330 } else if (type == xAOD::Muon::MuonType::SegmentTagged) {
331 const SegmentTag* segTag = dynamic_cast<const SegmentTag*>(tag);
332 const MuGirlTag* muGirlTag = dynamic_cast<const MuGirlTag*>(tag);
333
334 addSegmentTag(ctx, *muon, segTag, outputData);
335 addMuGirl(ctx, *muon, muGirlTag, outputData);
336
337 if (!(segTag || muGirlTag)) { ATH_MSG_WARNING("Unknown segment-tagged tag "); }
338 } else if (type == xAOD::Muon::MuonType::CaloTagged) {
339 const CaloTag* caloTag = dynamic_cast<const CaloTag*>(tag);
340 addCaloTag(*muon, caloTag);
341 if (!caloTag) { ATH_MSG_WARNING("Unknown calo tag type "); }
342 } else {
343 ATH_MSG_WARNING("Unknown tag type. Type= "<<type);
344 }
345 }
346 } // m_buildStauContainer
347
348 if (!dressMuon(*muon)) {
349 ATH_MSG_WARNING("Failed to dress muon");
350 outputData.muonContainer->pop_back();
351 // if we are dealing with staus, also need to remove the slowMuon
352 if (m_buildStauContainer) outputData.slowMuonContainer->pop_back();
353 return nullptr;
354 }
355
356 // If eLoss is not already available then build it
357 float eLoss = -1;
358 bool haveEloss = muon->parameter(eLoss, xAOD::Muon::ParamDef::EnergyLoss);
359 if (!haveEloss || eLoss == 0) {
360 ATH_MSG_DEBUG("Adding Energy Loss to muon" << std::endl << m_muonPrinter->print(*muon));
361 addEnergyLossToMuon(*muon);
362 }
363
364 // check if there is a cluster container, if yes collect the cells around the
365 // muon and fill Etcore variables for muon
366 if (m_useCaloCells) collectCells(ctx, *muon, outputData.clusterContainer, candidate.first->getCaloExtension());
367
368 ATH_MSG_DEBUG("Done creating muon with " << acc_nUnspoiledCscHits(*muon) << " unspoiled csc hits");
369
370 return muon;
371 }
372
373 void MuonCreatorTool::addStatisticalCombination(const EventContext& ctx, xAOD::Muon& muon, const InDetCandidate* candidate,
374 const StacoTag* tag, OutputData& outputData) const {
375 static const SG::Accessor<float> acc_d0("d0_staco");
376 static const SG::Accessor<float> acc_z0("z0_staco");
377 static const SG::Accessor<float> acc_phi0("phi0_staco");
378 static const SG::Accessor<float> acc_theta("theta_staco");
379 static const SG::Accessor<float> acc_qOverP("qOverP_staco");
380 static const SG::Accessor<float> acc_qOverPerr("qOverPErr_staco");
381
382 if (!tag) {
383 // init variables if necessary.
384 acc_d0(muon) = -999;
385 acc_z0(muon) = -999;
386 acc_phi0(muon) = -999;
387 acc_theta(muon) = -999;
388 acc_qOverP(muon) = -999;
389 acc_qOverPerr(muon) = -999.;
390 return;
391 }
392
393 ATH_MSG_DEBUG("Adding Staco Muon " << tag->author() << " type " << tag->type());
394
395 if (!muon.trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) {
396 // create primary track particle
397 // get summary
398 const Trk::Track* idTrack = candidate->indetTrackParticle().track();
399 const Trk::Track* msTrack = tag->muonCandidate().extrapolatedTrack() ? tag->muonCandidate().extrapolatedTrack()
400 : &tag->muonCandidate().muonSpectrometerTrack();
401
402 const Trk::TrackSummary* idSummary = idTrack ? idTrack->trackSummary() : nullptr;
403 const Trk::TrackSummary* msSummary = msTrack->trackSummary();
404
405 Trk::TrackSummary summary;
406 if (idSummary) summary += *idSummary;
407 if (msSummary) summary += *msSummary;
408
409 Trk::FitQuality fq(tag->matchChi2(), 5);
410 Trk::TrackInfo info(msTrack->info());
411 // todo update patrec bit set adding ID values
412
413 if (outputData.combinedTrackParticleContainer) {
414 xAOD::TrackParticle* tp = m_particleCreator->createParticle(ctx, &tag->combinedParameters(), &fq, &info, &summary, {}, {},
415 xAOD::muon, outputData.combinedTrackParticleContainer);
416 if (!tp) {
417 ATH_MSG_WARNING("Failed to create track particle");
418 } else {
421 std::vector<float> dummy_cov(15, 0.);
422 tp->setTrackParameterCovarianceMatrix(0, dummy_cov);
423
424 ElementLink<xAOD::TrackParticleContainer> link(*outputData.combinedTrackParticleContainer,
425 outputData.combinedTrackParticleContainer->size() - 1);
426 if (link.isValid()) {
427 // link.toPersistent();
428 ATH_MSG_DEBUG("Adding statistical combination: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi "
429 << (*link)->phi());
430 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::CombinedTrackParticle, link);
431 }
432 // for the purpose of the truth matching, set the track link to point to
433 // the ID track
434 // tp->setTrackLink(candidate.indetTrackParticle().trackLink());
436 std::bitset<xAOD::NumberOfTrackRecoInfo> pattern;
437 pattern.set(xAOD::STACO);
438 tp->setPatternRecognitionInfo(pattern);
439
440 const xAOD::TrackParticle &id_track_particle = candidate->indetTrackParticle();
441 for (const std::unique_ptr< SG::Accessor<float> > &accessor : m_copyFloatSummaryAccessors ) {
442 (*accessor)( *tp ) = (*accessor)( id_track_particle );
443 }
444 for (const std::unique_ptr< SG::Accessor<uint8_t> > &accessor : m_copyCharSummaryAccessors ) {
445 (*accessor)( *tp ) = (*accessor)( id_track_particle );
446 }
447
448 }
449 } // endif outputData.combinedTrackParticleContainer
450 }
451
452 // add muon candidate
453 addMuonCandidate(ctx, tag->muonCandidate(), muon, outputData);
454
455 // Add inner match chi^2
456 muon.setParameter(5, xAOD::Muon::ParamDef::msInnerMatchDOF);
457 muon.setParameter(static_cast<float>(tag->matchChi2()), xAOD::Muon::ParamDef::msInnerMatchChi2);
458
459 // STACO parameters added as auxdata
460 acc_d0(muon) = tag->combinedParameters().parameters()[Trk::d0];
461 acc_z0(muon) = tag->combinedParameters().parameters()[Trk::z0];
462 acc_phi0(muon) = tag->combinedParameters().parameters()[Trk::phi0];
463 acc_theta(muon) = tag->combinedParameters().parameters()[Trk::theta];
464 acc_qOverP(muon) = tag->combinedParameters().parameters()[Trk::qOverP];
465 acc_qOverPerr(muon) = Amg::error(*tag->combinedParameters().covariance(), Trk::qOverP);
466
467 ATH_MSG_DEBUG("Done adding Staco Muon " << tag->author() << " type " << tag->type());
468 }
469
470 void MuonCreatorTool::addCombinedFit(const EventContext& ctx, xAOD::Muon& muon, const CombinedFitTag* tag,
471 OutputData& outputData) const {
472 if (!tag) {
473 // init variables if necessary.
474 return;
475 }
476
477 ATH_MSG_DEBUG("Adding Combined fit Muon " << tag->author() << " type " << tag->type());
478 if (!muon.trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) {
479 // if the combined track particle is part of a container set the link
480 if (outputData.combinedTrackParticleContainer) {
481 // create element link from the track
483 ctx, tag->combinedTrackLink(), *outputData.combinedTrackParticleContainer, outputData.combinedTrackCollection);
484
485 if (link.isValid()) {
486 // link.toPersistent();
487 ATH_MSG_DEBUG("Adding combined fit: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi " << (*link)->phi());
488 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::CombinedTrackParticle, link);
489 } else
490 ATH_MSG_WARNING("Creating of Combined TrackParticle Link failed");
491 }
492 }
493 // add muon candidate
494 addMuonCandidate(ctx, tag->muonCandidate(), muon, outputData, tag->updatedExtrapolatedTrackLink());
495
496 // Add inner match chi^2
497 const float inner_chi2 = tag->matchChi2();
498 muon.setParameter(tag->matchDoF(), xAOD::Muon::ParamDef::msInnerMatchDOF);
499 muon.setParameter(inner_chi2, xAOD::Muon::ParamDef::msInnerMatchChi2);
500
501 ATH_MSG_DEBUG("Done adding Combined Fit Muon " << tag->author() << " type " << tag->type());
502 }
503
504 void MuonCreatorTool::addMuGirlLowBeta(const EventContext& ctx,
505 xAOD::Muon& muon,
506 const MuGirlLowBetaTag* tag,
507 xAOD::SlowMuon* slowMuon,
508 OutputData& outputData) const {
509 if (!tag) {
510 // init variables if necessary.
511 return;
512 }
513
514 ATH_MSG_DEBUG("Adding MuGirlLowBeta Muon " << tag->author() << " type " << tag->type());
515
516 // get stauExtras and write to slowMuon
517 const MuGirlNS::StauExtras* stauExtras = tag->getStauExtras();
518 if (slowMuon && stauExtras) {
519 ATH_MSG_VERBOSE("StauSummary beta " << stauExtras->betaAll<<" "<<stauExtras->betaAllt);
520 slowMuon->setBeta(stauExtras->betaAll);
521 slowMuon->setBetaT(stauExtras->betaAllt);
522 slowMuon->setAnn(stauExtras->ann);
523 slowMuon->setNRpcHits(stauExtras->numRpcHitsInSeg);
524 slowMuon->setNTileCells(stauExtras->numCaloCells);
525 slowMuon->setRpcInfo(stauExtras->rpcBetaAvg, stauExtras->rpcBetaRms, stauExtras->rpcBetaChi2, stauExtras->rpcBetaDof);
526 slowMuon->setMdtInfo(stauExtras->mdtBetaAvg, stauExtras->mdtBetaRms, stauExtras->mdtBetaChi2, stauExtras->mdtBetaDof);
527 slowMuon->setCaloInfo(stauExtras->caloBetaAvg, stauExtras->caloBetaRms, stauExtras->caloBetaChi2, stauExtras->caloBetaDof);
528
529 static const SG::Accessor<std::vector<uint8_t> > eTechAcc ("hitTechnology");
530 static const SG::Accessor<std::vector<unsigned int> > idAcc ("hitIdentifier");
531 static const SG::Accessor<std::vector<float> > mToFAcc ("hitTOF");
532 static const SG::Accessor<std::vector<float> > xAcc ("hitPositionX");
533 static const SG::Accessor<std::vector<float> > yAcc ("hitPositionY");
534 static const SG::Accessor<std::vector<float> > zAcc ("hitPositionZ");
535 static const SG::Accessor<std::vector<float> > eAcc ("hitEnergy");
536 static const SG::Accessor<std::vector<float> > errorAcc ("hitError");
537 static const SG::Accessor<std::vector<float> > shiftAcc ("hitShift");
538 static const SG::Accessor<std::vector<float> > propTimeAcc ("hitPropagationTime");
539 static const SG::Accessor<std::vector<uint8_t> > hitPassesMDTBetaCutAcc ("hitPassesMDTBetaCut");
540
541 std::vector<uint8_t>& eTechVec = eTechAcc(*slowMuon);
542 std::vector<unsigned int>& idVec = idAcc(*slowMuon);
543 std::vector<float>& mToFVec = mToFAcc(*slowMuon);
544 std::vector<float>& xVec = xAcc(*slowMuon);
545 std::vector<float>& yVec = yAcc(*slowMuon);
546 std::vector<float>& zVec = zAcc(*slowMuon);
547 std::vector<float>& eVec = eAcc(*slowMuon);
548 std::vector<float>& errorVec = errorAcc(*slowMuon);
549 std::vector<float>& shiftVec = shiftAcc(*slowMuon);
550 std::vector<float>& propagationTimeVec = propTimeAcc(*slowMuon);
551 std::vector<uint8_t>& passesMDTBetaCutVec = hitPassesMDTBetaCutAcc(*slowMuon);
552
553 for (const auto& hit : stauExtras->hits) {
554 eTechVec.push_back(hit.eTech);
555 idVec.push_back(hit.id.get_identifier32().get_compact());
556 mToFVec.push_back(hit.mToF);
557 xVec.push_back(hit.x);
558 yVec.push_back(hit.y);
559 zVec.push_back(hit.z);
560 eVec.push_back(hit.e);
561 errorVec.push_back(hit.error);
562 shiftVec.push_back(hit.shift);
563 propagationTimeVec.push_back(hit.propagationTime);
564 passesMDTBetaCutVec.push_back(hit.passesMDTBetaCut ? uint8_t{1} : uint8_t{0});
565 }
566
567 // additional MDT hit info (optional)
569 static const SG::Accessor<std::vector<int> > adcAcc ("hitAdc");
570 static const SG::Accessor<std::vector<float> > rdriftAcc ("hitDriftRadius");
571
572 std::vector<int>& adcVec = adcAcc(*slowMuon);
573 std::vector<float>& rdriftVec = rdriftAcc(*slowMuon);
574
575 if (stauExtras->extraMDTHitInfo) { // check if extra MDT hit info added
576 for (const auto& extraMDTinfo : *stauExtras->extraMDTHitInfo) {
577 adcVec.push_back(extraMDTinfo.adc);
578 rdriftVec.push_back(extraMDTinfo.rdrift);
579 }
580 }
581 }
582
583
584 }
585
586 if (!muon.trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle) && tag->combinedTrack()) {
587 // if the combined track particle is part of a container set the link
588 if (outputData.combinedTrackParticleContainer) {
589 // create element link
591 ctx, tag->combinedTrackLink(), *outputData.combinedTrackParticleContainer, outputData.combinedTrackCollection);
592
593 if (link.isValid()) {
594 ATH_MSG_DEBUG("Adding MuGirlLowBeta: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi " << (*link)->phi());
595 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::CombinedTrackParticle, link);
596 } else
597 ATH_MSG_WARNING("Creating of MuGirlLowBeta TrackParticle Link failed");
598 }
599 }
600
601 if (outputData.xaodSegmentContainer) {
602 ATH_MSG_DEBUG("Adding MuGirlLowBeta muonSegmentColection");
603 std::vector<ElementLink<xAOD::MuonSegmentContainer>> segments;
604 for (const ElementLink<Trk::SegmentCollection>& seglink : tag->segments()) {
605 ElementLink<xAOD::MuonSegmentContainer> link{*outputData.xaodSegmentContainer, seglink.index(), ctx};
606 if (link.isValid()) {
607 segments.push_back(link);
608 ATH_MSG_DEBUG("Adding MuGirlLowBeta: xaod::MuonSegment px " << (*link)->px() << " py " << (*link)->py() << " pz "
609 << (*link)->pz());
610 } else
611 ATH_MSG_WARNING("Creating of MuGirlLowBeta segment Link failed");
612 }
613 muon.setMuonSegmentLinks(segments);
614 }
615 }
616
617 void MuonCreatorTool::addMuGirl(const EventContext& ctx, xAOD::Muon& muon, const MuGirlTag* tag, OutputData& outputData) const {
618 if (!tag) {
619 // init variables if necessary.
620 return;
621 }
622
623 ATH_MSG_DEBUG("Adding MuGirl Muon " << tag->author() << " type " << tag->type());
624
625 if (!muon.trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle) && tag->combinedTrack()) {
626 // if the combined track particle is part of a container set the link
627 if (outputData.combinedTrackParticleContainer) {
628 // create element link
630 ctx, tag->combinedTrackLink(), *outputData.combinedTrackParticleContainer, outputData.combinedTrackCollection);
631
632 if (link.isValid()) {
633 // link.toPersistent();
634 ATH_MSG_DEBUG("Adding MuGirl: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi " << (*link)->phi());
635 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::CombinedTrackParticle, link);
636 } else
637 ATH_MSG_WARNING("Creating of MuGirl TrackParticle Link failed");
638 }
639
640 if (outputData.extrapolatedTrackParticleContainer && tag->updatedExtrapolatedTrack()) {
641 // create element link
643 createTrackParticleElementLink(ctx, tag->updatedExtrapolatedTrackLink(), *outputData.extrapolatedTrackParticleContainer,
644 outputData.extrapolatedTrackCollection);
645
646 if (link.isValid()) {
647 ATH_MSG_DEBUG("Adding MuGirl: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi " << (*link)->phi());
648 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle, link);
649 } else
650 ATH_MSG_WARNING("Creating of MuGirl TrackParticle Link failed");
651 }
652
653 if (outputData.xaodSegmentContainer) {
654 ATH_MSG_DEBUG("Adding MuGirl muonSegmentCollection");
655
656 std::vector<ElementLink<xAOD::MuonSegmentContainer>> segments;
657 for (const Muon::MuonSegment* segLink : tag->associatedSegments()) {
659 if (link.isValid()) {
660 segments.push_back(link);
661 ATH_MSG_DEBUG("Adding MuGirl: xaod::MuonSegment px " << (*link)->px() << " py " << (*link)->py() << " pz "
662 << (*link)->pz());
663 } else
664 ATH_MSG_WARNING("Creating of MuGirl segment Link failed");
665 }
666 muon.setMuonSegmentLinks(segments);
667 }
668 }
669 ATH_MSG_DEBUG("Done Adding MuGirl Muon " << tag->author() << " type " << tag->type());
670 }
671
672 void MuonCreatorTool::addSegmentTag(const EventContext& ctx, xAOD::Muon& muon, const SegmentTag* tag, OutputData& outputData) const {
673 if (!tag) {
674 // init variables if necessary.
675 using enum xAOD::Muon::ParamDef;
676 muon.setParameter(-1.f, segmentDeltaEta);
677 muon.setParameter(-1.f, segmentDeltaPhi);
678 muon.setParameter(-1.f, segmentChi2OverDoF);
679 return;
680 }
681
682 ATH_MSG_DEBUG("Adding Segment Tag Muon " << tag->author() << " type " << tag->type());
683
684 std::vector<ElementLink<xAOD::MuonSegmentContainer>> segments;
685 bool foundseg = false;
686 for (const auto& info : tag->segmentsInfo()) {
687 // this is a bit tricky, as we have here a link to an xAOD segment in the old container
688 // but the new container should have the segments in the same order, plus the MuGirl ones tacked on the end
689 // so we should be able to just make a new link here
690 // note that this only applies to segment-tagged muons, others get their associated segments elsewhere
691 if (muon.author() == xAOD::Muon::Author::MuTagIMO) {
692 ElementLink<xAOD::MuonSegmentContainer> seglink = createMuonSegmentElementLink(ctx, info.segment, outputData);
693 if (seglink.isValid()) segments.push_back(seglink);
694 }
695
696 if (!foundseg) { // add parameters for the first segment
697 muon.setParameter(static_cast<float>(info.dtheta), xAOD::Muon::ParamDef::segmentDeltaEta);
698 muon.setParameter(static_cast<float>(info.dphi), xAOD::Muon::ParamDef::segmentDeltaPhi);
699 muon.setParameter(static_cast<float>(info.segment->fitQuality()->chiSquared() / info.segment->fitQuality()->numberDoF()),
700 xAOD::Muon::ParamDef::segmentChi2OverDoF);
701 foundseg = true;
702 } else if (muon.author() != xAOD::Muon::Author::MuTagIMO)
703 break; // for non-segment-tagged muons, we only need to set the above
704 // parameters
705 }
706 if (muon.author() == xAOD::Muon::Author::MuTagIMO) muon.setMuonSegmentLinks(segments); // set the associated segments
707 }
708
709 void MuonCreatorTool::addCaloTag(xAOD::Muon& mu, const CaloTag* tag) const {
710 static const SG::Accessor<float> acc_ElType("CT_EL_Type"); // FIXME - should be uint
711 static const SG::Accessor<float> acc_ElFSREnergy("CT_ET_FSRCandidateEnergy");
712
713 if (!tag) {
714 // init variables if necessary.
715
716 mu.setParameter(0.f, xAOD::Muon::ParamDef::CaloMuonScore);
717 mu.setParameter(static_cast<int>(0xFF), xAOD::Muon::ParamDef::CaloMuonIDTag);
719 // Here we can make sure that we store the extra calotag information -
720 // just always add it since this is then unambigious for debugging
721 acc_ET_Core(mu) = 0.0;
722 acc_ElType(mu) = -999.0;
723 acc_ElFSREnergy(mu) = -999.0;
724 }
725 return;
726 }
727
728 ATH_MSG_DEBUG("Adding Calo Muon with author " << tag->author() << ", type " << tag->type() << ", CaloMuonScore "
729 << tag->caloMuonScore());
730 mu.setParameter(static_cast<float>(tag->caloMuonScore()), xAOD::Muon::ParamDef::CaloMuonScore);
731 mu.setParameter(static_cast<int>(tag->caloMuonIdTag()), xAOD::Muon::ParamDef::CaloMuonIDTag);
732
734 // Here we can make sure that we store the extra calotag information - just
735 // always add it since this is then unambigious for debugging
736 acc_ET_Core(mu) = tag->etCore();
737 acc_ElType(mu) = tag->energyLossType();
738 acc_ElFSREnergy(mu) = tag->fsrCandidateEnergy();
739 }
740 // FIXME - calo deposits
741 }
742
744 const EventContext& ctx,
745 const ElementLink<TrackCollection>& trackLink, xAOD::TrackParticleContainer& trackParticleContainer,
746 TrackCollection* trackCollection) const {
747 ATH_MSG_DEBUG("createTrackParticleElementLink");
748 xAOD::TrackParticle* tp = nullptr;
749 if (trackCollection) {
750 trackCollection->push_back(new Trk::Track(**trackLink));
751 // want to link the track particle to this track
752 ElementLink<TrackCollection> link(*trackCollection, trackCollection->size() - 1);
753 if (link.isValid())
754 tp = m_particleCreator->createParticle(ctx, link, &trackParticleContainer, nullptr, xAOD::muon);
755 else
756 ATH_MSG_WARNING("new Track Collection link invalid");
757 }
758 if (!tp) {
759 // create track particle without a link to the track
760 tp = m_particleCreator->createParticle(ctx, **trackLink, &trackParticleContainer, nullptr, xAOD::muon);
761 }
762
763 if (tp) {
764 ElementLink<xAOD::TrackParticleContainer> link(trackParticleContainer, trackParticleContainer.size() - 1);
765 return link;
766 }
768 }
769
771 const Muon::MuonSegment* trkSeg,
772 const OutputData& outData) const {
773 if (outData.xaodSegmentContainer && outData.tagToSegmentAssocMap) {
774 // if a muon segment collection is provided, duplicate the segment and
775 // create a link to that
776 unsigned int link = outData.tagToSegmentAssocMap->linkIndex(trkSeg);
777 if (link >= outData.xaodSegmentContainer->size()) {
778 ATH_MSG_WARNING("Failed to retrieve a proper link for segment " << m_printer->print(*trkSeg));
779 return {};
780 }
781 ElementLink<xAOD::MuonSegmentContainer> eleLink{*outData.xaodSegmentContainer, link, ctx};
782 return eleLink;
783 }
785 }
786
787 void MuonCreatorTool::addMuonCandidate(const EventContext& ctx, const MuonCandidate& candidate, xAOD::Muon& muon,
788 OutputData& outputData, const ElementLink<TrackCollection>& meLink) const {
789 if (!muon.nMuonSegments()) {
790 std::vector< ElementLink<xAOD::MuonSegmentContainer>> segments;
791 for (const Muon::MuonSegment* segLink : candidate.getSegments()) {
793 if (link.isValid()) {
794 segments.push_back(link);
795 ATH_MSG_DEBUG("Adding MuGirl: xaod::MuonSegment px " << (*link)->px() << " py " << (*link)->py() << " pz "
796 << (*link)->pz());
797 } else
798 ATH_MSG_WARNING("Creating of Muon candidate segment failed "<<candidate.toString());
799
800 }
801 muon.setMuonSegmentLinks(segments);
802 }
803 // only set once
804 if (muon.trackParticle(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle)) { return; }
805 // case where we have a MuGirl muon that is also reconstructed by STACO: don't
806 // want to add this track as it is misleading however, we will still keep the
807 // MS-only extrapolated track (see below) for debugging purposes
808 if (muon.author() != xAOD::Muon::Author::MuGirl)
809 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle, candidate.muonSpectrometerTrackLink());
810
811 // we need both the container and the extrapolated muon track to add the link
812 if (!outputData.extrapolatedTrackParticleContainer || (!candidate.extrapolatedTrack() && !meLink.isValid())) { return; }
813
814 const Trk::Track* extrapolatedTrack = candidate.extrapolatedTrack();
815
816 if (!extrapolatedTrack || !extrapolatedTrack->perigeeParameters()) {
817 ATH_MSG_DEBUG("There is no extrapolated track associated to the MuonCandidate.");
818 if (muon.author() == xAOD::Muon::Author::MuidCo) { // this can happen for MuidCo muons, though it's
819 // quite rare: in this case just add the ME track
820 if (meLink.isValid()) {
822 ctx, meLink, *outputData.extrapolatedTrackParticleContainer, outputData.extrapolatedTrackCollection);
823 if (link.isValid()) {
824 ATH_MSG_DEBUG("Adding standalone fit (refitted): pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi "
825 << (*link)->phi());
826 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle, link);
827 float fieldInt = m_trackQuery->fieldIntegral(**meLink, ctx).betweenSpectrometerMeasurements();
828 muon.setParameter(fieldInt, xAOD::Muon::ParamDef::spectrometerFieldIntegral);
829 int nunspoiled = (*link)->track()->trackSummary()->get(Trk::numberOfCscUnspoiltEtaHits);
830 acc_nUnspoiledCscHits(muon) = nunspoiled;
831 }
832 }
833 } else { // I don't think we should ever get here, but just in case
834 if (!extrapolatedTrack) ATH_MSG_WARNING("Track doesn't have extrapolated track. Skipping");
835 if (extrapolatedTrack && !extrapolatedTrack->perigeeParameters())
837 "Track doesn't have perigee parameters on extrapolated "
838 "track. Skipping");
839 }
840 } else {
841 // Now we just add the original extrapolated track itself
842 // but not for SA muons, for consistency they will still have
843 // extrapolatedTrackParticle
844 if (muon.muonType() != xAOD::Muon::MuonType::MuonStandAlone) {
845 if (meLink.isValid()) { // add ME track and MS-only extrapolated track
846 if (outputData.msOnlyExtrapolatedTrackParticleContainer) { // add un-refitted
847 // extrapolated track
848 // as MS-only
849 // extrapolated track
851 ctx, candidate.extrapolatedTrackLink(), *outputData.msOnlyExtrapolatedTrackParticleContainer,
852 outputData.msOnlyExtrapolatedTrackCollection);
853
854 if (link.isValid()) {
855 ATH_MSG_DEBUG("Adding MS-only extrapolated track: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi "
856 << (*link)->phi());
857 // link.toPersistent();
858 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::MSOnlyExtrapolatedMuonSpectrometerTrackParticle, link);
859 } else
860 ATH_MSG_WARNING("failed to create MS-only extrapolated track particle");
861 }
862 // now add refitted track as ME track
864 ctx, meLink, *outputData.extrapolatedTrackParticleContainer, outputData.extrapolatedTrackCollection);
865 if (link.isValid()) {
866 ATH_MSG_DEBUG("Adding standalone fit (refitted): pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi "
867 << (*link)->phi());
868 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle, link);
869 float fieldInt = m_trackQuery->fieldIntegral(**meLink, ctx).betweenSpectrometerMeasurements();
870 muon.setParameter(fieldInt, xAOD::Muon::ParamDef::spectrometerFieldIntegral);
871 int nunspoiled = (*link)->track()->trackSummary()->get(Trk::numberOfCscUnspoiltEtaHits);
872 acc_nUnspoiledCscHits(muon) = nunspoiled;
873 }
874 } else { // no refitted track, so add original un-refitted extrapolated
875 // track as ME track
876 if (muon.author() == xAOD::Muon::Author::MuGirl && muon.trackParticle(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle)) {
877 // MuGirl case: ME track is already set, but now we have the
878 // extrapolated track from the STACO tag add this as the MS-only
879 // extrapolated track instead
881 ctx, candidate.extrapolatedTrackLink(), *outputData.msOnlyExtrapolatedTrackParticleContainer,
882 outputData.msOnlyExtrapolatedTrackCollection);
883
884 if (link.isValid()) {
885 ATH_MSG_DEBUG("Adding MS-only extrapolated track to MuGirl muon: pt "
886 << (*link)->pt() << " eta " << (*link)->eta() << " phi " << (*link)->phi());
887 // link.toPersistent();
888 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::MSOnlyExtrapolatedMuonSpectrometerTrackParticle, link);
889 float fieldInt =
890 m_trackQuery->fieldIntegral(**candidate.extrapolatedTrackLink(), ctx).betweenSpectrometerMeasurements();
891 muon.setParameter(fieldInt, xAOD::Muon::ParamDef::spectrometerFieldIntegral);
892 }
893 } else {
895 ctx, candidate.extrapolatedTrackLink(), *outputData.extrapolatedTrackParticleContainer,
896 outputData.extrapolatedTrackCollection);
897
898 if (link.isValid()) {
899 ATH_MSG_DEBUG("Adding standalone fit (un-refitted): pt " << (*link)->pt() << " eta " << (*link)->eta()
900 << " phi " << (*link)->phi());
901 // link.toPersistent();
902 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle, link);
903 float fieldInt =
904 m_trackQuery->fieldIntegral(**candidate.extrapolatedTrackLink(), ctx).betweenSpectrometerMeasurements();
905 muon.setParameter(fieldInt, xAOD::Muon::ParamDef::spectrometerFieldIntegral);
906 }
907 }
908 }
909 } else { // SA tracks only get un-refitted track as ME track
910 // create element link from the track
912 createTrackParticleElementLink(ctx, candidate.extrapolatedTrackLink(), *outputData.extrapolatedTrackParticleContainer,
913 outputData.extrapolatedTrackCollection);
914
915 if (link.isValid()) {
916 ATH_MSG_DEBUG("Adding standalone fit: pt " << (*link)->pt() << " eta " << (*link)->eta() << " phi " << (*link)->phi());
917 // link.toPersistent();
918 muon.setTrackParticleLink(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle, link);
919 float fieldInt =
920 m_trackQuery->fieldIntegral(**candidate.extrapolatedTrackLink(), ctx).betweenSpectrometerMeasurements();
921 muon.setParameter(fieldInt, xAOD::Muon::ParamDef::spectrometerFieldIntegral);
922 int nunspoiled = extrapolatedTrack->trackSummary()->get(Trk::numberOfCscUnspoiltEtaHits);
923 acc_nUnspoiledCscHits(muon) = nunspoiled;
924 } else {
925 ATH_MSG_WARNING("failed to create ME track particle for SA muon");
926 }
927 }
928 }
929 }
930
932 const std::vector<const InDetCandidateToTagMap*>& tagMaps) const {
933 resolvedInDetCandidates.clear();
934 for (const InDetCandidateToTagMap* tag_map : tagMaps) {
935 if (!tag_map) continue;
936 for (const auto& combined_tag : *tag_map) {
937 const TagBase* tag = combined_tag.second.get();
938 const MuGirlLowBetaTag* muGirlLowBetaTag = dynamic_cast<const MuGirlLowBetaTag*>(tag);
939 if (muGirlLowBetaTag) { resolvedInDetCandidates.emplace_back(combined_tag.first, std::vector<const TagBase*>{tag}); }
940 }
941 break;
942 }
943 // print-out
944 if (msgLvl(MSG::DEBUG)) {
945 ATH_MSG_DEBUG("ID candidates: " << tagMaps.size() << " after stau selection " << resolvedInDetCandidates.size());
946 for (const InDetCandidateTags& candidate : resolvedInDetCandidates) {
947 msg(MSG::DEBUG) << "ID candidate staus: " << candidate.first->toString() << endmsg;
948 }
949 }
950
951 // tag_map above is keyed on a pointer.
952 // So we need to sort in order to get reproducible results.
953 std::stable_sort(resolvedInDetCandidates.begin(), resolvedInDetCandidates.end(),
954 [](const InDetCandidateTags& a, const InDetCandidateTags& b) {
955 return a.first->indetTrackParticle().pt() > b.first->indetTrackParticle().pt();
956 });
957 }
958
959 void MuonCreatorTool::resolveOverlaps(const EventContext& ctx, const MuonCandidateCollection* muonCandidates,
960 const std::vector<const InDetCandidateToTagMap*>& tagMaps,
961 InDetCandidateTagsMap& resolvedInDetCandidates,
962 std::vector<const MuonCombined::MuonCandidate*>& resolvedMuonCandidates) const {
963 resolvedMuonCandidates.clear();
964 resolvedInDetCandidates.clear();
965
966 std::unique_ptr<const TrackCollection> resolvedTracks;
967 std::vector<std::unique_ptr<Trk::Track>> garbage_collection;
968
972 InDetCandidateTagsMap inDetCandidateMap;
973 for (const InDetCandidateToTagMap* tag_map : tagMaps) {
974 if (!tag_map) continue;
975 for (const auto& comb_tag : *tag_map) {
976 const TagBase* tag = comb_tag.second.get();
980 InDetCandidateTagsMap::iterator itr =
981 std::find_if(inDetCandidateMap.begin(), inDetCandidateMap.end(),
982 [&comb_tag](const InDetCandidateTags& to_test) { return (*to_test.first) == (*comb_tag.first); });
983 if (itr != inDetCandidateMap.end())
984 itr->second.emplace_back(tag);
985 else
986 inDetCandidateMap.emplace_back(std::make_pair(comb_tag.first, std::vector<const TagBase*>{tag}));
987 }
988 }
989
990 // Each InDetCandidate corresponds to a different ID track.
991 // Resolve overlap among InDetCandidates for cases where different
992 // ID tracks are tagged by the same MS info (track or segment)
993 if (!inDetCandidateMap.empty()) {
994 // the muons only found by the calo tagger should always be kept so we can
995 // filter them out from the start
996 InDetCandidateTagsMap caloMuons;
997
998 // first loop over ID candidates and select all candidates that have a tag
999 resolvedInDetCandidates.reserve(inDetCandidateMap.size());
1000 caloMuons.reserve(inDetCandidateMap.size());
1001 for (InDetCandidateTags& comb_tag : inDetCandidateMap) {
1002 std::stable_sort(comb_tag.second.begin(), comb_tag.second.end(), SortTagBasePtr());
1003 if (comb_tag.second.size() == 1 && comb_tag.second.front()->type() == xAOD::Muon::MuonType::CaloTagged) {
1004 caloMuons.emplace_back(std::move(comb_tag));
1005 } else
1006 resolvedInDetCandidates.emplace_back(std::move(comb_tag));
1007 }
1008 inDetCandidateMap.clear();
1009 // now sort the selected ID candidates
1010 std::stable_sort(resolvedInDetCandidates.begin(), resolvedInDetCandidates.end(), SortInDetCandidates());
1011 if (msgLvl(MSG::DEBUG)) {
1012 ATH_MSG_DEBUG("Found " << resolvedInDetCandidates.size() << " inner detector tags in event "
1013 << ctx.eventID().event_number());
1014 for (const InDetCandidateTags& candidate : resolvedInDetCandidates) {
1015 std::stringstream tags;
1016 for (const TagBase* tag : candidate.second) tags << " " << tag->toString();
1017 ATH_MSG_DEBUG("ID candidate: " << candidate.first->toString() << " " << tags.str());
1018 }
1019 }
1020
1022
1023 to_resolve.reserve(resolvedInDetCandidates.size());
1024 garbage_collection.reserve(resolvedInDetCandidates.size());
1025
1026 // a dummy track for segment tagged candidates to be used in the overlap
1027 // check
1028 std::map<const Trk::Track*, InDetCandidateTags> trackInDetCandLinks;
1029
1030 for (InDetCandidateTags& candidate : resolvedInDetCandidates) {
1031 // retrieve the primary tag
1032 const TagBase* primaryTag = candidate.second[0];
1033
1034 // check if a track is available
1035 if (primaryTag->primaryTrack()) {
1037 to_resolve.push_back(primaryTag->primaryTrack());
1038 // create a track summary for this track
1039 trackInDetCandLinks[to_resolve.back()] = std::move(candidate);
1040 }
1041 // if not, make a dummy track out of segments, muonTracks takes ownership
1042 // of the memory
1043 else {
1044 std::vector<const Muon::MuonSegment*> segments = primaryTag->associatedSegments();
1045 if (!segments.empty()) {
1047 garbage_collection.emplace_back(
1048 createDummyTrack(ctx, primaryTag->associatedSegments(), *(candidate.first->indetTrackParticle().track())));
1050 to_resolve.push_back(garbage_collection.back().get());
1052 trackInDetCandLinks[garbage_collection.back().get()] = std::move(candidate);
1053 }
1054 }
1055 }
1056 resolvedInDetCandidates.clear();
1057
1058 // Resolve ambiguity between muon tracks
1059 resolvedTracks.reset(m_ambiguityProcessor->process(to_resolve.asDataVector()));
1060
1061 // link back to InDet candidates and fill the resolved container
1062 for (const Trk::Track* track : *resolvedTracks) {
1063 std::map<const Trk::Track*, InDetCandidateTags>::iterator trackCandLink = trackInDetCandLinks.find(track);
1064 if (trackCandLink == trackInDetCandLinks.end()) {
1065 ATH_MSG_WARNING("Unable to find internal link between MS track and ID candidate!");
1066 continue;
1067 }
1068 resolvedInDetCandidates.push_back(std::move(trackCandLink->second));
1069 }
1070
1071 // print-out
1072 if (msgLvl(MSG::VERBOSE)) {
1073 ATH_MSG_DEBUG("ID candidates after ambiguity solving "
1074 << resolvedInDetCandidates.size() << " trackCandLinks: " << trackInDetCandLinks.size()
1075 << " to_resolve: " << to_resolve.size() << " resolvedTracks: " << resolvedTracks->size());
1076 for (const InDetCandidateTags& candidate : resolvedInDetCandidates) {
1077 ATH_MSG_DEBUG("ID candidate: " << candidate.first->toString() << " " << candidate.second[0]->toString());
1078 }
1079 ATH_MSG_DEBUG("Calo muons after ambiguity solving: ");
1080 for (const InDetCandidateTags& candidate : caloMuons) {
1081 ATH_MSG_DEBUG("ID candidate: " << candidate.first->toString() << " " << candidate.second[0]->toString());
1082 }
1083 }
1084 // add muons only found by calo tagger
1085 resolvedInDetCandidates.insert(resolvedInDetCandidates.end(), caloMuons.begin(), caloMuons.end());
1086
1087 // now sort the selected ID candidates
1088 std::stable_sort(resolvedInDetCandidates.begin(), resolvedInDetCandidates.end(),
1089 [](const InDetCandidateTags& a, const InDetCandidateTags& b) {
1090 return a.first->indetTrackParticle().pt() > b.first->indetTrackParticle().pt();
1091 });
1092 }
1093
1094 // MuonCandidateCollection contains all muon tracks (SA extrapolated or not)
1095 // Resolve overlap with InDetCandidate collection
1096 if (!muonCandidates) { return; }
1097
1098 if (msgLvl(MSG::DEBUG)) {
1099 ATH_MSG_DEBUG("Muon candidates: " << muonCandidates->size());
1100 for (const MuonCandidate* candidate : *muonCandidates) { ATH_MSG_DEBUG("Muon candidate: " << candidate->toString()); }
1101 }
1102
1104 if (resolvedTracks) { resolvedTracks2.assign(resolvedTracks->begin(), resolvedTracks->end()); }
1105 // Keep track of the MuonCandidates used by MuidCo
1106 std::set<const MuonCandidate*> used_candidates;
1107 for (const InDetCandidateTags& indet_cand : resolvedInDetCandidates) {
1108 for (const TagBase* tag : indet_cand.second) {
1110 if (tag->author() == xAOD::Muon::Author::MuidCo) {
1111 const CombinedFitTag* cmb_tag = dynamic_cast<const CombinedFitTag*>(tag);
1112 used_candidates.insert(&cmb_tag->muonCandidate());
1113 } else if (tag->author() == xAOD::Muon::Author::STACO && indet_cand.second[0] == tag) {
1114 const StacoTag* staco_tag = dynamic_cast<const StacoTag*>(tag);
1115 used_candidates.insert(&staco_tag->muonCandidate());
1116 }
1117 }
1118 }
1119
1120 // add MS tracks to resolvedTrack collection and store a link between tracks
1121 // and muon candidates
1122 std::map<const Trk::Track*, const MuonCandidate*> trackMuonCandLinks;
1123 for (const MuonCandidate* candidate : *muonCandidates) {
1124 const Trk::Track* track = candidate->primaryTrack();
1125 if (used_candidates.count(candidate)) {
1126 ATH_MSG_DEBUG("Duplicate MS track " << m_printer->print(*track));
1127 continue;
1128 }
1129 used_candidates.insert(candidate);
1130 resolvedTracks2.push_back(track); // VIEW_ELEMENTS, pointer only
1131 trackMuonCandLinks[track] = candidate;
1132 }
1133
1134 // solve ambiguity
1135 resolvedTracks.reset(m_ambiguityProcessor->process(resolvedTracks2.asDataVector()));
1136
1137 // loop over resolved tracks and fill resolved muon candidates
1138 for (const Trk::Track* track : *resolvedTracks) {
1139 auto trackCandLink = trackMuonCandLinks.find(track);
1140 if (trackCandLink != trackMuonCandLinks.end()) resolvedMuonCandidates.push_back(trackCandLink->second);
1141 }
1142
1143 // print-out
1144 if (msgLvl(MSG::DEBUG)) {
1145 ATH_MSG_DEBUG("Muon candidates: " << muonCandidates->size() << " after ambiguity solving " << resolvedMuonCandidates.size());
1146 for (const MuonCandidate* candidate : resolvedMuonCandidates) {
1147 msg(MSG::DEBUG) << "Muon candidate: " << candidate->toString() << endmsg;
1148 }
1149 }
1150 }
1151
1152 std::unique_ptr<Trk::Track> MuonCreatorTool::createDummyTrack(const EventContext& ctx,
1153 const std::vector<const Muon::MuonSegment*>& segments,
1154 const Trk::Track& indetTrack) const {
1155 ATH_MSG_VERBOSE("Creating dummy tracks from segments...");
1156
1157 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1158
1159 for (const Muon::MuonSegment* seg : segments) {
1160 // create pars for muon and loop over hits
1161 double momentum{1e8}, charge{0.};
1162 std::unique_ptr<const Trk::TrackParameters> pars{m_edmHelperSvc->createTrackParameters(*seg, momentum, charge)};
1163 for (const Trk::MeasurementBase* meas : seg->containedMeasurements()) {
1164 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern(0);
1166 // TSoS takes ownership
1167 std::unique_ptr<Trk::TrackParameters> exPars{m_propagator->propagateParameters(
1168 ctx, *pars, meas->associatedSurface(), Trk::anyDirection, false, Trk::MagneticFieldProperties(Trk::NoField))};
1169 if (!exPars) { ATH_MSG_VERBOSE("Could not propagate Track to segment surface"); }
1170 Trk::TrackStateOnSurface* trackState =
1171 new Trk::TrackStateOnSurface(meas->uniqueClone(), std::move(exPars), nullptr, typePattern);
1172 trackStateOnSurfaces->push_back(trackState);
1173 } // end segment loop
1174 }
1175
1178 info.setPatternRecognitionInfo(author);
1179 std::unique_ptr<Trk::Track> newtrack =
1180 std::make_unique<Trk::Track>(info, std::move(trackStateOnSurfaces), (indetTrack.fitQuality())->uniqueClone());
1181
1182 // create a track summary for this track
1183 if (m_trackSummaryTool.isEnabled()) { m_trackSummaryTool->computeAndReplaceTrackSummary(ctx, *newtrack, false); }
1184
1185 return newtrack;
1186 }
1187
1189 const xAOD::TrackParticle* primary = muon.primaryTrackParticle();
1190 // update parameters with primary track particle
1191 setP4(muon, *primary);
1192 const float qOverP = primary->qOverP();
1193 if (qOverP != 0.0) {
1194 muon.setCharge(qOverP > 0 ? 1. : -1.);
1195 } else {
1196 ATH_MSG_WARNING("MuonCreatorTool::dressMuon - trying to set qOverP, but value from muon.primaryTrackParticle ["
1197 << "] is zero. Setting charge=0.0. The eta/phi of the muon is: " << muon.eta() << " / " << muon.phi());
1198 muon.setCharge(0.0);
1199 }
1200
1201 // add hit summary
1202 m_muonDressingTool->addMuonHitSummary(muon);
1203
1204 // calculate scattering significance and momentum balance significance
1205 if (!m_scatteringAngleTool.empty()) {
1206 Rec::ScatteringAngleSignificance scatSign = m_scatteringAngleTool->scatteringAngleSignificance(muon);
1207 float curvatureSignificance = scatSign.curvatureSignificance();
1208 muon.setParameter(curvatureSignificance, xAOD::Muon::ParamDef::scatteringCurvatureSignificance);
1209 float neighbourSignificance = scatSign.neighbourSignificance();
1210 muon.setParameter(neighbourSignificance, xAOD::Muon::ParamDef::scatteringNeighbourSignificance);
1211 ATH_MSG_VERBOSE("Got curvatureSignificance " << curvatureSignificance << " and neighbourSignificance "
1212 << neighbourSignificance);
1213 }
1214
1215 if (!m_momentumBalanceTool.empty()) {
1216 float momentumBalanceSignificance = m_momentumBalanceTool->momentumBalanceSignificance(muon);
1217 muon.setParameter(momentumBalanceSignificance, xAOD::Muon::ParamDef::momentumBalanceSignificance);
1218 ATH_MSG_VERBOSE("Got momentumBalanceSignificance " << momentumBalanceSignificance);
1219 }
1220
1221 if (!m_meanMDTdADCTool.empty()) {
1222 float meanDeltaADC = float(m_meanMDTdADCTool->meanMDTdADCFiller(muon));
1223 muon.setParameter(meanDeltaADC, xAOD::Muon::ParamDef::meanDeltaADCCountsMDT);
1224 ATH_MSG_VERBOSE("Got meanDeltaADCCountsMDT " << meanDeltaADC);
1225 }
1226
1227 if (!m_selectorTool.empty()) {
1228 acc_MuonSpectrometerPt(muon) = muon.pt();
1229 acc_InnerDetectorPt(muon) = muon.pt();
1230 // set id cuts
1231 m_selectorTool->setPassesIDCuts(muon);
1232 ATH_MSG_VERBOSE("Setting passesIDCuts " << muon.passesIDCuts());
1233 // set quality
1234 m_selectorTool->setQuality(muon);
1235 ATH_MSG_VERBOSE("Setting Quality " << muon.quality());
1236 }
1237
1239 const Trk::Track* trk = nullptr;
1240 if (muon.trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) {
1241 trk = muon.trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)->track();
1242 }
1243 if (!trk && muon.trackParticle(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle)) {
1244 trk = muon.trackParticle(xAOD::Muon::TrackParticleType::ExtrapolatedMuonSpectrometerTrackParticle)->track();
1245 }
1246 if (trk) {
1248 } else {
1249 fillEnergyLossFromTrack(muon, nullptr); // Just fill empty variables.
1250 ATH_MSG_VERBOSE("Couldn't find matching track which might have energy loss.");
1251 }
1252 }
1253 return true;
1254 }
1256 const xAOD::TrackParticle* trkPart = muon.trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
1257 if (!trkPart) {
1258 ATH_MSG_WARNING("Missing ID track particle link in addEnergyLossToMuon!");
1259 return;
1260 }
1261
1262 // get ID track particle
1263 const Trk::Track* trk = trkPart->track();
1264 if (!trk) {
1265 ATH_MSG_WARNING("Missing ID trk::track in addEnergyLossToMuon!");
1266 return;
1267 }
1268
1269 // find last ID TSOS with track parameters
1270 const Trk::TrackStateOnSurface* lastID = nullptr;
1273 for (; it != itEnd; ++it) {
1274 if ((*it)->trackParameters()) {
1275 lastID = *it;
1276 break;
1277 }
1278 }
1279 if (!lastID) {
1280 ATH_MSG_WARNING("Missing ID TSOS with track parameters in addEnergyLossToMuon!");
1281 return;
1282 }
1283
1284 // get calorimeter TSOS
1285 std::vector<const Trk::TrackStateOnSurface*>* caloTSOS = m_caloMaterialProvider->getCaloTSOS(*((*it)->trackParameters()), *trk);
1286
1287 if (!caloTSOS) {
1288 ATH_MSG_WARNING("Unable to find calo TSOS in addEnergyLossToMuon!");
1289 return;
1290 }
1291
1292 // fill muon parameters for eloss
1293 fillEnergyLossFromTrack(muon, caloTSOS);
1294
1295 // delete caloTSOS
1296 std::vector<const Trk::TrackStateOnSurface*>::const_iterator it2 = caloTSOS->begin();
1297 std::vector<const Trk::TrackStateOnSurface*>::const_iterator itEnd2 = caloTSOS->end();
1298 for (; it2 != itEnd2; ++it2) delete *it2;
1299 delete caloTSOS;
1300 }
1301
1302 void MuonCreatorTool::fillEnergyLossFromTrack(xAOD::Muon& muon, const std::vector<const Trk::TrackStateOnSurface*>* tsosVector) const {
1303 // Ensure these are set for every muon
1304 if (!tsosVector) {
1305 using enum xAOD::Muon::ParamDef;
1306 muon.setParameter(0.f, EnergyLoss);
1307 muon.setParameter(0.f, ParamEnergyLoss);
1308 muon.setParameter(0.f, MeasEnergyLoss);
1309 muon.setParameter(0.f, EnergyLossSigma);
1310 muon.setParameter(0.f, MeasEnergyLossSigma);
1311 muon.setParameter(0.f, ParamEnergyLossSigmaPlus);
1312 muon.setParameter(0.f, ParamEnergyLossSigmaMinus);
1313 muon.setParameter(0.f, FSR_CandidateEnergy);
1314
1315 muon.setEnergyLossType(xAOD::Muon::EnergyLossType::Parametrized); // Not so nice! Add 'unknown' type?
1316 if (m_fillExtraELossInfo) acc_numEnergyLossPerTrack(muon) = 0;
1317
1318 return;
1319 }
1320
1321 unsigned int numEnergyLossPerTrack = 0;
1322 bool problem = false;
1323 for (const auto* tsos : *tsosVector) {
1324 const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(tsos->materialEffectsOnTrack());
1325 if (!meot) continue;
1326 const Trk::EnergyLoss* el = meot->energyLoss();
1327 const CaloEnergy* caloEnergy = dynamic_cast<const CaloEnergy*>(el);
1328 if (!caloEnergy) continue;
1329 ++numEnergyLossPerTrack;
1330 using enum xAOD::Muon::ParamDef;
1331
1332 muon.setParameter(static_cast<float>(caloEnergy->deltaE()), EnergyLoss);
1333 muon.setParameter(static_cast<float>(caloEnergy->deltaEParam()), ParamEnergyLoss);
1334 muon.setParameter(static_cast<float>(caloEnergy->deltaEMeas()), MeasEnergyLoss);
1335 muon.setParameter(static_cast<float>(caloEnergy->sigmaDeltaE()), EnergyLossSigma);
1336 muon.setParameter(static_cast<float>(caloEnergy->sigmaDeltaEMeas()), MeasEnergyLossSigma);
1337 muon.setParameter(static_cast<float>(caloEnergy->sigmaPlusDeltaEParam()), ParamEnergyLossSigmaPlus);
1338 muon.setParameter(static_cast<float>(caloEnergy->sigmaMinusDeltaEParam()), ParamEnergyLossSigmaMinus);
1339
1340 muon.setEnergyLossType(static_cast<xAOD::Muon::EnergyLossType>(caloEnergy->energyLossType()));
1341 muon.setParameter(static_cast<float>(caloEnergy->fsrCandidateEnergy()), FSR_CandidateEnergy);
1342 }
1343 if (numEnergyLossPerTrack > 1) {
1344 ATH_MSG_VERBOSE("More than one e loss per track... ");
1345 problem = true;
1346 }
1347 if (m_fillExtraELossInfo) acc_numEnergyLossPerTrack(muon) = numEnergyLossPerTrack;
1348 if (problem) ATH_MSG_VERBOSE("Dumping problematic muon: " << m_muonPrinter->print(muon));
1349 }
1350
1351 void MuonCreatorTool::collectCells(const EventContext& ctx, xAOD::Muon& muon, xAOD::CaloClusterContainer* clusterContainer,
1352 const Trk::CaloExtension* inputCaloExt) const {
1353 const xAOD::TrackParticle* tp = muon.primaryTrackParticle();
1354 if (!tp || !clusterContainer) {
1355 if (!tp) ATH_MSG_WARNING("Can not get primary track.");
1356 return;
1357 }
1358
1359 // get ParticleCellAssociation
1360 ATH_MSG_DEBUG(" Selected track: pt " << tp->pt() << " eta " << tp->eta() << " phi " << tp->phi());
1361
1362 xAOD::CaloCluster* cluster = nullptr;
1364
1366 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
1367
1368 if (!inputCaloExt) { // need to make one
1369 // for some reason, ID tracks need to be extrapolated from the ID exit, and
1370 // combined from the perigee
1371 std::unique_ptr<Trk::CaloExtension> caloExtension = m_caloExtTool->caloExtension(ctx, *tp);
1372 if (!caloExtension) {
1373 ATH_MSG_WARNING("Cannot get caloExtension.");
1374 return;
1375 }
1376 if (caloExtension->caloLayerIntersections().empty())
1377 ATH_MSG_DEBUG("Received a caloExtension object without track extrapolation");
1378
1379 cluster = m_cellCollector.collectCells(*caloExtension, caloDDMgr, *container, *clusterContainer);
1380 } else
1381 cluster = m_cellCollector.collectCells(*inputCaloExt, caloDDMgr, *container, *clusterContainer);
1382
1383 if (!cluster) {
1384 ATH_MSG_DEBUG("Failed to create cluster from ParticleCellAssociation");
1385 return;
1386 } else {
1387 ATH_MSG_DEBUG(" New cluster: eta " << cluster->eta() << " phi " << cluster->phi() << " cells " << cluster->size());
1388 }
1389
1390 // create element links
1391 ElementLink<xAOD::CaloClusterContainer> clusterLink(*clusterContainer, cluster->index(), ctx);
1392 muon.setClusterLink(clusterLink);
1393 const CaloNoise* caloNoise = nullptr;
1394 if (!m_caloNoiseKey.empty()) {
1396 caloNoise = noiseH.cptr();
1397 }
1398 // collect the core energy
1399 std::vector<float> etcore(4, 0);
1400 m_cellCollector.collectEtCore(*cluster, etcore, caloNoise, m_sigmaCaloNoiseCut);
1401
1402 acc_ET_Core(muon) = etcore[Rec::CaloCellCollector::ET_Core];
1403 acc_ET_EMCore(muon) = etcore[Rec::CaloCellCollector::ET_EMCore];
1404 acc_ET_TileCore(muon) = etcore[Rec::CaloCellCollector::ET_TileCore];
1405 acc_ET_HECCore(muon) = etcore[Rec::CaloCellCollector::ET_HECCore];
1406 if (m_caloNoiseKey.empty())
1407 ATH_MSG_DEBUG("NO Tool for calo noise,sigma: " << m_sigmaCaloNoiseCut);
1408 else
1409 ATH_MSG_DEBUG("sigma: " << m_sigmaCaloNoiseCut);
1410
1411 ATH_MSG_DEBUG("Etcore: tot/em/tile/hec "
1412 << etcore[Rec::CaloCellCollector::ET_Core] << "/" << etcore[Rec::CaloCellCollector::ET_EMCore] << "/"
1414 }
1415 void MuonCreatorTool::setP4(xAOD::Muon& muon, const xAOD::TrackParticle& tp) const { muon.setP4(tp.pt(), tp.eta(), tp.phi()); }
1416
1417} // namespace MuonCombined
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
Helper class to provide constant type-safe access to aux data.
DataVector adapter that acts like it holds const pointers.
Helper class to provide type-safe access to aux data.
static Double_t a
DataVector< MuonCombined::MuonCandidate > MuonCandidateCollection
This typedef represents a collection of MuonCandidate objects.
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
This class provides the client interface for accessing the detector description information common to...
class extending the basic Trk::EnergyLoss to describe the measured or parameterised muon energy loss ...
Definition CaloEnergy.h:28
CaloEnergy::EnergyLossType energyLossType(void) const
Accessor methods.
Definition CaloEnergy.h:162
double sigmaMinusDeltaEParam() const
get parametrised energy loss minus error
Definition CaloEnergy.h:140
double deltaEMeas() const
get measured energy loss
Definition CaloEnergy.h:127
double sigmaDeltaEMeas() const
get measured energy loss error
Definition CaloEnergy.h:130
double deltaEParam() const
get parametrised energy loss
Definition CaloEnergy.h:137
double sigmaPlusDeltaEParam() const
get parametrised energy loss plus error
Definition CaloEnergy.h:143
float fsrCandidateEnergy() const
FSR Candidate Energy.
Definition CaloEnergy.h:94
DataVector adapter that acts like it holds const pointers.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
ElementProxy back()
Access the last element in the collection as an lvalue.
const DV * asDataVector() const
Return a pointer to this object, as a const DataVector.
void assign(InputIterator first, InputIterator last)
Assign from iterators.
const_reverse_iterator rend() const noexcept
Return a const_reverse_iterator pointing at the beginning of the collection.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const PtrVector & stdcont() const
Return the underlying std::vector of the container.
const_reverse_iterator rbegin() const noexcept
Return a const_reverse_iterator pointing past the end of the collection.
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition DataVector.h:847
size_type size() const noexcept
Returns the number of elements in the collection.
TagBase implementation for a calo tag.
Definition CaloTag.h:17
TagBase implementation for a combined fit.
const MuonCandidate & muonCandidate() const
access to MuonCandidate
const xAOD::TrackParticle & indetTrackParticle() const
access TrackParticle
TagBase implementation for a combined fit.
TagBase implementation for a combined fit.
Definition MuGirlTag.h:23
const ElementLink< TrackCollection > & extrapolatedTrackLink() const
access extrapolated track element link
const std::vector< const Muon::MuonSegment * > & getSegments() const
returns the vector of associated muon segments
const ElementLink< xAOD::TrackParticleContainer > & muonSpectrometerTrackLink() const
access spectrometer track, always there
const Trk::Track * extrapolatedTrack() const
access extrapolated track, can be zero if back extrapolation failed
void setP4(xAOD::Muon &muon, const xAOD::TrackParticle &tp) const
ToolHandle< Trk::ITrackParticleCreatorTool > m_particleCreator
void addCaloTag(xAOD::Muon &muon, const CaloTag *tag) const
void addSegmentTag(const EventContext &ctx, xAOD::Muon &muon, const SegmentTag *tag, OutputData &outputData) const
ToolHandle< Trk::IParticleCaloExtensionTool > m_caloExtTool
ToolHandle< Trk::ITrackAmbiguityProcessorTool > m_ambiguityProcessor
void fillEnergyLossFromTrack(xAOD::Muon &muon, const std::vector< const Trk::TrackStateOnSurface * > *tsosVector) const
std::vector< std::unique_ptr< SG::AuxElement::Accessor< float > > > m_copyFloatSummaryAccessors
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
Gaudi::Property< bool > m_useCaloCells
ToolHandle< Rec::IMuonScatteringAngleSignificance > m_scatteringAngleTool
virtual void create(const EventContext &ctx, const MuonCandidateCollection *muonCandidates, const std::vector< const InDetCandidateToTagMap * > &tagMaps, OutputData &outputData) const override final
IMuonCreatorTool interface: build muons from ID and MS candidates.
SG::ReadHandleKey< CaloCellContainer > m_cellContainerName
ToolHandle< xAOD::IMuonDressingTool > m_muonDressingTool
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Gaudi::Property< bool > m_fillExtraELossInfo
std::vector< InDetCandidateTags > InDetCandidateTagsMap
void addMuonCandidate(const EventContext &ctx, const MuonCandidate &candidate, xAOD::Muon &muon, OutputData &outputData, const ElementLink< TrackCollection > &meLink=ElementLink< TrackCollection >()) const
add muon candidate info to a muon, if an updateExtrapolatedTrack is provided, the routine takes owner...
void addMuGirlLowBeta(const EventContext &ctx, xAOD::Muon &muon, const MuGirlLowBetaTag *tag, xAOD::SlowMuon *slowMuon, OutputData &outputData) const
ToolHandle< Trk::IPropagator > m_propagator
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
bool dressMuon(xAOD::Muon &muon) const
Gaudi::Property< float > m_sigmaCaloNoiseCut
ToolHandle< Rec::IMuonPrintingTool > m_muonPrinter
Gaudi::Property< std::vector< std::string > > m_copyCharSummaryKeys
ToolHandle< CP::IMuonSelectionTool > m_selectorTool
ToolHandle< Rec::IMuonMomentumBalanceSignificance > m_momentumBalanceTool
ElementLink< xAOD::TrackParticleContainer > createTrackParticleElementLink(const EventContext &ctx, const ElementLink< TrackCollection > &trackLink, xAOD::TrackParticleContainer &trackParticleContainer, TrackCollection *trackCollection=0) const
function creates an element link to a track particle from the track and the TrackParticle collection.
ToolHandle< Trk::ITrkMaterialProviderTool > m_caloMaterialProvider
void addEnergyLossToMuon(xAOD::Muon &muon) const
std::vector< std::unique_ptr< SG::AuxElement::Accessor< uint8_t > > > m_copyCharSummaryAccessors
ElementLink< xAOD::MuonSegmentContainer > createMuonSegmentElementLink(const EventContext &ctx, const Muon::MuonSegment *segLink, const OutputData &outData) const
void addCombinedFit(const EventContext &ctx, xAOD::Muon &muon, const CombinedFitTag *tag, OutputData &outputData) const
Gaudi::Property< std::vector< std::string > > m_copyFloatSummaryKeys
void selectStaus(InDetCandidateTagsMap &resolvedInDetCandidates, const std::vector< const InDetCandidateToTagMap * > &tagMaps) const
void resolveOverlaps(const EventContext &ctx, const MuonCandidateCollection *muonCandidates, const std::vector< const InDetCandidateToTagMap * > &tagMaps, InDetCandidateTagsMap &resolvedInDetCandidates, std::vector< const MuonCombined::MuonCandidate * > &resolvedMuonCandidates) const
void collectCells(const EventContext &ctx, xAOD::Muon &muon, xAOD::CaloClusterContainer *clusterContainer, const Trk::CaloExtension *inputCaloExt=nullptr) const
Gaudi::Property< bool > m_fillEnergyLossFromTrack
virtual StatusCode initialize() override final
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
Gaudi::Property< bool > m_addMDTExtrasMuGirlLowBeta
Gaudi::Property< bool > m_printSummary
ToolHandle< Rec::IMuonMeanMDTdADCFiller > m_meanMDTdADCTool
Gaudi::Property< bool > m_requireCaloDepositForSA
Gaudi::Property< bool > m_requireMSOEforSA
SG::ReadCondHandleKey< CaloNoise > m_caloNoiseKey
Gaudi::Property< bool > m_buildStauContainer
Rec::CaloCellCollector m_cellCollector
std::unique_ptr< Trk::Track > createDummyTrack(const EventContext &ctx, const std::vector< const Muon::MuonSegment * > &segments, const Trk::Track &indetTrack) const
void decorateDummyValues(const EventContext &ctx, xAOD::Muon &muon, OutputData &outputData) const
De^corated a bunch of dummy values to the muon to ensure data consistency in the xAOD.
void addMuGirl(const EventContext &ctx, xAOD::Muon &muon, const MuGirlTag *tag, OutputData &outputData) const
Gaudi::Property< bool > m_doSA
Gaudi::Property< bool > m_requireIDTracks
In case of running the muon reconstruction with LRT tracks this property removes the overlap of muons...
void addStatisticalCombination(const EventContext &ctx, xAOD::Muon &muon, const InDetCandidate *candidate, const StacoTag *tag, OutputData &outputData) const
ToolHandle< Rec::IMuonTrackQuery > m_trackQuery
ToolHandle< Trk::IExtendedTrackSummaryTool > m_trackSummaryTool
TagBase implementation for a segment tagger.
Definition SegmentTag.h:14
TagBase implementation for a combined fit.
Definition StacoTag.h:22
const MuonCandidate & muonCandidate() const
access to MuonCandidate
Definition StacoTag.cxx:27
base-class for combined reconstruction output Provides access to MuonType and Author
Definition TagBase.h:49
virtual const Trk::Track * primaryTrack() const
access to primary muon system track, zero if non available
Definition TagBase.h:86
virtual std::vector< const Muon::MuonSegment * > associatedSegments() const
access to associated segments, empty vector if non available
Definition TagBase.h:88
This is the common class for 3D segments used in the muon spectrometer.
lightweight return data-object for (mainly indet) scattering angle analysis by track query
double curvatureSignificance(void) const
ScatteringAngleSignificance inline accessor: significance of maximum curvature discontinuity.
double neighbourSignificance(void) const
ScatteringAngleSignificance inline accessor: maximum significance of neighbouring scatterers.
Helper class to provide type-safe access to aux data.
const_pointer_type cptr()
Tracking class to hold the extrapolation through calorimeter Layers Both the caloEntryLayerIntersecti...
This class describes energy loss material effects in the ATLAS tracking EDM.
Definition EnergyLoss.h:34
double sigmaDeltaE() const
returns the symmatric error
double deltaE() const
returns the
Class to represent and store fit qualities from track reconstruction in terms of and number of degre...
Definition FitQuality.h:97
magnetic field properties to steer the behavior of the extrapolation
represents the full description of deflection and e-loss of a track in material.
const EnergyLoss * energyLoss() const
returns the energy loss object.
This class is the pure abstract base class for all fittable tracking measurements.
Contains information about the 'fitter' of this track.
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
A summary of the information contained by a track.
int get(const SummaryType &type) const
returns the summary information for the passed SummaryType.
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
const TrackInfo & info() const
Returns a const ref to info of a const tracks.
const Perigee * perigeeParameters() const
return Perigee.
const Trk::TrackSummary * trackSummary() const
Returns a pointer to the const Trk::TrackSummary owned by this const track (could be nullptr).
const FitQuality * fitQuality() const
return a pointer to the fit quality const-overload
virtual double eta() const
The pseudorapidity ( ) of the particle.
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
virtual double phi() const
The azimuthal angle ( ) of the particle.
void setMuonLink(const ElementLink< MuonContainer > &muonLink)
Sets.
void setNRpcHits(int nRpcHits)
Sets.
void setNTileCells(int nTileCells)
Sets.
void setAnn(float ann)
Sets.
void setMdtInfo(float mdtBetaAvg, float mdtBetaRms, float mdtBetaChi2, int mdtBetaDof)
Sets.
void setBeta(float beta)
Sets.
void setBetaT(float betaT)
Sets.
void setRpcInfo(float rpcBetaAvg, float rpcBetaRms, float rpcBetaChi2, int rpcBetaDof)
Sets.
void setCaloInfo(float caloBetaAvg, float caloBetaRms, float caloBetaChi2, int caloBetaDof)
Sets.
void setTrackParameterCovarianceMatrix(unsigned int index, std::vector< float > &cov)
Set the cov matrix of the parameter at 'index', using a vector of floats.
void setTrackLink(const ElementLink< TrackCollection > &track)
Set the link to the original track.
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.
void setPatternRecognitionInfo(const std::bitset< xAOD::NumberOfTrackRecoInfo > &patternReco)
Method setting the pattern recognition algorithm, using a bitset.
std::vector< std::string > tags
Definition hcg.cxx:107
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
The MuonTagToSegMap is an auxillary construct that links the MuonSegments associated with a combined ...
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
@ anyDirection
@ NoField
Field is set to 0., 0., 0.,.
@ phi0
Definition ParamDefs.h:65
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ d0
Definition ParamDefs.h:63
@ z0
Definition ParamDefs.h:64
@ numberOfCscUnspoiltEtaHits
number of unspoilt CSC eta measurements (all CSC phi measurements are by definition spoilt).
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
SlowMuon_v1 SlowMuon
Reference the current persistent version:
Definition SlowMuon.h:13
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
Muon_v1 Muon
Reference the current persistent version:
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
@ STACO
Tracks produced by STACO.
unsigned int numRpcHitsInSeg
std::optional< StauMDTHitExtras > extraMDTHitInfo
MsgStream & msg
Definition testRead.cxx:32