20#include "Acts/Utilities/Helpers.hpp"
21#include "Acts/Surfaces/RectangleBounds.hpp"
22#include "Acts/Surfaces/TrapezoidBounds.hpp"
23#include "Acts/Surfaces/PlaneSurface.hpp"
24#include "Acts/Surfaces/StrawSurface.hpp"
25#include "Acts/Visualization/GeometryView3D.hpp"
40 constexpr int truthColor = kOrange +2;
41 constexpr int parLineColor = kRed;
42 using SpacePointSet = std::unordered_set<const MuonR4::SpacePoint*>;
48 using namespace MuonR4;
66 ATH_MSG_INFO(
"Hits linked to the following segment decorations are considered as truth");
69 if (decorName.empty()) {
71 return StatusCode::FAILURE;
84 return StatusCode::SUCCESS;
93 return !decor(hit).empty();
98 std::vector<const xAOD::UncalibratedMeasurement*> measurements{};
99 measurements.reserve(2* hits.size());
101 measurements.push_back(hit->primaryMeasurement());
102 if(hit->secondaryMeasurement()) {
103 measurements.push_back(hit->secondaryMeasurement());
112 for (
const SegLink_t& link : decor(*hit)) {
113 truthSegs.insert(*link);
121 const Acts::HoughTransformUtils::HoughAxisRanges& axisRanges,
122 const MaximumVec& maxima,
123 const std::string& extraLabel)
const {
129 const Acts::HoughTransformUtils::HoughAxisRanges& axisRanges,
130 const MaximumVec& maxima,
131 const std::string& extraLabel,
141 if (accumulator.getNonEmptyBins().empty()) {
146 auto accHisto = std::make_unique<TH2F>(
"AccumulatorHisto",
"histo",
147 accumulator.nBinsX(), axisRanges.xMin, axisRanges.xMax,
148 accumulator.nBinsY(), axisRanges.yMin, axisRanges.yMax);
149 accHisto->SetDirectory(
nullptr);
151 std::vector<const SpacePoint*> spacePointsInAcc{};
152 for (
const std::size_t
bin : accumulator.getNonEmptyBins()) {
153 const auto [xBin, yBin] = accumulator.axisBins(
bin);
154 auto hitIds = accumulator.hitIds(xBin, yBin);
155 spacePointsInAcc.insert(spacePointsInAcc.end(),hitIds.begin(), hitIds.end());
156 accHisto->SetBinContent(xBin+1, yBin+1, accumulator.nHits(
bin));
161 ATH_MSG_VERBOSE(
"visualizeAccumulator skipped: no truth segments found and displayOnlyTruth=true");
172 const double maxBins = std::max(accumulator.nBinsX(), accumulator.nBinsY());
173 double markerTextSize = 0.035;
175 markerTextSize *= 25. / std::max(25., maxBins);
177 markerTextSize = std::clamp(markerTextSize, 0.006, 0.035);
178 accHisto->SetMarkerSize(markerTextSize);
179 accHisto->SetMarkerColor(kBlack);
180 accHisto->SetMinimum(0.);
182 canvas->expandPad(axisRanges.xMin, axisRanges.yMin);
183 canvas->expandPad(axisRanges.xMax, axisRanges.yMax);
184 canvas->setAxisTitles(std::format(
"tan#{}",
m_accumlIsEta ?
"beta" :
"#alpha"),
186 canvas->add(std::move(accHisto),
"HIST SAME");
190 const double binLabelPx = std::clamp(1.2 * 500. / maxBins, 7.0, 18.0);
191 for (
const std::size_t
bin : accumulator.getNonEmptyBins()) {
192 const auto [xBin, yBin] = accumulator.axisBins(
bin);
193 const double xCenter = axisRanges.xMin + (xBin + 0.5) * (axisRanges.xMax - axisRanges.xMin) / accumulator.nBinsX();
194 const double yCenter = axisRanges.yMin + (yBin + 0.5) * (axisRanges.yMax - axisRanges.yMin) / accumulator.nBinsY();
197 std::string binLabel = std::format(
"{:0}",
int(accumulator.nHits(
bin)));
199 auto binTxt =
drawLabel(binLabel, xCenter, yCenter, binLabelPx,
false, kBlack);
200 binTxt->SetTextAlign(22);
201 canvas->add(std::move(binTxt));
209 auto truthMarker = std::make_unique<TMarker>(tan, icept, kFullCrossX);
210 truthMarker->SetMarkerColor(truthColor);
211 truthMarker->SetMarkerSize(4);
212 canvas->add(std::move(truthMarker));
213 canvas->add(
drawLabel(std::format(
"true parameters: {:}",
217 for (
const auto& maximum : maxima) {
218 auto maxMarker = std::make_unique<TMarker>(maximum.x, maximum.y, kFullTriangleUp);
219 maxMarker->SetMarkerColor(parLineColor);
220 maxMarker->SetMarkerSize(4);
221 canvas->add(std::move(maxMarker));
224 const double xMin = maximum.x - maximum.wx;
225 const double xMax = maximum.x + maximum.wx;
226 const double yMin = maximum.y - maximum.wy;
227 const double yMax = maximum.y + maximum.wy;
230 maxBox->SetLineStyle(kDashed);
231 maxBox->SetLineWidth(2);
232 canvas->add(std::move(maxBox));
235 canvas->add(std::move(primitives));
240 const int view)
const {
252 re->measurementHash(simHit->identify()) :
253 re->layerHash(simHit->identify());
255 re->localToGlobalTransform(*geoCtx, hash);
256 const Amg::Vector3D locPos = trf * xAOD::toEigen(simHit->localPosition());
257 const Amg::Vector3D locDir = trf.linear() * xAOD::toEigen(simHit->localDirection());
258 canvas.add(
drawArrow(locPos, locDir, truthColor, kDashed, view));
263 const std::string& extraLabel)
const {
269 const std::string& extraLabel,
272 ATH_MSG_VERBOSE(
"Visualizing seed with " << seed.getHitsInMax().size() <<
" hits");
275 ATH_MSG_VERBOSE(
"visualizeSeed skipped: canvas quota already exhausted for " << extraLabel);
280 ATH_MSG_VERBOSE(
"visualizeSeed skipped: no truth segments found and displayOnlyTruth=true");
290 canvas->add(std::move(primitives));
298 canvas->setAxisTitles(std::format(
"{:} [mm]", view ==
objViewEta ?
'y' :
'x'),
"z [mm]");
300 if (!
drawHits(*seed.parentBucket(), seed.getHitsInMax(), *canvas, view)) {
305 canvas->corner(Edges::yLow), canvas->corner(Edges::yHigh),
306 truthColor, kDotted, view));
309 canvas->add(
drawLine(seed.parameters(), canvas->corner(Edges::yLow),
310 canvas->corner(Edges::yHigh), parLineColor, kDashed, view));
312 writeChi2(seed.parameters(), seed.getHitsInMax(), *canvas);
314 std::string legendLabel = std::format(
"Event: {:}, chamber : {:}, #{:}-view ({:})",
315 ctx.eventID().event_number(),
316 m_idHelperSvc->toStringChamber(seed.getHitsInMax().front()->identify()),
319 canvas->add(
drawLabel(legendLabel, 0.1, 0.96));
320 canvas->add(
drawLabel(
"Seed parameters: " +
makeLabel(seed.parameters()),0.25, 0.89));
326 const std::string& extraLabel)
const {
332 const std::string& extraLabel,
342 ATH_MSG_VERBOSE(
"visualizeBucket skipped: no truth segments found and displayOnlyTruth=true");
351 canvas->add(std::move(primitives));
358 canvas->setAxisTitles(std::format(
"{:} [mm]", view ==
objViewEta ?
'y' :
'x'),
"z [mm]");
360 if (!
drawHits(bucket, bucket, *canvas, view)) {
363 bool drawnTrueLabel{
false};
366 canvas->corner(Edges::yLow), canvas->corner(Edges::yHigh),
367 truthColor, kDotted, view));
368 if (!drawnTrueLabel) {
370 drawnTrueLabel =
true;
375 std::string legendLabel = std::format(
"Event: {:}, chamber : {:}, #{:}-view ({:})",
376 ctx.eventID().event_number(),
380 canvas->add(
drawLabel(legendLabel, 0.15, 0.96));
386 const std::string& extraLabel)
const {
393 const std::string& extraLabel,
415 canvas->add(std::move(primitives));
425 canvas->setAxisTitles(std::format(
"{:} [mm]", view ==
objViewEta ?
'y' :
'x'),
"z [mm]");
432 truthColor, kDotted, view));
437 canvas->add(
drawLine(segPars, canvas->corner(Edges::yLow), canvas->corner(Edges::yHigh),
438 parLineColor, kDashed, view));
441 std::string legendLabel=std::format(
"Event: {:}, chamber: {:}, #chi^{{2}} / nDoF: {:.2f} ({:d}), #{:}-view (:)",
442 ctx.eventID().event_number(),
m_idHelperSvc->toStringChamber(canvasId),
443 segment.
chi2() /std::max(1u, segment.
nDoF()), segment.
nDoF(),
444 view ==
objViewEta ?
"eta" :
"phi", extraLabel);
446 canvas->add(
drawLabel(legendLabel, 0.2, 0.96));
451 template<
class SpacePo
intType>
454 const unsigned int view,
455 unsigned int fillStyle)
const {
463 canvas.expandPad(hit.localPosition()[view] - hit.driftRadius(),
464 hit.localPosition().z() - hit.driftRadius());
465 canvas.expandPad(hit.localPosition()[view] + hit.driftRadius(),
466 hit.localPosition().z() + hit.driftRadius());
471 constexpr int invalidCalibFill = 3305;
472 if constexpr (std::is_same_v<SpacePointType, SpacePoint>) {
476 if (dc && dc->status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
477 fillStyle = invalidCalibFill;
480 }
else if constexpr(std::is_same_v<SpacePointType, CalibratedSpacePoint>) {
481 underlyingSp = hit.spacePoint();
482 if (hit.fitState() == CalibratedSpacePoint::State::Valid) {
484 }
else if (hit.fitState() == CalibratedSpacePoint::State::FailedCalib) {
485 fillStyle = invalidCalibFill;
501 canvas.add(
drawDriftCircle(hit.localPosition(), dc->readoutElement()->innerTubeRadius(),
503 auto driftCircle =
drawDriftCircle(hit.localPosition(), hit.driftRadius(), kBlue, fillStyle);
506 driftCircle->SetLineColor(truthColor);
507 driftCircle->SetLineWidth(1);
509 canvas.add(std::move(driftCircle));
513 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->
covariance()[view]);
514 auto rpcBox =
drawBox(hit.localPosition(), boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
515 kGreen + 2, fillStyle);
517 rpcBox->SetLineColor(truthColor);
518 rpcBox->SetLineWidth(1);
520 canvas.add(std::move(rpcBox));
523 const auto* meas{
static_cast<const xAOD::TgcStrip*
>(primaryMeas)};
524 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->
covariance()[view]);
525 auto tgcBox =
drawBox(hit.localPosition(), boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
526 kCyan + 2, fillStyle);
528 tgcBox->SetLineColor(truthColor);
529 tgcBox->SetLineWidth(1);
531 canvas.add(std::move(tgcBox));
534 const double boxWidth = 5*Gaudi::Units::mm;
535 auto mmBox =
drawBox(hit.localPosition(), boxWidth, 10.*Gaudi::Units::mm, kAquamarine, fillStyle);
537 mmBox->SetLineColor(truthColor);
538 mmBox->SetLineWidth(1);
540 canvas.add(std::move(mmBox));
545 const double boxWidth = 5*Gaudi::Units::mm;
546 auto stgcBox =
drawBox(hit.localPosition(), boxWidth, 10.*Gaudi::Units::mm, kTeal, fillStyle);
548 stgcBox->SetLineColor(truthColor);
549 stgcBox->SetLineWidth(1);
551 canvas.add(std::move(stgcBox));
554 ATH_MSG_WARNING(
"Please implement proper drawings of the new small wheel.. "<<__FILE__<<
":"<<__LINE__);
561 template<
class SpacePo
intType>
563 const std::vector<SpacePointType>& hitsToDraw,
565 unsigned int view)
const {
567 SpacePointSet drawnPoints{};
569 for (
const SpacePointType& hit : hitsToDraw) {
573 for (
const SpacePointBucket::value_type& hit : bucket) {
575 if (drawnPoints.count(hit.get())) {
582 return drawnPoints.size() - drawnPoints.count(
nullptr) > 1;
584 template<
class SpacePo
intType>
586 const std::vector<SpacePointType>& hits,
588 const double legX,
double startLegY,
589 const double endLegY)
const {
590 const auto [pos, dir] =
makeLine(pars);
592 for (
const SpacePointType& hit : hits) {
594 bool displayChi2{
true};
595 if constexpr(std::is_same_v<SpacePointType, Segment::MeasType>) {
596 underlyingSp = hit->spacePoint();
597 displayChi2 = (hit->fitState() == CalibratedSpacePoint::State::Valid);
602 std::string legendstream{};
603 switch(hit->type()) {
605 const int driftSign{SeedingAux::strawSign(pos, dir, *hit)};
607 legendstream = std::format(
"ML: {:1d}, TL: {:1d}, T: {:3d}, {:}",
609 idHelper.
tube(hitId), driftSign == -1 ?
"L" :
"R");
613 legendstream= std::format(
"DR: {:1d}, DZ: {:1d}, GAP: {:1d}, #eta/#phi: {:}/{:}",
615 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
619 legendstream = std::format(
"ST: {:}, GAP: {:1d}, #eta/#phi: {:}/{:}",
621 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
626 const MuonGMR4::StripDesign& design = clus->readoutElement()->stripLayer(clus->layerHash()).design();
627 legendstream = std::format(
"ML: {:1d}, GAP: {:1d}, {:}", idHelper.
multilayer(hitId), idHelper.
gasGap(hitId),
632 legendstream = std::format(
"ML: {:1d}, GAP: {:1d}, #eta/#phi: {:}/{:}",
634 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
637 legendstream =
"Ext. constaint";
643 const double chi2 = SeedingAux::chi2Term(pos, dir,*hit);
644 legendstream+=std::format(
", #chi^{{2}}: {:.2f}",
chi2);
646 legendstream+=
", #chi^{2}: ---";
648 canvas.add(
drawLabel(legendstream, legX, startLegY, 14));
650 if (startLegY<= endLegY) {
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
This is a "hash" representation of an Identifier.
int multilayer(const Identifier &id) const
Access to components of the ID.
int tube(const Identifier &id) const
int tubeLayer(const Identifier &id) const
int gasGap(const Identifier &id) const override
get the hashes
int multilayer(const Identifier &id) const
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
std::string identString() const
Returns a string encoding the chamber index & the sector of the MS sector.
double stereoAngle() const
Returns the value of the stereo angle.
bool hasStereoAngle() const
Returns whether a stereo angle is defined.
Representation of a segment seed (a fully processed hough maximum) produced by the hough transform.
const std::vector< HitType > & getHitsInMax() const
Returns the list of assigned hits.
const SpacePointBucket * parentBucket() const
Returns the bucket out of which the seed was formed.
Placeholder for what will later be the muon segment EDM representation.
unsigned int nDoF() const
Returns the number of degrees of freedom.
const SegmentSeed * parent() const
Returns the seed out of which the segment was built.
const MeasVec & measurements() const
Returns the associated measurements.
double chi2() const
Returns the chi2 of the segment fit.
: 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
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
const Cov_t & covariance() const
Returns the covariance array.
const Identifier & identify() const
: Identifier of the primary measurement
const xAOD::MuonMeasurement * secondaryMeasurement() const
const xAOD::MuonMeasurement * primaryMeasurement() const
int gasGap(const Identifier &id) const override
get the hashes
int doubletR(const Identifier &id) const
int doubletZ(const Identifier &id) const
Property holding a SG store/key/clid from which a ReadHandle is made.
int gasGap(const Identifier &id) const override
get the hashes
int multilayer(const Identifier &id) const
int gasGap(const Identifier &id) const override
get the hashes
double chi2(TH1 *h0, TH1 *h1)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
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.
double houghTanBeta(const Amg::Vector3D &v)
Returns the hough tanBeta [y] / [z].
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
MuonValR4::IPatternVisualizationTool::PrimitiveVec PrimitiveVec
Acts::HoughTransformUtils::HoughPlane< HoughHitType > HoughPlane
double houghTanAlpha(const Amg::Vector3D &v)
: Returns the hough tanAlpha [x] / [z]
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
constexpr int objViewEta
ObjectView.
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::unique_ptr< TEllipse > drawDriftCircle(const Amg::Vector3D ¢er, 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.
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
MdtDriftCircle_v1 MdtDriftCircle
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
RpcMeasurement_v1 RpcMeasurement
MuonSegment_v1 MuonSegment
Reference the current persistent version: