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