ATLAS Offline Software
Loading...
Searching...
No Matches
FastRecoVisualizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
5
8
13
14#include "Acts/Utilities/Helpers.hpp"
15
16#include "TColor.h"
17
18namespace {
19 constexpr int truthColor = kOrange +2;
20 using SpacePointSet = std::unordered_set<const MuonR4::SpacePoint*>;
21
22 double inDegrees(double angle) {
23 return angle / Gaudi::Units::deg;
24 }
25}
26
27
28namespace MuonValR4 {
29 using namespace MuonR4;
30 using namespace SegmentFit;
31
33 if (m_canvasLimit > 0) {
34 m_clientToken.canvasLimit = m_canvasLimit;
35 m_clientToken.preFixName = m_canvasPrefix;
36 m_clientToken.saveSinglePlots = m_saveSinglePDFs;
37 m_clientToken.saveSummaryPlot = m_saveSummaryPDF;
38 m_clientToken.subDirectory = m_subDir;
39 ATH_CHECK(m_visualSvc.retrieve());
40 ATH_CHECK(m_visualSvc->registerClient(m_clientToken));
41 } else {
42 m_plotsDone = true;
43 }
44 ATH_CHECK(m_prepContainerKeys.initialize(!m_truthSegLinks.empty()));
46 ATH_MSG_INFO("Hits linked to the following segment decorations are considered as truth");
47 for (const std::string& decorName : m_truthSegLinks) {
48 ATH_MSG_INFO(" **** "<<decorName);
49 if (decorName.empty()) {
50 ATH_MSG_FATAL("Decoration must not be empty");
51 return StatusCode::FAILURE;
52 }
54 m_truthLinkDecorKeys.emplace_back(key, decorName);
55 m_truthLinkDecors.push_back(SegLinkDecor_t{decorName});
56 }
57 }
58 ATH_CHECK(m_truthLinkDecorKeys.initialize());
59 m_displayOnlyTruth.value() &= !m_truthLinkDecorKeys.empty();
60
61 ATH_CHECK(m_idHelperSvc.retrieve());
62 ATH_CHECK(m_geoCtxKey.initialize());
63 ATH_CHECK(detStore()->retrieve(m_detMgr));
65 ATH_MSG_ERROR("No bucket view enabled. Please enable at least one of the bucket views to visualize the buckets.");
66 return StatusCode::FAILURE;
67 }
69 ATH_MSG_ERROR("Multiple bucket views enabled. Please enable only one bucket view.");
70 return StatusCode::FAILURE;
71 }
72 return StatusCode::SUCCESS;
73 }
79 return std::find_if(m_truthLinkDecors.begin(), m_truthLinkDecors.end(),
80 [&hit](const SegLinkDecor_t& decor){
81 return !decor(hit).empty();
82 }) != m_truthLinkDecors.end();
83 }
84 FastRecoVisualizationTool::LabeledSegmentSet FastRecoVisualizationTool::getLabeledSegments(const std::vector<const MuonR4::SpacePoint*>& hits) const {
85 std::vector<const xAOD::UncalibratedMeasurement*> measurements{};
86 measurements.reserve(2* hits.size());
87 for (const SpacePoint* hit: hits) {
88 measurements.push_back(hit->primaryMeasurement());
89 if(hit->secondaryMeasurement()) {
90 measurements.push_back(hit->secondaryMeasurement());
91 }
92 }
93 return getLabeledSegments(measurements);
94 }
95 FastRecoVisualizationTool::LabeledSegmentSet FastRecoVisualizationTool::getLabeledSegments(const std::vector<const xAOD::UncalibratedMeasurement*>& hits) const {
96 LabeledSegmentSet truthSegs{};
97 for (const xAOD::UncalibratedMeasurement* hit : hits) {
98 for (const SegLinkDecor_t& decor: m_truthLinkDecors) {
99 for (const SegLink_t& link : decor(*hit)) {
100 truthSegs.insert(*link);
101 }
102 }
103 }
104 return truthSegs;
105 }
107 const std::string& extraLabel,
108 PatternHitVisualInfoVec&& patternVisualVec) const {
109 PrimitiveVec primitives{};
110 plotPatternBuckets(ctx, extraLabel, std::move(patternVisualVec), std::move(primitives));
111 }
113 const std::string& extraLabel,
114 PatternHitVisualInfoVec&& patternVisualVec,
115 PrimitiveVec&& primitives) const {
116 if (patternVisualVec.empty()) {
117 ATH_MSG_VERBOSE("No pattern visual info available. Do not create visualization.");
118 return;
119 }
121 for (PatternHitVisualInfo& patVisual : patternVisualVec) {
122 PrimitiveVec primitivesCopy {clone(primitives)};
123 plotPatternBuckets(ctx, extraLabel, std::move(patVisual), std::move(primitivesCopy));
124 }
125 }
127 const std::string& extraLabel,
128 PatternHitVisualInfo&& patternVisual) const {
129 PrimitiveVec primitives{};
130 plotPatternBuckets(ctx, extraLabel, std::move(patternVisual), std::move(primitives));
131 }
132
134 const std::string& extraLabel,
135 PatternHitVisualInfo&& patternVisual,
136 PrimitiveVec&& extraPaints) const {
137 for (const MuonR4::SpacePointBucket* bucket : patternVisual.parentBuckets) {
138 PatternHitVisualInfo patternVisualCopy {patternVisual};
139 PrimitiveVec extraPaintsCopy {clone(extraPaints)};
140 plotPatternBucket(ctx, extraLabel, *bucket, std::move(patternVisualCopy), std::move(extraPaintsCopy));
141 }
142 }
144 const std::string& extraLabel,
145 const MuonR4::SpacePointBucket& bucket,
146 PatternHitVisualInfo&& patternVisual,
147 PrimitiveVec&& extraPaints) const {
148 using PatternStatus = FastRecoVisualizationTool::PatternHitVisualInfo::PatternStatus;
149 using HitStatus = FastRecoVisualizationTool::PatternHitVisualInfo::HitStatus;
151 if (m_plotsDone) {
152 return;
153 }
155 LabeledSegmentSet truthSegs{getLabeledSegments(Acts::unpackConstSmartPointers(bucket))};
156 if (truthSegs.empty() && m_displayOnlyTruth) {
157 return;
158 }
160 PatternStatus patStatus{patternVisual.status};
161 if ((patStatus == PatternStatus::eSuccessful && !m_paintSuccessfullPatterns) ||
162 (patStatus == PatternStatus::eFailed && !m_paintFailedPatterns) ||
163 (patStatus == PatternStatus::eOverlap && !m_paintOverlapPatterns)) {
164 return;
165 }
167 std::vector<const MuonR4::SpacePoint*> patHitsInBucket{};
168 const MuonR4::GlobalPattern& pat {*patternVisual.patternCopy};
169 for (const Muon::MuonStationIndex::StIndex& station : pat.getStations()) {
170 for (const MuonR4::SpacePoint* hit : pat.hitsInStation(station)) {
171 if (std::ranges::find_if(bucket,
172 [hit](const std::shared_ptr<MuonR4::SpacePoint> sp) { return sp.get() == hit; }) != bucket.end()) {
173 patHitsInBucket.push_back(hit);
174 }
175 }
176 }
177 if (patHitsInBucket.empty() && m_displayOnlyWithPattern) {
178 return;
179 }
181 std::string nameTag = std::format("{}_{}_Bkt_{:d}", extraLabel, bucket.msSector()->identString(), bucket.bucketId());
182 auto canvas = m_visualSvc->prepareCanvas(ctx, m_clientToken, nameTag);
183 if (!canvas){
184 m_plotsDone = true;
185 return;
186 }
187 canvas->add(std::move(extraPaints));
188 const ActsTrk::GeometryContext* geoCtx{nullptr};
189 if (!SG::get(geoCtx, m_geoCtxKey, ctx).isSuccess()) {
190 throw std::runtime_error("Failed to retrieve GeometryContext from EventStore");
191 return;
192 }
195 const Amg::Transform3D& localToGlobalBucket{bucket.msSector()->localToGlobalTransform(*geoCtx)};
197 if (view == View::objViewZR && !bucket.msSector()->barrel()) {
198 view = View::objViewRZ;
199 }
200 switch (view) {
201 case View::objViewEta:
202 canvas->setAxisTitles("y [mm]", "z [mm]");
203 break;
204 case View::objViewPhi:
205 canvas->setAxisTitles("x [mm]", "z [mm]");
206 break;
207 case View::objViewZR:
208 canvas->setAxisTitles("z [mm]", "R [mm]");
209 break;
210 case View::objViewRZ:
211 canvas->setAxisTitles("R [mm]", "z [mm]");
212 break;
213 }
215 if (!drawHits(bucket, localToGlobalBucket, patHitsInBucket, *canvas, view)) {
216 return;
217 }
218
219 PrimitiveVec lines{};
220
222 drawSearchWindow(localToGlobalBucket, lines, patternVisual.thetaSearchMin, patternVisual.thetaSearchMax, *canvas, view);
223
225 for (const auto& sp : bucket) {
226 const MuonR4::SpacePoint* testHit {sp.get()};
228 if (patternVisual.hitLineInfo.find(testHit) == patternVisual.hitLineInfo.end()) {
229 continue;
230 }
232 const HitStatus hitStatus {std::ranges::find(patternVisual.discardedHits, testHit) != patternVisual.discardedHits.end() ? HitStatus::eDiscarded :
233 (std::ranges::find(patternVisual.replacedHits, testHit) != patternVisual.replacedHits.end() ? HitStatus::eReplaced : HitStatus::eKept)};
234
236 const auto& [lineSlope, deltaRWindow] = patternVisual.hitLineInfo.at(testHit);
237 drawLineResidual(*geoCtx, localToGlobalBucket, lines, patternVisual.seed, testHit, lineSlope, deltaRWindow, hitStatus, *canvas, view);
238 }
239
241 double yLegend{0.9};
242 auto printOnCanvas = [&lines, &yLegend](const std::string& text){
243 lines.push_back(drawLabel(text, 0.2, yLegend, 13));
244 yLegend-=0.03;
245 };
246
247 printOnCanvas(std::format("Seed hit: {}", m_idHelperSvc->toString(patternVisual.seed->identify())));
248 printOnCanvas(std::format("Chamber: {}", m_idHelperSvc->toStringChamber(bucket.front()->identify())));
249 printOnCanvas(std::format("nPrec: {:d}", pat.nPrecisionHits()));
250 printOnCanvas(std::format("nEtaNonPrec: {:d}", pat.nEtaNonPrecisionHits()));
251 printOnCanvas(std::format("nPhi: {:d}", pat.nPhiHits()));
252 printOnCanvas(std::format("theta: {:.2f}^{{#circ}}", inDegrees(pat.theta())));
253 printOnCanvas(std::format("phi: {:.2f}^{{#circ}}", inDegrees(pat.phi())));
254 printOnCanvas(std::format("TotalResidual: {:.2f}", pat.totalResidual()));
255 printOnCanvas(std::format("Status: {}", patStatus == PatternStatus::eSuccessful ? "Success" : (patStatus == PatternStatus::eFailed ? "Fail" : "Overlap")));
256 printOnCanvas(std::format("Sector: {:d}", pat.sector()));
257 printOnCanvas(std::format("OverlapSector: {:d}", pat.isSectorOverlap() ? pat.secondarySector() : -1));
258
260 bool drawnTrueLabel{true};
261 for (const xAOD::MuonSegment* segment : truthSegs) {
262 drawSegment(*segment, localToGlobalBucket, lines, drawnTrueLabel, *canvas, view);
263 paintSimHits(*geoCtx, localToGlobalBucket, *segment, lines, view);
264 }
265 canvas->add(std::move(lines));
266
267 std::string legendLabel = std::format("Event: {:}, chamber : {:}, #{:}-view ({:})",
268 ctx.eventID().event_number(),
269 bucket.msSector()->identString(),
270 view ==View::objViewEta ? "eta" : (view ==View::objViewPhi ? "phi" : (view == View::objViewZR ? "ZR" : "RZ")),
271 nameTag);
272 canvas->add(drawLabel(legendLabel, 0.15, 0.96));
273 }
275 PrimitiveVec& outputContainer,
276 const double thetaMin,
277 const double thetaMax,
278 const Canvas_t& canvas,
279 const View view) const {
281 if (view == View::objViewPhi) {
282 return;
283 }
284 auto addSearchWindowLine = [&outputContainer, &localToGlobalBucket, &view, &canvas, this](const double globLineTheta){
285 constexpr double smallAngle {1e-3};
286 if (std::abs(globLineTheta) < smallAngle || std::abs(globLineTheta - M_PI) < smallAngle) {
288 throw std::runtime_error("Unexpected horizontal pattern search line in global frame. Cannot draw search window.");
289 return;
290 }
291 Amg::Vector3D lineDirection{};
292 Amg::Vector3D linePosition{};
293 double lowEnd{};
294 double upEnd{};
295 if (view == View::objViewZR || view == View::objViewRZ) {
297 lineDirection = Acts::makeDirectionFromAxisTangents(0., tan(globLineTheta));
298 linePosition = Amg::Vector3D::Zero();
299 lowEnd = view == View::objViewZR ? canvas.corner(Edges::yLow) : canvas.corner(Edges::xLow);
300 upEnd = view == View::objViewZR ? canvas.corner(Edges::yHigh) : canvas.corner(Edges::xHigh);
301 } else {
303 const double globLinePhi {localToGlobalBucket.translation().phi()};
304 const Amg::Vector3D globLineDir {Acts::makeDirectionFromPhiTheta(globLinePhi,globLineTheta)};
305 lineDirection = localToGlobalBucket.inverse().linear() * globLineDir;
306 linePosition = localToGlobalBucket.inverse() * Amg::Vector3D::Zero();
307 lowEnd = canvas.corner(Edges::yLow);
308 upEnd = canvas.corner(Edges::yHigh);
309 }
310 outputContainer.emplace_back(drawLine(lineDirection, linePosition,
311 lowEnd, upEnd, kOrange, kDashed, view));
312 };
313 addSearchWindowLine(thetaMin);
314 addSearchWindowLine(thetaMax);
315 }
317 const Amg::Transform3D& localToGlobalBucket,
318 PrimitiveVec& outputContainer,
319 const MuonR4::SpacePoint* seed,
320 const MuonR4::SpacePoint* testHit,
321 const double lineSlope,
322 const double Rwindow,
323 const PatternHitVisualInfo::HitStatus status,
324 const Canvas_t& canvas,
325 const View view) const {
326 using HitStatus = PatternHitVisualInfo::HitStatus;
328 if (view == View::objViewPhi) {
329 return;
330 }
331 if (std::abs(lineSlope) < std::numeric_limits<double>::epsilon()) {
333 return;
334 }
335 auto color {status == HitStatus::eKept ? kGreen : (status == HitStatus::eReplaced ? kPink : kGray)};
336 if (view == View::objViewZR || view == View::objViewRZ) {
338 const Amg::Vector3D lineDir {Acts::makeDirectionFromAxisTangents(0., lineSlope)};
339 const Amg::Vector3D seedGlobalPos {seed->msSector()->localToGlobalTransform(gctx) * seed->localPosition()};
340 const Amg::Vector3D linePos {seedGlobalPos.perp()* Amg::Vector3D::UnitY() + seedGlobalPos.z() * Amg::Vector3D::UnitZ()};
342 const double seedGlobalR {seedGlobalPos.perp()};
343 const double testGlobalR {(localToGlobalBucket * testHit->localPosition()).perp()};
344 const double testGlobalZ {(localToGlobalBucket * testHit->localPosition()).z()};
345 const double lineIntercept {linePos.y() - lineSlope * linePos.z()};
346 const double line2WindowInters {lineSlope*testGlobalZ + lineIntercept};
347 double lowLimit{};
348 double upLimit{};
349 if (seedGlobalR < testGlobalR) {
350 lowLimit = (seed->msSector() == testHit->msSector() ?
351 seedGlobalR : (view == View::objViewZR ? canvas.corner(Edges::yLow) : canvas.corner(Edges::xLow)));
352 upLimit = line2WindowInters;
353 } else {
354 upLimit = (seed->msSector() == testHit->msSector() ?
355 seedGlobalR : (view == View::objViewZR ? canvas.corner(Edges::yHigh) : canvas.corner(Edges::xHigh)));
356 lowLimit = line2WindowInters;
357 }
358 outputContainer.emplace_back(drawLine(lineDir, linePos,
359 lowLimit, upLimit, color, kDashed, view));
360
362 const Amg::Vector3D barLineDir {Amg::Vector3D::UnitY()};
363 const Amg::Vector3D barLinePos {testGlobalZ* Amg::Vector3D::UnitZ()};
364 lowLimit = testGlobalR - Rwindow;
365 upLimit = testGlobalR + Rwindow;
366 outputContainer.emplace_back(drawLine(barLineDir, barLinePos,
367 lowLimit, upLimit, color, kDotted, view));
368 } else {
370 const double globLineTheta { lineSlope > 0 ? atan(lineSlope) : atan(lineSlope) + M_PI };
371 const double globLinePhi {localToGlobalBucket.translation().phi()};
372 const Amg::Vector3D globLineDir {Acts::makeDirectionFromPhiTheta(globLinePhi,globLineTheta)};
373 const Amg::Vector3D locLineDir {localToGlobalBucket.inverse().linear() * globLineDir};
375 const Amg::Vector3D seedGlobalPos {seed->msSector()->localToGlobalTransform(gctx) * seed->localPosition()};
376 const Amg::Vector3D seedLocalPos {localToGlobalBucket.inverse() * seedGlobalPos};
378 const double& testLocalZ {testHit->localPosition().z()};
379 const double& testLocalY {testHit->localPosition().y()};
380 const double testGlobalR {(localToGlobalBucket * testHit->localPosition()).perp()};
381 double seedGlobalR {seedGlobalPos.perp()};
382 const bool isBarrel {seed->msSector()->barrel()};
383 const double line2WindowInters {isBarrel ? Acts::detail::LineHelper::lineIntersect<3>(seedLocalPos, locLineDir, testLocalY* Amg::Vector3D::UnitY(), Amg::Vector3D::UnitZ()).position().z()
384 : Acts::detail::LineHelper::lineIntersect<3>(seedLocalPos, locLineDir, testLocalZ* Amg::Vector3D::UnitZ(), Amg::Vector3D::UnitY()).position().z()};
385 double lowLimit{};
386 double upLimit{};
387 if (seedGlobalR < testGlobalR) {
388 lowLimit = (seed->msSector() == testHit->msSector() ? seedLocalPos.z() : canvas.corner(Edges::yLow));
389 upLimit = line2WindowInters;
390 } else {
391 upLimit = (seed->msSector() == testHit->msSector() ? seedLocalPos.z() : canvas.corner(Edges::yHigh));
392 lowLimit = line2WindowInters;
393 }
394 outputContainer.emplace_back(drawLine(locLineDir, seedLocalPos,
395 lowLimit, upLimit, color, kDashed, view));
396
398 const Amg::Vector3D barLineDir {isBarrel ? Amg::Vector3D::UnitZ() : Amg::Vector3D::UnitY()};
399 const Amg::Vector3D barLinePos {isBarrel ? testLocalY* Amg::Vector3D::UnitY() : testLocalZ* Amg::Vector3D::UnitZ()};
400 lowLimit = isBarrel ? testLocalZ - Rwindow : testLocalY - Rwindow;
401 upLimit = isBarrel ? testLocalZ + Rwindow : testLocalY + Rwindow;
402 outputContainer.emplace_back(drawLine(barLineDir, barLinePos,
403 lowLimit, upLimit, color, kDotted, view));
404 }
405 }
407 const Amg::Transform3D& localToGlobalBucket,
408 PrimitiveVec& outputContainer,
409 bool& drawnTrueLabel,
410 const Canvas_t& canvas,
411 const View view) const {
413 return;
414 }
415 auto [linePos, lineDir] = makeLine(localSegmentPars(segment));
416 double lowEnd{canvas.corner(Edges::yLow)};
417 double highEnd{canvas.corner(Edges::yHigh)};
418 if (view == View::objViewZR || view == View::objViewRZ){
420 const Amg::Vector3D globDir {localToGlobalBucket.linear() * lineDir};
421 const Amg::Vector3D globPos {localToGlobalBucket * linePos};
423 const double slopeRZ {(globPos.x()*globDir.x() + globPos.y()*globDir.y()) / (globPos.perp()*globDir.z())};
424 lineDir = Acts::makeDirectionFromAxisTangents(0., slopeRZ);
425 linePos = globPos.perp()* Amg::Vector3D::UnitY() + globPos.z() * Amg::Vector3D::UnitZ();
426 if (view == View::objViewRZ) {
427 lowEnd = canvas.corner(Edges::xLow);
428 highEnd = canvas.corner(Edges::xHigh);
429 }
430 }
431 outputContainer.emplace_back(drawLine(lineDir, linePos, lowEnd, highEnd,
432 truthColor, kDotted, view));
433 if (!drawnTrueLabel) {
434 outputContainer.emplace_back(drawLabel(std::format("true parameters: {:}",makeLabel(localSegmentPars(segment))),0.2, 0.89));
435 drawnTrueLabel = true;
436 }
437 }
439 const Amg::Transform3D& localToGlobalBucket,
440 const xAOD::MuonSegment& truthSeg,
441 PrimitiveVec& outputContainer,
442 const View view) const {
443 if (!m_paintTruthHits) {
444 return;
445 }
446 auto truthHits = getMatchingSimHits(truthSeg);
447 for (const xAOD::MuonSimHit* simHit : truthHits) {
448 const MuonGMR4::MuonReadoutElement* re = m_detMgr->getReadoutElement(simHit->identify());
449 const IdentifierHash hash = re->detectorType() == ActsTrk::DetectorType::Mdt ?
450 re->measurementHash(simHit->identify()) :
451 re->layerHash(simHit->identify());
452 const Amg::Transform3D trf = re->msSector()->globalToLocalTransform(gctx) *
453 re->localToGlobalTransform(gctx, hash);
454 const Amg::Vector3D locPos = trf * xAOD::toEigen(simHit->localPosition());
455 const Amg::Vector3D locDir = trf.linear() * xAOD::toEigen(simHit->localDirection());
456 if (view == View::objViewEta || view == View::objViewPhi){
457 outputContainer.emplace_back(drawArrow(locPos, locDir, truthColor, kDashed, static_cast<int>(view)));
458 } else {
459 constexpr double arrowLength = 2.*Gaudi::Units::cm;
461 const Amg::Vector3D globDir {localToGlobalBucket.linear() * locDir};
462 const Amg::Vector3D globPos {localToGlobalBucket * locPos};
463 const Amg::Vector3D end = globPos + (arrowLength / std::hypot(globDir.z(),globDir.perp()) ) * globDir;
464 auto arrow = view == View::objViewZR ? std::make_unique<TArrow>(globPos.z(), globPos.perp(), end.z(), end.perp(),0.01) :
465 std::make_unique<TArrow>(globPos.perp(), globPos.z(), end.perp(), end.z(),0.01);
466 arrow->SetLineColor(truthColor);
467 arrow->SetLineWidth(2);
468 arrow->SetLineStyle(kDashed);
469 outputContainer.emplace_back(std::move(arrow));
470 }
471 }
472 }
473 template<class SpacePointType>
474 const SpacePoint*
475 FastRecoVisualizationTool::drawHit(const SpacePointType& hit,
476 const Amg::Transform3D& localToGlobalBucket,
477 Canvas_t& canvas,
478 const View view,
479 unsigned int fillStyle) const {
480
482 const bool isEtaView {view == View::objViewEta || view == View::objViewRZ || view == View::objViewZR};
483 if ((isEtaView && !hit.measuresEta()) || (view == View::objViewPhi && !hit.measuresPhi())) {
484 return nullptr;
485 }
486 const Amg::Vector3D& localPos {hit.localPosition()};
487 const Amg::Vector3D globalPos {localToGlobalBucket * localPos};
488 const auto expand = [&canvas, &hit]( double centerX, double centerY) {
489 canvas.expandPad(centerX- hit.driftRadius(), centerY - hit.driftRadius());
490 canvas.expandPad(centerX+ hit.driftRadius(), centerY + hit.driftRadius());
491 };
492 if (hit.type() != xAOD::UncalibMeasType::Other) {
493 if (view == View::objViewEta || view == View::objViewPhi) {
494 expand(localPos[static_cast<int>(view)], localPos.z());
495 } else if (view == View::objViewZR) {
496 expand(globalPos.z(), globalPos.perp());
497 } else if (view == View::objViewRZ) {
498 expand(globalPos.perp(), globalPos.z());
499 }
500 }
501 const SpacePoint* underlyingSp{nullptr};
503 constexpr int invalidCalibFill = 3305;
504 if constexpr (std::is_same_v<SpacePointType, SpacePoint>) {
505 underlyingSp = &hit;
507 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit.primaryMeasurement());
508 if (dc->status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
509 fillStyle = invalidCalibFill;
510 }
511 }
512 } else if constexpr(std::is_same_v<SpacePointType, CalibratedSpacePoint>) {
513 underlyingSp = hit.spacePoint();
514 if (hit.fitState() == CalibratedSpacePoint::State::Valid) {
515 fillStyle = fullFilling;
516 } else if (hit.fitState() == CalibratedSpacePoint::State::FailedCalib) {
517 fillStyle = invalidCalibFill;
518 } else {
519 fillStyle = hatchedFilling;
520 }
521 }
522 const Amg::Vector3D posInCanvas = [view, localPos, globalPos]() -> Amg::Vector3D{
523 switch (view) {
524 case View::objViewEta:
525 case View::objViewPhi:
526 return localPos;
527 case View::objViewZR:
528 return globalPos.z()* Amg::Vector3D::UnitY() + globalPos.perp() * Amg::Vector3D::UnitZ();
529 case View::objViewRZ:
530 return globalPos.z()* Amg::Vector3D::UnitZ() + globalPos.perp() * Amg::Vector3D::UnitY();
531 }
532 return Amg::Vector3D::Zero();
533 }();
534 const int covIdx {view == View::objViewPhi ? static_cast<int>(View::objViewPhi) : static_cast<int>(View::objViewEta)};
535 switch(hit.type()) {
537 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(underlyingSp->primaryMeasurement());
538 canvas.add(drawDriftCircle(posInCanvas, dc->readoutElement()->innerTubeRadius(),
539 kBlack, hollowFilling));
540
541 const int circColor = isLabeled(*dc) ? truthColor : kBlue;
542 canvas.add(drawDriftCircle(posInCanvas, hit.driftRadius(), circColor, fillStyle));
543 break;
545 const auto* meas{static_cast<const xAOD::RpcMeasurement*>(underlyingSp->primaryMeasurement())};
546 const int boxColor = isLabeled(*meas) ? truthColor : kGreen +2;
547 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->covariance()[covIdx]);
548 canvas.add(drawBox(posInCanvas, boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
549 boxColor, fillStyle, covIdx));
550 break;
552 const auto* meas{static_cast<const xAOD::TgcStrip*>(underlyingSp->primaryMeasurement())};
553 const int boxColor = isLabeled(*meas) ? truthColor : kCyan + 2;
554 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->covariance()[covIdx]);
555 canvas.add(drawBox(posInCanvas, boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
556 boxColor, fillStyle, covIdx));
557 break;
559 const int boxColor = isLabeled(*underlyingSp->primaryMeasurement()) ? truthColor : kAquamarine;
560 const double boxWidth = 5*Gaudi::Units::mm;
561 canvas.add(drawBox(posInCanvas, boxWidth, 10.*Gaudi::Units::mm, boxColor, fillStyle, covIdx));
562 break;
564 break;
566 const int boxColor = isLabeled(*underlyingSp->primaryMeasurement()) ? truthColor : kTeal;
567 const double boxWidth = 5*Gaudi::Units::mm;
568 canvas.add(drawBox(posInCanvas, boxWidth, 10.*Gaudi::Units::mm, boxColor, fillStyle, covIdx));
569 break;
570 } default: {
571 ATH_MSG_WARNING("Please implement proper drawings of the new small wheel.. "<<__FILE__<<":"<<__LINE__);
572 break;
573 }
574 }
575 return underlyingSp;
576 }
577
578 template<class SpacePointType>
580 const Amg::Transform3D& localToGlobalBucket,
581 const std::vector<SpacePointType>& hitsToDraw,
582 Canvas_t& canvas,
583 const View view) const {
584
585 SpacePointSet drawnPoints{};
586 for (const SpacePointType& hit : hitsToDraw) {
587 drawnPoints.insert(drawHit(*hit, localToGlobalBucket, canvas, view, fullFilling));
588 }
589 for (const SpacePointBucket::value_type& hit : bucket) {
590 // Don't redraw the other points
591 if (drawnPoints.count(hit.get())) {
592 continue;
593 }
594 drawHit(*hit, localToGlobalBucket, canvas, view, hollowFilling);
595 }
596 return drawnPoints.size() - drawnPoints.count(nullptr) > 1;
597 }
598 std::unique_ptr<TLine> FastRecoVisualizationTool::drawLine(const Amg::Vector3D& lineDirection,
599 const Amg::Vector3D& linePoint,
600 const double lowEnd,
601 const double highEnd,
602 const int color,
603 const int lineStyle,
604 const View view) const {
606 using ParamDefs = MuonR4::SpacePoint::SeedingAux::FitParIndex;
607 auto makeLine = [](const double x1, const double y1, const double x2, const double y2, const int color, const int style){
608 auto line = std::make_unique<TLine>(x1, y1, x2, y2);
609 line->SetLineColor(color);
610 line->SetLineWidth(2);
611 line->SetLineStyle(style);
612 return line;
613 };
614
615 if (view == View::objViewEta || view == View::objViewPhi){
617 if (std::abs(lineDirection.z()) < std::numeric_limits<double>::epsilon()) {
619 return makeLine(lowEnd, linePoint.z(), highEnd, linePoint.z(), color, lineStyle);
620 } else {
621 return MuonValR4::drawLine(linePoint + Amg::intersect<3>(linePoint,lineDirection,Amg::Vector3D::UnitZ(), lowEnd).value_or(0.)* lineDirection,
622 linePoint + Amg::intersect<3>(linePoint,lineDirection,Amg::Vector3D::UnitZ(), highEnd).value_or(0.)* lineDirection,
623 color, lineStyle, static_cast<int>(view));
624 }
625 } else {
627 if (std::abs(lineDirection.y()) < std::numeric_limits<double>::epsilon()) {
629 if (view == View::objViewZR) {
631 return makeLine(lowEnd, linePoint.y(), highEnd, linePoint.y(), color, lineStyle);
632 } else {
634 return makeLine(linePoint.y(), lowEnd, linePoint.y(), highEnd, color, lineStyle);
635 }
636 } else if (std::abs(lineDirection.z()) < std::numeric_limits<double>::epsilon()) {
638 if (view == View::objViewZR) {
640 return makeLine(linePoint.z(), lowEnd, linePoint.z(), highEnd, color, lineStyle);
641 } else {
643 return makeLine(lowEnd, linePoint.z(), highEnd, linePoint.z(), color, lineStyle);
644 }
645 } else {
646 const double slope {lineDirection.y() / lineDirection.z()};
647 const double intercept {linePoint.y() - slope * linePoint.z()};
648 const double Zlow {(lowEnd - intercept) / slope};
649 const double Zhigh {(highEnd - intercept) / slope};
650 if (view == View::objViewZR) {
652 return makeLine(Zlow, lowEnd, Zhigh, highEnd, color, lineStyle);
653 } else {
655 return makeLine(lowEnd, Zlow, highEnd, Zhigh, color, lineStyle);
656 }
657 }
658 }
659 }
660}
const boost::regex re(r_e)
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
static Double_t sp
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
This is a "hash" representation of an Identifier.
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
bool barrel() const
Returns whether the sector is placed in the barrel.
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
std::string identString() const
Returns a string encoding the chamber index & the sector of the MS sector.
Data class to represent an eta maximum in hough space.
: The muon space point bucket represents a collection of points that will bre processed together in t...
const MuonGMR4::SpectrometerSector * msSector() const
returns th associated muonChamber
unsigned int bucketId() const
Returns the Identifier in the context of the MuonChamber.
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
const xAOD::UncalibratedMeasurement * secondaryMeasurement() const
const Cov_t & covariance() const
Returns the covariance array.
const xAOD::UncalibratedMeasurement * primaryMeasurement() const
Gaudi::Property< std::set< std::string > > m_truthSegLinks
List of truth segment links to fetch.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Service Handle to the IMuonIdHelperSvc.
virtual StatusCode initialize() override final
std::unique_ptr< TLine > drawLine(const Amg::Vector3D &lineDirection, const Amg::Vector3D &linePoint, const double lowEnd, const double highEnd, const int color=kRed+1, const int lineStyle=kDashed, const View view=View::objViewEta) const
Draws a line given the parameters of the line in the local frame for Eta and Phi views and in the R-Z...
IRootVisualizationService::ClientToken m_clientToken
Token to present to the visualization service such that the display froms this tool are grouped toget...
BooleanProperty m_paintSuccessfullPatterns
Switch to visualize successfull patterns.
BooleanProperty m_paintOverlapPatterns
Switch to visualize overlap patterns.
const MuonR4::SpacePoint * drawHit(const SpacePointType &hit, const Amg::Transform3D &localToGlobalBucket, Canvas_t &canvas, const View view, unsigned int fillStyle) const
Converts a Hit into a particular TBox/ TEllipse for drawing.
SG::ReadDecorHandleKeyArray< xAOD::UncalibratedMeasurementContainer > m_truthLinkDecorKeys
Declaration of the dependency on the decorations.
virtual bool isLabeled(const MuonR4::SpacePoint &hit) const override final
Fetches all labeled (e.g.
void paintSimHits(const ActsTrk::GeometryContext &gctx, const Amg::Transform3D &localToGlobalBucket, const xAOD::MuonSegment &truthSeg, PrimitiveVec &outputContainer, const View view) const
Paints the truth sim hits associated with the segment.
void drawSearchWindow(const Amg::Transform3D &localToGlobalBucket, PrimitiveVec &outputContainer, const double thetaMin, const double thetaMax, const Canvas_t &canvas, const View view) const
Draw the search window lines in the local frame expressed by the Transform3D for eta views and in the...
BooleanProperty m_displayOnlyWithPattern
Toggle to print pattern buckets only if they contain pattern hits.
BooleanProperty m_saveSinglePDFs
If set to true each canvas is saved into a dedicated pdf file.
BooleanProperty m_paintFailedPatterns
Switch to visualize failed patterns.
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
Geometry context key to retrieve the alignment.
void plotPatternBucket(const EventContext &ctx, const std::string &extraLabel, const MuonR4::SpacePointBucket &bucket, PatternHitVisualInfo &&patternVisual, PrimitiveVec &&extraPaints) const
Plot a single pattern bucket.
StringProperty m_canvasPrefix
Prefix of the individual canvas file names <MANDATORY>
BooleanProperty m_paintTruthSegment
Switch to visualize the truth segment.
BooleanProperty m_saveSummaryPDF
If set to true a summary Canvas is created.
void drawLineResidual(const ActsTrk::GeometryContext &gctx, const Amg::Transform3D &localToGlobalBucket, PrimitiveVec &outputContainer, const MuonR4::SpacePoint *seed, const MuonR4::SpacePoint *testHit, const double lineSlope, const double Rwindow, const PatternHitVisualInfo::HitStatus status, const Canvas_t &canvas, const View view) const
Draw the pattern line and acceptance window for the testHit used during pattern building in the local...
ElementLink< xAOD::MuonSegmentContainer > SegLink_t
ServiceHandle< IRootVisualizationService > m_visualSvc
Service handle of the visualization service.
BooleanProperty m_doPhiBucketViews
Switch to visualize the phi view of the bucket event.
BooleanProperty m_displayOnlyTruth
Toggle to print pattern buckets only if they contain truth hits.
SG::ReadHandleKeyArray< xAOD::UncalibratedMeasurementContainer > m_prepContainerKeys
Declare dependency on the prep data containers.
SG::AuxElement::ConstAccessor< SegLinkVec_t > SegLinkDecor_t
BooleanProperty m_doEtaBucketViews
Switch to visualize the eta view of the bucket event.
const MuonGMR4::MuonDetectorManager * m_detMgr
pointer to the Detector manager
void drawSegment(const xAOD::MuonSegment &segment, const Amg::Transform3D &localToGlobalBucket, PrimitiveVec &outputContainer, bool &drawnTrueLabel, const Canvas_t &canvas, const View view) const
Draw a segment on the canvas.
virtual LabeledSegmentSet getLabeledSegments(const std::vector< const MuonR4::SpacePoint * > &hits) const override final
Returns whether the hit has been used on the labeled segments we refer to (e.g.
BooleanProperty m_paintTruthHits
Switch to visualize the truth hits.
virtual void plotPatternBuckets(const EventContext &ctx, const std::string &extraLabel, PatternHitVisualInfoVec &&patternVisualVec) const override final
StringProperty m_subDir
Define the subdirectory in which the plots shall be saved.
IRootVisualizationService::ICanvasObject Canvas_t
std::vector< SegLinkDecor_t > m_truthLinkDecors
bool drawHits(const MuonR4::SpacePointBucket &bucket, const Amg::Transform3D &localToGlobalBucket, const std::vector< SpacePointType > &hitsToDraw, Canvas_t &canvasDim, const View view) const
Translates the Spacepoint information into TObjects that are dawn on the canvas & evaluates the size ...
UnsignedIntegerProperty m_canvasLimit
Maximum canvases to draw.
Property holding a SG store/key/clid from which a ReadHandle is made.
@ Mdt
MuonSpectrometer.
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
SeedingAux::FitParIndex ParamDefs
Use the same parameter indices as used by the CompSpacePointAuxiliaries.
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
std::pair< Amg::Vector3D, Amg::Vector3D > makeLine(const Parameters &pars)
Returns the parsed parameters into an Eigen line parametrization.
Acts::Experimental::CompositeSpacePointLineFitter::ParamVec_t Parameters
std::string makeLabel(const Parameters &pars)
Dumps the parameters into a string in the form of TLatex.
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
MuonValR4::IPatternVisualizationTool::PrimitiveVec PrimitiveVec
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
PatternVisualizationTool::LabeledSegmentSet LabeledSegmentSet
constexpr int hollowFilling
Filling codes for hollow / fullFilling / hatched filling.
std::unique_ptr< TLine > drawLine(const MuonR4::SegmentFit::Parameters &pars, const double lowEnd, const double highEnd, const int color=kRed+1, const int lineStyle=kDashed, const int view=objViewEta)
Draws a line from the segment fit parameters.
constexpr int hatchedFilling
std::unique_ptr< TLatex > drawLabel(const std::string &text, const double xPos, const double yPos, const double textSize=18, const bool useNDC=true, const int color=kBlack)
Create a TLatex label,.
std::vector< std::unique_ptr< TObject > > clone(const std::vector< std::unique_ptr< TObject > > &cloneMe)
std::unique_ptr< TEllipse > drawDriftCircle(const Amg::Vector3D &center, const double radius, const int color=kViolet, const int fillStyle=hollowFilling)
Create a TEllipse for drawing a drift circle.
constexpr int fullFilling
std::unique_ptr< TArrow > drawArrow(const Amg::Vector3D &start, const Amg::Vector3D &dir, const int color=kRed+1, const int lineStyle=kDashed, const int view=objViewEta)
Draw an arror between two endpoints in the y-z or the x-z plane.
std::unique_ptr< TBox > drawBox(const Amg::Vector3D &boxCenter, const double boxWidth, const double boxHeight, const int color=kGreen+2, const int fillStyle=hollowFilling, const int view=objViewEta)
Creates a box for drawing, e.g strip measurements.
StIndex
enum to classify the different station layers in the muon spectrometer
bool isBarrel(const ChIndex index)
Returns true if the chamber index points to a barrel chamber.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
std::vector< const SpacePoint * > SpacePointSet
vector of space points
Definition FitterTypes.h:38
MdtDriftCircle_v1 MdtDriftCircle
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
TgcStrip_v1 TgcStrip
Definition TgcStripFwd.h:9
RpcMeasurement_v1 RpcMeasurement
MuonSegment_v1 MuonSegment
Reference the current persistent version:
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.