21 #include "Acts/Utilities/Helpers.hpp"
34 std::string removeNonAlphaNum(std::string
str) {
35 str.erase(std::remove_if(
str.begin(),
str.end(),
36 [](
const unsigned char c){
37 return !std::isalnum(c);
41 constexpr
int truthColor = kOrange +2;
42 constexpr
int parLineColor = kRed;
43 using SpacePointSet = std::unordered_set<const MuonR4::SpacePoint*>;
45 yLow = 0, yHigh, zLow, zHigh
52 using namespace SegmentFit;
57 if (m_canvasLimit > 0) {
58 if (m_canvasPrefix.value().empty() || m_allCanName.value().empty()) {
59 ATH_MSG_FATAL(
"Please define "<<m_canvasPrefix<<
" && "<<m_allCanName);
60 return StatusCode::FAILURE;
62 if (m_saveSummaryPDF) {
63 m_allCan = std::make_unique<TCanvas>(
"all",
"all", m_canvasWidth, m_canvasHeight);
64 m_allCan->SaveAs((m_allCanName +
".pdf[").c_str());
66 m_outFile = std::make_unique<TFile>( (m_allCanName +
".root").c_str(),
"RECREATE");
67 if (m_saveSinglePDFs) {
68 std::filesystem::create_directories(
"Plots/" + m_canvasPrefix);
70 gROOT->SetStyle(
"ATLAS");
71 TStyle* plotStyle = gROOT->GetStyle(
"ATLAS");
72 plotStyle->SetOptTitle(0);
73 plotStyle->SetHistLineWidth(1.);
74 plotStyle->SetPalette(kViridis);
76 ATH_CHECK(m_prepContainerKeys.initialize(!m_truthSegLinks.empty()));
77 m_truthLinkDecorKeys.clear();
78 ATH_MSG_INFO(
"Hits linked to the following segment decorations are considered as truth");
79 for (
const std::string& decorName : m_truthSegLinks) {
81 if (decorName.empty()) {
83 return StatusCode::FAILURE;
86 m_truthLinkDecorKeys.emplace_back(
key, decorName);
90 ATH_CHECK(m_truthLinkDecorKeys.initialize());
91 m_displayOnlyTruth.value() &= !m_truthLinkDecorKeys.empty();
96 return StatusCode::SUCCESS;
100 return StatusCode::SUCCESS;
107 return std::find_if(m_truthLinkDecors.begin(), m_truthLinkDecors.end(),
109 return !decor(hit).empty();
110 }) != m_truthLinkDecors.end();
114 std::vector<const xAOD::UncalibratedMeasurement*> measurements{};
115 measurements.reserve(2*
hits.size());
117 measurements.push_back(hit->primaryMeasurement());
118 if(hit->secondaryMeasurement()) {
119 measurements.push_back(hit->secondaryMeasurement());
122 return getLabeledSegments(measurements);
128 for (
const SegLink_t& link : decor(*hit)) {
129 truthSegs.insert(*link);
136 const double yLow =
can.GetPad(0)->GetUymin();
137 const double yHigh =
can.GetPad(0)->GetUymax();
138 for (
auto& prim : primitives) {
139 const TObject &primRef = *prim;
140 if (
typeid(primRef) ==
typeid(TLine)){
141 TLine*
line =
static_cast<TLine*
>(prim.get());
145 const Amg::Vector3D newHigh = linePoint + Amg::intersect<3>(linePoint, lineDir, Amg::Vector3D::UnitY(), yHigh).value_or(0.) * lineDir;
146 const Amg::Vector3D newLow = linePoint + Amg::intersect<3>(linePoint, lineDir, Amg::Vector3D::UnitY(), yLow).value_or(0.) * lineDir;
147 line->SetX1(newLow.x());
148 line->SetY1(newLow.y());
149 line->SetX2(newHigh.x());
150 line->SetY2(newHigh.y());
158 const Acts::HoughTransformUtils::HoughAxisRanges& axisRanges,
159 const MaximumVec& maxima,
160 const std::string& extraLabel)
const {
162 visualizeAccumulator(ctx, accumulator, axisRanges, maxima, extraLabel, std::move(primitives));
166 const Acts::HoughTransformUtils::HoughAxisRanges& axisRanges,
167 const MaximumVec& maxima,
168 const std::string& extraLabel,
172 if (m_canvCounter >= m_canvasLimit) {
176 std::lock_guard guard{
s_mutex};
179 if (m_canvCounter >= m_canvasLimit) {
182 if (accumulator.getNonEmptyBins().empty()) {
187 auto accHisto = std::make_unique<TH2F>(
"AccumulatorHisto",
"histo",
188 accumulator.nBinsX(), axisRanges.xMin, axisRanges.xMax,
189 accumulator.nBinsY(), axisRanges.yMin, axisRanges.yMax);
191 accHisto->SetDirectory(
nullptr);
192 accHisto->GetXaxis()->SetTitle(
std::format(
"tan#{}", m_accumlIsEta ?
"theta" :
"phi" ).c_str());
193 accHisto->GetYaxis()->SetTitle( std::string{m_accumlIsEta ?
"y_{0}" :
"x_{0}"}.c_str());
195 std::vector<const SpacePoint*> spacePointsInAcc{};
196 for (
const std::size_t
bin : accumulator.getNonEmptyBins()) {
197 const auto [xBin, yBin] = accumulator.axisBins(
bin);
201 auto hitIds = accumulator.hitIds(xBin, yBin);
202 hitsInBin.insert(std::make_move_iterator(hitIds.begin()),std::make_move_iterator(hitIds.end()));
204 spacePointsInAcc.insert(spacePointsInAcc.end(),hitsInBin.begin(), hitsInBin.end());
205 accHisto->SetBinContent(xBin+1, yBin+1, accumulator.nHits(
bin));
209 if (truthSegs.empty() && m_displayOnlyTruth) {
216 auto truthMarker = std::make_unique<TMarker>(
tan, icept, kFullCrossX);
217 truthMarker->SetMarkerColor(truthColor);
218 truthMarker->SetMarkerSize(8);
219 primitives.push_back(std::move(truthMarker));
222 for (
const auto& maximum : maxima) {
223 auto maxMarker = std::make_unique<TMarker>(maximum.x, maximum.y, kFullTriangleUp);
224 maxMarker->SetMarkerColor(parLineColor);
225 maxMarker->SetMarkerSize(8);
226 primitives.push_back(std::move(maxMarker));
229 primitives.push_back(
drawLumiSqrtS(0.65,0.21, m_sqrtSLabel, m_lumiLabel));
231 std::stringstream canvasName{};
232 canvasName<<
name()<<
"_"<<ctx.eventID().event_number()<<
"_"<<m_canvCounter;
233 auto canvas = std::make_unique<TCanvas>(canvasName.str().c_str(),
234 "can", m_canvasWidth, m_canvasHeight);
235 canvas->GetPad(0)->SetRightMargin(0.12);
236 canvas->GetPad(0)->SetTopMargin(0.12);
238 accHisto->Draw(
"COLZ");
239 drawPrimitives(*
canvas, primitives);
240 primitives.push_back(std::move(accHisto));
241 saveCanvas(ctx, spacePointsInAcc.front()->identify(), *
canvas, extraLabel);
242 primitives.push_back(std::move(
canvas));
245 if (m_canvasLimit <= m_canvCounter) {
246 closeSummaryCanvas();
252 const int view)
const {
253 if (!m_paintTruthHits) {
258 if (!
SG::get(geoCtx, m_geoCtxKey, ctx).isSuccess()) {
264 re->measurementHash(simHit->identify()) :
265 re->layerHash(simHit->identify());
267 re->localToGlobalTrans(*geoCtx,
hash);
275 const std::string& extraLabel)
const {
277 visualizeSeed(ctx, seed, extraLabel, std::move(primitives));
281 const std::string& extraLabel,
285 if (m_canvCounter >= m_canvasLimit) {
289 std::lock_guard guard{
s_mutex};
292 if (m_canvCounter >= m_canvasLimit) {
297 if (truthSegs.empty() && m_displayOnlyTruth) {
301 std::array<double, 4> canvasDim{};
302 const std::size_t parsedPrimSize{primitives.size()};
309 primitives.resize(parsedPrimSize);
311 if (!drawHits(*seed.parentBucket(), seed.getHitsInMax(), primitives, canvasDim,
view)) {
316 truthColor, kDotted,
view));
319 primitives.push_back(
drawLine(seed.parameters(), canvasDim[Edges::zLow], canvasDim[Edges::zHigh],
320 parLineColor, kDashed,
view));
322 writeChi2(seed.parameters(), seed.getHitsInMax(), primitives);
324 std::stringstream legendLabel{};
327 legendLabel<<
"Event: "<<ctx.eventID().event_number()<<
", chamber : "<<m_idHelperSvc->toStringChamber(seed.getHitsInMax().front()->identify())
331 if (!extraLabel.empty()) {
332 legendLabel<<
" ("<<extraLabel<<
")";
334 primitives.push_back(
drawLabel(legendLabel.str(), 0.1, 0.96));
337 auto canvas = makeCanvas(ctx, canvasDim,
view);
339 primitives.push_back(
drawLumiSqrtS(0.75,0.21, m_sqrtSLabel, m_lumiLabel));
341 drawPrimitives(*
canvas, primitives);
343 saveCanvas(ctx, seed.getHitsInMax().front()->identify(), *
canvas, extraLabel);
345 if (m_canvasLimit <= m_canvCounter) {
347 closeSummaryCanvas();
353 const std::string& extraLabel)
const {
355 visualizeBucket(ctx, bucket, extraLabel, std::move(primitives));
359 const std::string& extraLabel,
362 if (m_canvCounter >= m_canvasLimit) {
366 std::lock_guard guard{
s_mutex};
369 if (m_canvCounter >= m_canvasLimit) {
372 std::array<double, 4> canvasDim{};
373 LabeledSegmentSet truthSegs{getLabeledSegments(Acts::unpackConstSmartPointers(bucket))};
374 if (truthSegs.empty() && m_displayOnlyTruth) {
377 const std::size_t parsedPrimSize{primitives.size()};
384 primitives.resize(parsedPrimSize);
385 if (!drawHits(bucket, bucket, primitives, canvasDim,
view)) {
388 bool drawnTrueLabel{
false};
391 truthColor, kDotted,
view));
392 if (!drawnTrueLabel) {
394 drawnTrueLabel =
true;
399 std::stringstream legendLabel{};
400 legendLabel<<
"Event: "<<ctx.eventID().event_number()
401 <<
", chamber : "<<m_idHelperSvc->toStringChamber(bucket.front()->identify())
403 if (!extraLabel.empty()) {
404 legendLabel<<
" ("<<extraLabel<<
")";
406 primitives.push_back(
drawLabel(legendLabel.str(), 0.2, 0.96));
409 primitives.push_back(
drawLumiSqrtS(0.75,0.21, m_sqrtSLabel, m_lumiLabel));
411 auto can = makeCanvas(ctx , canvasDim,
view);
412 drawPrimitives(*
can, primitives);
414 saveCanvas(ctx, bucket.front()->identify(), *
can, extraLabel);
416 if (m_canvasLimit <= m_canvCounter) {
418 closeSummaryCanvas();
425 const std::string& extraLabel)
const {
427 visualizeSegment(ctx,
segment,extraLabel, std::move(primitives));
432 const std::string& extraLabel,
435 if (m_canvCounter >= m_canvasLimit) {
439 std::lock_guard guard{
s_mutex};
442 if (m_canvCounter >= m_canvasLimit) {
446 if (truthSegs.empty() && m_displayOnlyTruth) {
452 if (!
SG::get(geoCtx, m_geoCtxKey, ctx).isSuccess()) {
458 segPars[Acts::toUnderlying(ParamDefs::x0)] = locPos.x();
459 segPars[Acts::toUnderlying(ParamDefs::y0)] = locPos.y();
465 std::array<double, 4> canvasDim{};
466 const std::size_t parsedPrimSize{primitives.size()};
473 primitives.resize(parsedPrimSize);
475 if (!drawHits(*
segment.parent()->parentBucket(),
segment.measurements(),
476 primitives, canvasDim,
view)) {
481 truthColor, kDotted,
view));
484 writeChi2(segPars,
segment.measurements(), primitives);
487 primitives.push_back(
drawLumiSqrtS(0.75,0.21, m_sqrtSLabel, m_lumiLabel));
489 primitives.push_back(
drawLine(segPars, canvasDim[Edges::zLow], canvasDim[Edges::zHigh],
490 parLineColor, kDashed,
view));
493 std::stringstream legendLabel{};
495 legendLabel<<
"Event: "<<ctx.eventID().event_number() <<
", chamber : "<<m_idHelperSvc->toStringChamber(canvasId)
499 if (!extraLabel.empty()) {
500 legendLabel<<
" ("<<extraLabel<<
")";
502 primitives.push_back(
drawLabel(legendLabel.str(), 0.2, 0.96));
505 auto canvas = makeCanvas(ctx, canvasDim,
view);
506 drawPrimitives(*
canvas, primitives);
508 saveCanvas(ctx, canvasId, *
canvas, extraLabel);
510 if (m_canvasLimit <= m_canvCounter) {
512 closeSummaryCanvas();
516 template<
class SpacePo
intType>
519 std::array<double, 4>& canvasDim,
const unsigned int view,
520 unsigned int fillStyle)
const {
528 canvasDim[Edges::yLow] =
std::min(canvasDim[Edges::yLow], hit.localPosition()[
view] - hit.driftRadius());
529 canvasDim[Edges::yHigh] =
std::max(canvasDim[Edges::yHigh], hit.localPosition()[
view] + hit.driftRadius());
530 canvasDim[Edges::zLow] =
std::min(canvasDim[Edges::zLow], hit.localPosition().z() - hit.driftRadius());
531 canvasDim[Edges::zHigh] =
std::max(canvasDim[Edges::zHigh], hit.localPosition().z() + hit.driftRadius());
536 constexpr
int invalidCalibFill = 3305;
537 if constexpr (std::is_same_v<SpacePointType, SpacePoint>) {
542 fillStyle = invalidCalibFill;
545 }
else if constexpr(std::is_same_v<SpacePointType, CalibratedSpacePoint>) {
546 underlyingSp = hit.spacePoint();
550 fillStyle = invalidCalibFill;
558 primitives.push_back(
drawDriftCircle(hit.localPosition(), dc->readoutElement()->innerTubeRadius(),
561 const int circColor = isLabeled(*dc) ? truthColor : kBlue;
562 primitives.push_back(
drawDriftCircle(hit.localPosition(), hit.driftRadius(), circColor, fillStyle));
566 const int boxColor = isLabeled(*meas) ? truthColor : kGreen +2;
567 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->covariance()[
view]);
568 primitives.push_back(
drawBox(hit.localPosition(), boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
569 boxColor, fillStyle));
572 const auto* meas{
static_cast<const xAOD::TgcStrip*
>(underlyingSp->primaryMeasurement())};
573 const int boxColor = isLabeled(*meas) ? truthColor : kCyan + 2;
574 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->covariance()[
view]);
575 primitives.push_back(
drawBox(hit.localPosition(), boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
576 boxColor, fillStyle));
579 const auto* meas{
static_cast<const xAOD::MMCluster*
>(underlyingSp->primaryMeasurement())};
580 const int boxColor = isLabeled(*meas) ? truthColor : kAquamarine;
583 boxColor, fillStyle));
588 ATH_MSG_WARNING(
"Please implement proper drawings of the new small wheel.. "<<__FILE__<<
":"<<__LINE__);
594 template<
class SpacePo
intType>
596 const std::vector<SpacePointType>& hitsToDraw,
597 std::vector<PrimitivePtr>& primitives,
598 std::array<double, 4>& canvasDim,
599 unsigned int view)
const {
601 canvasDim[Edges::yLow] = canvasDim[Edges::zLow] = 100. *
Gaudi::Units::m;
602 canvasDim[Edges::yHigh] = canvasDim[Edges::zHigh] = -100. *
Gaudi::Units::m;
605 for (
const SpacePointType& hit : hitsToDraw) {
606 drawnPoints.insert(drawHit(*hit, primitives, canvasDim,
view,
fullFilling));
608 if (m_displayBucket) {
609 for (
const SpacePointBucket::value_type& hit : bucket) {
611 if (drawnPoints.count(hit.get())) {
620 for (
auto & prim : primitives){
621 TBox* theBox =
dynamic_cast<TBox*
>(prim.get());
623 canvasDim[Edges::zLow] =
std::min(canvasDim[Edges::zLow], theBox->GetY1());
624 canvasDim[Edges::zHigh] =
std::max(canvasDim[Edges::zHigh], theBox->GetY2());
628 double width = (canvasDim[Edges::yHigh] - canvasDim[Edges::yLow])*m_canvasExtraScale;
629 double height = (canvasDim[Edges::zHigh] - canvasDim[Edges::zLow])*m_canvasExtraScale;
633 const double midPointX = 0.5 * (canvasDim[Edges::yHigh] + canvasDim[Edges::yLow]);
634 const double midPointY = 0.5 * (canvasDim[Edges::zHigh] + canvasDim[Edges::zLow]);
635 canvasDim[Edges::yLow] = midPointX - 0.5 *
width;
636 canvasDim[Edges::zLow] = midPointY - 0.5 * height;
637 canvasDim[Edges::yHigh] = midPointX + 0.5 *
width;
638 canvasDim[Edges::zHigh] = midPointY + 0.5 * height;
639 return drawnPoints.size() - drawnPoints.count(
nullptr) > 1;
641 template<
class SpacePo
intType>
643 const std::vector<SpacePointType>&
hits,
645 const double legX,
double startLegY,
646 const double endLegY)
const {
652 for (
const SpacePointType& hit :
hits) {
654 bool displayChi2{
true};
655 if constexpr(std::is_same_v<SpacePointType, Segment::MeasType>) {
656 underlyingSp = hit->spacePoint();
665 std::string legendstream{};
666 switch(hit->type()) {
668 const int driftSign{SeedingAux::strawSign(
pos,
dir, *hit)};
669 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
670 legendstream =
std::format(
"ML: {:1d}, TL: {:1d}, T: {:3d}, {:}",
671 idHelper.multilayer(hitId), idHelper.tubeLayer(hitId),
672 idHelper.tube(hitId), driftSign == -1 ?
"L" :
"R");
675 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
676 legendstream=
std::format(
"DR: {:1d}, DZ: {:1d}, GAP: {:1d}, #eta/#phi: {:}/{:}",
677 idHelper.doubletR(hitId), idHelper.doubletZ(hitId), idHelper.gasGap(hitId),
678 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
681 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
682 legendstream =
std::format(
"ST: {:}, GAP: {:1d}, #eta/#phi: {:}/{:}",
683 m_idHelperSvc->stationNameString(hitId), idHelper.gasGap(hitId),
684 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
687 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
688 const auto* clus =
static_cast<const xAOD::MMCluster*
>(underlyingSp->primaryMeasurement());
689 const MuonGMR4::StripDesign& design = clus->readoutElement()->stripLayer(clus->layerHash()).design();
690 legendstream =
std::format(
"ML: {:1d}, GAP: {:1d}, {:}", idHelper.multilayer(hitId), idHelper.gasGap(hitId),
694 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
695 legendstream =
std::format(
"ML: {:1d}, GAP: {:1d}, #eta/#phi: {:}/{:}",
696 idHelper.multilayer(hitId), idHelper.gasGap(hitId),
697 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
700 legendstream =
"Ext. constaint";
706 const double chi2 = SeedingAux::chi2Term(
pos,
dir,*hit);
709 legendstream+=
", #chi^{2}: ---";
711 primitives.push_back(
drawLabel(legendstream, legX, startLegY, 14));
713 if (startLegY<= endLegY) {
719 if (!m_outFile)
return;
720 ATH_MSG_INFO(
"Close summary pdf & root file "<<m_allCanName);
723 m_allCan->SaveAs((m_allCanName +
".pdf]").c_str());
729 const std::array<double, 4>& canvasDim,
730 const int view)
const {
731 std::stringstream canvasName{};
732 canvasName<<
name()<<
"_"<<ctx.eventID().event_number()<<
"_"<<m_canvCounter;
733 ATH_MSG_VERBOSE(
"Create new canvas "<<canvasName.str()<<
" "<<canvasDim);
734 auto canvas = std::make_unique<TCanvas>(canvasName.str().c_str(),
"all", m_canvasWidth, m_canvasHeight);
736 TH1F* frame =
canvas->DrawFrame(canvasDim[Edges::yLow],canvasDim[Edges::zLow], canvasDim[Edges::yHigh], canvasDim[Edges::zHigh]);
738 frame->GetYaxis()->SetTitle(
"z [mm]");
744 const std::string& extraLabel)
const {
746 std::stringstream canvasName{};
747 canvasName<<m_canvasPrefix.value()<<
"_"<<ctx.eventID().event_number()<<
"_"<<(m_canvCounter++)<<
"_"
748 <<m_idHelperSvc->stationNameString(chambId)
749 <<std::abs(m_idHelperSvc->stationEta(chambId))
750 <<(m_idHelperSvc->stationEta(chambId) >0 ?
"A" :
"C")
751 <<m_idHelperSvc->stationPhi(chambId);
752 if (!extraLabel.empty()) canvasName<<
"_"<<removeNonAlphaNum(extraLabel);
754 if (m_saveSinglePDFs) {
755 canvas.SaveAs((
"Plots/" + m_canvasPrefix+
"/" + canvasName.str()+
".pdf").c_str());
757 if (m_saveSummaryPDF) {
758 canvas.SaveAs((m_allCanName+
".pdf").c_str());
760 m_outFile->WriteObject(&
canvas, canvasName.str().c_str());