19 #include "Acts/Utilities/Helpers.hpp"
32 std::string removeNonAlphaNum(std::string
str) {
33 str.erase(std::remove_if(
str.begin(),
str.end(),
34 [](
const unsigned char c){
35 return !std::isalnum(c);
39 constexpr
int truthColor = kOrange +2;
40 constexpr
int parLineColor = kRed;
41 using SpacePointSet = std::unordered_set<const MuonR4::SpacePoint*>;
43 yLow = 0, yHigh, zLow, zHigh
50 using namespace SegmentFit;
55 if (m_canvasLimit > 0) {
56 if (m_canvasPrefix.value().empty() || m_allCanName.value().empty()) {
57 ATH_MSG_FATAL(
"Please define "<<m_canvasPrefix<<
" && "<<m_allCanName);
58 return StatusCode::FAILURE;
60 if (m_saveSummaryPDF) {
61 m_allCan = std::make_unique<TCanvas>(
"all",
"all", m_canvasWidth, m_canvasHeight);
62 m_allCan->SaveAs((m_allCanName +
".pdf[").c_str());
64 m_outFile = std::make_unique<TFile>( (m_allCanName +
".root").c_str(),
"RECREATE");
65 if (m_saveSinglePDFs) {
66 std::filesystem::create_directories(
"Plots/" + m_canvasPrefix);
68 gROOT->SetStyle(
"ATLAS");
69 TStyle* plotStyle = gROOT->GetStyle(
"ATLAS");
70 plotStyle->SetOptTitle(0);
71 plotStyle->SetHistLineWidth(1.);
72 plotStyle->SetPalette(kViridis);
74 ATH_CHECK(m_prepContainerKeys.initialize(!m_truthSegLinks.empty()));
75 m_truthLinkDecorKeys.clear();
76 ATH_MSG_INFO(
"Hits linked to the following segment decorations are considered as truth");
77 for (
const std::string& decorName : m_truthSegLinks) {
79 if (decorName.empty()) {
81 return StatusCode::FAILURE;
84 m_truthLinkDecorKeys.emplace_back(
key, decorName);
88 ATH_CHECK(m_truthLinkDecorKeys.initialize());
89 m_displayOnlyTruth.value() &= !m_truthLinkDecorKeys.empty();
94 return StatusCode::SUCCESS;
98 return StatusCode::SUCCESS;
105 return std::find_if(m_truthLinkDecors.begin(), m_truthLinkDecors.end(),
107 return !decor(hit).empty();
108 }) != m_truthLinkDecors.end();
112 std::vector<const xAOD::UncalibratedMeasurement*> measurements{};
113 measurements.reserve(2*
hits.size());
115 measurements.push_back(hit->primaryMeasurement());
116 if(hit->secondaryMeasurement()) {
117 measurements.push_back(hit->secondaryMeasurement());
120 return getLabeledSegments(measurements);
126 for (
const SegLink_t& link : decor(*hit)) {
127 truthSegs.insert(*link);
134 const double yLow =
can.GetPad(0)->GetUymin();
135 const double yHigh =
can.GetPad(0)->GetUymax();
136 for (
auto& prim : primitives) {
137 const TObject &primRef = *prim;
138 if (
typeid(primRef) ==
typeid(TLine)){
139 TLine*
line =
static_cast<TLine*
>(prim.get());
143 const Amg::Vector3D newHigh = linePoint + Amg::intersect<3>(linePoint, lineDir, Amg::Vector3D::UnitY(), yHigh).value_or(0.) * lineDir;
144 const Amg::Vector3D newLow = linePoint + Amg::intersect<3>(linePoint, lineDir, Amg::Vector3D::UnitY(), yLow).value_or(0.) * lineDir;
145 line->SetX1(newLow.x());
146 line->SetY1(newLow.y());
147 line->SetX2(newHigh.x());
148 line->SetY2(newHigh.y());
156 const Acts::HoughTransformUtils::HoughAxisRanges& axisRanges,
157 const MaximumVec& maxima,
158 const std::string& extraLabel)
const {
160 visualizeAccumulator(ctx, accumulator, axisRanges, maxima, extraLabel, std::move(primitives));
164 const Acts::HoughTransformUtils::HoughAxisRanges& axisRanges,
165 const MaximumVec& maxima,
166 const std::string& extraLabel,
170 if (m_canvCounter >= m_canvasLimit) {
174 std::lock_guard guard{
s_mutex};
177 if (m_canvCounter >= m_canvasLimit) {
180 if (accumulator.getNonEmptyBins().empty()) {
185 auto accHisto = std::make_unique<TH2F>(
"AccumulatorHisto",
"histo",
186 accumulator.nBinsX(), axisRanges.xMin, axisRanges.xMax,
187 accumulator.nBinsY(), axisRanges.yMin, axisRanges.yMax);
189 accHisto->SetDirectory(
nullptr);
190 accHisto->GetXaxis()->SetTitle(
std::format(
"tan#{}", m_accumlIsEta ?
"theta" :
"phi" ).c_str());
191 accHisto->GetYaxis()->SetTitle( std::string{m_accumlIsEta ?
"y_{0}" :
"x_{0}"}.c_str());
193 std::vector<const SpacePoint*> spacePointsInAcc{};
194 for (
const std::size_t
bin : accumulator.getNonEmptyBins()) {
195 const auto [xBin, yBin] = accumulator.axisBins(
bin);
199 auto hitIds = accumulator.hitIds(xBin, yBin);
200 hitsInBin.insert(std::make_move_iterator(hitIds.begin()),std::make_move_iterator(hitIds.end()));
202 spacePointsInAcc.insert(spacePointsInAcc.end(),hitsInBin.begin(), hitsInBin.end());
203 accHisto->SetBinContent(xBin+1, yBin+1, accumulator.nHits(
bin));
207 if (truthSegs.empty() && m_displayOnlyTruth) {
214 auto truthMarker = std::make_unique<TMarker>(
tan, icept, kFullCrossX);
215 truthMarker->SetMarkerColor(truthColor);
216 truthMarker->SetMarkerSize(8);
217 primitives.push_back(std::move(truthMarker));
220 for (
const auto& maximum : maxima) {
221 auto maxMarker = std::make_unique<TMarker>(maximum.x, maximum.y, kFullTriangleUp);
222 maxMarker->SetMarkerColor(parLineColor);
223 maxMarker->SetMarkerSize(8);
224 primitives.push_back(std::move(maxMarker));
227 primitives.push_back(
drawLumiSqrtS(0.65,0.21, m_sqrtSLabel, m_lumiLabel));
229 std::stringstream canvasName{};
230 canvasName<<
name()<<
"_"<<ctx.eventID().event_number()<<
"_"<<m_canvCounter;
231 auto canvas = std::make_unique<TCanvas>(canvasName.str().c_str(),
232 "can", m_canvasWidth, m_canvasHeight);
233 canvas->GetPad(0)->SetRightMargin(0.12);
234 canvas->GetPad(0)->SetTopMargin(0.12);
236 accHisto->Draw(
"COLZ");
237 drawPrimitives(*
canvas, primitives);
238 primitives.push_back(std::move(accHisto));
239 saveCanvas(ctx, spacePointsInAcc.front()->identify(), *
canvas, extraLabel);
240 primitives.push_back(std::move(
canvas));
243 if (m_canvasLimit <= m_canvCounter) {
244 closeSummaryCanvas();
250 const int view)
const {
251 if (!m_paintTruthHits) {
256 if (!
SG::get(geoCtx, m_geoCtxKey, ctx).isSuccess()) {
262 re->measurementHash(simHit->identify()) :
263 re->layerHash(simHit->identify());
265 re->localToGlobalTrans(*geoCtx,
hash);
273 const std::string& extraLabel)
const {
275 visualizeSeed(ctx, seed, extraLabel, std::move(primitives));
279 const std::string& extraLabel,
283 if (m_canvCounter >= m_canvasLimit) {
287 std::lock_guard guard{
s_mutex};
290 if (m_canvCounter >= m_canvasLimit) {
295 if (truthSegs.empty() && m_displayOnlyTruth) {
299 std::array<double, 4> canvasDim{};
300 const std::size_t parsedPrimSize{primitives.size()};
307 primitives.resize(parsedPrimSize);
309 if (!drawHits(*seed.parentBucket(), seed.getHitsInMax(), primitives, canvasDim,
view)) {
314 truthColor, kDotted,
view));
315 paintSimHits(ctx,*segment, primitives,
view);
317 primitives.push_back(
drawLine(seed.parameters(), canvasDim[Edges::zLow], canvasDim[Edges::zHigh],
318 parLineColor, kDashed,
view));
320 writeChi2(seed.parameters(), seed.getHitsInMax(), primitives);
322 std::stringstream legendLabel{};
325 legendLabel<<
"Event: "<<ctx.eventID().event_number()<<
", chamber : "<<m_idHelperSvc->toStringChamber(seed.getHitsInMax().front()->identify())
329 if (!extraLabel.empty()) {
330 legendLabel<<
" ("<<extraLabel<<
")";
332 primitives.push_back(
drawLabel(legendLabel.str(), 0.1, 0.96));
335 auto canvas = makeCanvas(ctx, canvasDim,
view);
337 primitives.push_back(
drawLumiSqrtS(0.75,0.21, m_sqrtSLabel, m_lumiLabel));
339 drawPrimitives(*
canvas, primitives);
341 saveCanvas(ctx, seed.getHitsInMax().front()->identify(), *
canvas, extraLabel);
343 if (m_canvasLimit <= m_canvCounter) {
345 closeSummaryCanvas();
351 const std::string& extraLabel)
const {
353 visualizeBucket(ctx, bucket, extraLabel, std::move(primitives));
357 const std::string& extraLabel,
360 if (m_canvCounter >= m_canvasLimit) {
364 std::lock_guard guard{
s_mutex};
367 if (m_canvCounter >= m_canvasLimit) {
370 std::array<double, 4> canvasDim{};
371 LabeledSegmentSet truthSegs{getLabeledSegments(Acts::unpackConstSmartPointers(bucket))};
372 if (truthSegs.empty() && m_displayOnlyTruth) {
375 const std::size_t parsedPrimSize{primitives.size()};
382 primitives.resize(parsedPrimSize);
383 if (!drawHits(bucket, bucket, primitives, canvasDim,
view)) {
386 bool drawnTrueLabel{
false};
389 truthColor, kDotted,
view));
390 if (!drawnTrueLabel) {
392 drawnTrueLabel =
true;
394 paintSimHits(ctx,*segment, primitives,
view);
397 std::stringstream legendLabel{};
398 legendLabel<<
"Event: "<<ctx.eventID().event_number()
399 <<
", chamber : "<<m_idHelperSvc->toStringChamber(bucket.front()->identify())
401 if (!extraLabel.empty()) {
402 legendLabel<<
" ("<<extraLabel<<
")";
404 primitives.push_back(
drawLabel(legendLabel.str(), 0.2, 0.96));
407 primitives.push_back(
drawLumiSqrtS(0.75,0.21, m_sqrtSLabel, m_lumiLabel));
409 auto can = makeCanvas(ctx , canvasDim,
view);
410 drawPrimitives(*
can, primitives);
412 saveCanvas(ctx, bucket.front()->identify(), *
can, extraLabel);
414 if (m_canvasLimit <= m_canvCounter) {
416 closeSummaryCanvas();
423 const std::string& extraLabel)
const {
425 visualizeSegment(ctx, segment,extraLabel, std::move(primitives));
430 const std::string& extraLabel,
433 if (m_canvCounter >= m_canvasLimit) {
437 std::lock_guard guard{
s_mutex};
440 if (m_canvCounter >= m_canvasLimit) {
444 if (truthSegs.empty() && m_displayOnlyTruth) {
450 if (!
SG::get(geoCtx, m_geoCtxKey, ctx).isSuccess()) {
456 segPars[Acts::toUnderlying(ParamDefs::x0)] = locPos.x();
457 segPars[Acts::toUnderlying(ParamDefs::y0)] = locPos.y();
463 std::array<double, 4> canvasDim{};
464 const std::size_t parsedPrimSize{primitives.size()};
471 primitives.resize(parsedPrimSize);
474 primitives, canvasDim,
view)) {
479 truthColor, kDotted,
view));
480 paintSimHits(ctx,*segment, primitives,
view);
485 primitives.push_back(
drawLumiSqrtS(0.75,0.21, m_sqrtSLabel, m_lumiLabel));
487 primitives.push_back(
drawLine(segPars, canvasDim[Edges::zLow], canvasDim[Edges::zHigh],
488 parLineColor, kDashed,
view));
491 std::stringstream legendLabel{};
493 legendLabel<<
"Event: "<<ctx.eventID().event_number() <<
", chamber : "<<m_idHelperSvc->toStringChamber(canvasId)
497 if (!extraLabel.empty()) {
498 legendLabel<<
" ("<<extraLabel<<
")";
500 primitives.push_back(
drawLabel(legendLabel.str(), 0.2, 0.96));
503 auto canvas = makeCanvas(ctx, canvasDim,
view);
504 drawPrimitives(*
canvas, primitives);
506 saveCanvas(ctx, canvasId, *
canvas, extraLabel);
508 if (m_canvasLimit <= m_canvCounter) {
510 closeSummaryCanvas();
514 template<
class SpacePo
intType>
517 std::array<double, 4>& canvasDim,
const unsigned int view,
518 unsigned int fillStyle)
const {
526 canvasDim[Edges::yLow] =
std::min(canvasDim[Edges::yLow], hit.localPosition()[
view] - hit.driftRadius());
527 canvasDim[Edges::yHigh] =
std::max(canvasDim[Edges::yHigh], hit.localPosition()[
view] + hit.driftRadius());
528 canvasDim[Edges::zLow] =
std::min(canvasDim[Edges::zLow], hit.localPosition().z() - hit.driftRadius());
529 canvasDim[Edges::zHigh] =
std::max(canvasDim[Edges::zHigh], hit.localPosition().z() + hit.driftRadius());
534 constexpr
int invalidCalibFill = 3305;
535 if constexpr (std::is_same_v<SpacePointType, SpacePoint>) {
540 fillStyle = invalidCalibFill;
543 }
else if constexpr(std::is_same_v<SpacePointType, CalibratedSpacePoint>) {
544 underlyingSp = hit.spacePoint();
548 fillStyle = invalidCalibFill;
556 primitives.push_back(
drawDriftCircle(hit.localPosition(), dc->readoutElement()->innerTubeRadius(),
559 const int circColor = isLabeled(*dc) ? truthColor : kBlue;
560 primitives.push_back(
drawDriftCircle(hit.localPosition(), hit.driftRadius(), circColor, fillStyle));
564 const int boxColor = isLabeled(*meas) ? truthColor : kGreen +2;
565 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->covariance()[
view]);
566 primitives.push_back(
drawBox(hit.localPosition(), boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
567 boxColor, fillStyle));
570 const auto* meas{
static_cast<const xAOD::TgcStrip*
>(underlyingSp->primaryMeasurement())};
571 const int boxColor = isLabeled(*meas) ? truthColor : kCyan + 2;
572 const double boxWidth = 0.5*std::sqrt(12)*std::sqrt(underlyingSp->covariance()[
view]);
573 primitives.push_back(
drawBox(hit.localPosition(), boxWidth, 0.5*meas->readoutElement()->gasGapPitch(),
574 boxColor, fillStyle));
577 const int boxColor = isLabeled(*underlyingSp->primaryMeasurement()) ? truthColor : kAquamarine;
580 boxColor, fillStyle));
585 const int boxColor = isLabeled(*underlyingSp->primaryMeasurement()) ? truthColor : kTeal;
588 boxColor, fillStyle));
591 ATH_MSG_WARNING(
"Please implement proper drawings of the new small wheel.. "<<__FILE__<<
":"<<__LINE__);
598 template<
class SpacePo
intType>
600 const std::vector<SpacePointType>& hitsToDraw,
601 std::vector<PrimitivePtr>& primitives,
602 std::array<double, 4>& canvasDim,
603 unsigned int view)
const {
605 canvasDim[Edges::yLow] = canvasDim[Edges::zLow] = 100. *
Gaudi::Units::m;
606 canvasDim[Edges::yHigh] = canvasDim[Edges::zHigh] = -100. *
Gaudi::Units::m;
609 for (
const SpacePointType& hit : hitsToDraw) {
610 drawnPoints.insert(drawHit(*hit, primitives, canvasDim,
view,
fullFilling));
612 if (m_displayBucket) {
613 for (
const SpacePointBucket::value_type& hit : bucket) {
615 if (drawnPoints.count(hit.get())) {
624 for (
auto & prim : primitives){
625 TBox* theBox =
dynamic_cast<TBox*
>(prim.get());
627 canvasDim[Edges::zLow] =
std::min(canvasDim[Edges::zLow], theBox->GetY1());
628 canvasDim[Edges::zHigh] =
std::max(canvasDim[Edges::zHigh], theBox->GetY2());
632 double width = (canvasDim[Edges::yHigh] - canvasDim[Edges::yLow])*m_canvasExtraScale;
633 double height = (canvasDim[Edges::zHigh] - canvasDim[Edges::zLow])*m_canvasExtraScale;
637 const double midPointX = 0.5 * (canvasDim[Edges::yHigh] + canvasDim[Edges::yLow]);
638 const double midPointY = 0.5 * (canvasDim[Edges::zHigh] + canvasDim[Edges::zLow]);
639 canvasDim[Edges::yLow] = midPointX - 0.5 *
width;
640 canvasDim[Edges::zLow] = midPointY - 0.5 * height;
641 canvasDim[Edges::yHigh] = midPointX + 0.5 *
width;
642 canvasDim[Edges::zHigh] = midPointY + 0.5 * height;
643 return drawnPoints.size() - drawnPoints.count(
nullptr) > 1;
645 template<
class SpacePo
intType>
647 const std::vector<SpacePointType>&
hits,
649 const double legX,
double startLegY,
650 const double endLegY)
const {
656 for (
const SpacePointType& hit :
hits) {
658 bool displayChi2{
true};
659 if constexpr(std::is_same_v<SpacePointType, Segment::MeasType>) {
660 underlyingSp = hit->spacePoint();
669 std::string legendstream{};
670 switch(hit->type()) {
672 const int driftSign{SeedingAux::strawSign(
pos,
dir, *hit)};
673 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
674 legendstream =
std::format(
"ML: {:1d}, TL: {:1d}, T: {:3d}, {:}",
675 idHelper.multilayer(hitId), idHelper.tubeLayer(hitId),
676 idHelper.tube(hitId), driftSign == -1 ?
"L" :
"R");
679 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
680 legendstream=
std::format(
"DR: {:1d}, DZ: {:1d}, GAP: {:1d}, #eta/#phi: {:}/{:}",
681 idHelper.doubletR(hitId), idHelper.doubletZ(hitId), idHelper.gasGap(hitId),
682 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
685 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
686 legendstream =
std::format(
"ST: {:}, GAP: {:1d}, #eta/#phi: {:}/{:}",
687 m_idHelperSvc->stationNameString(hitId), idHelper.gasGap(hitId),
688 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
691 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
692 const auto* clus =
static_cast<const xAOD::MMCluster*
>(underlyingSp->primaryMeasurement());
693 const MuonGMR4::StripDesign& design = clus->readoutElement()->stripLayer(clus->layerHash()).design();
694 legendstream =
std::format(
"ML: {:1d}, GAP: {:1d}, {:}", idHelper.multilayer(hitId), idHelper.gasGap(hitId),
698 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
699 legendstream =
std::format(
"ML: {:1d}, GAP: {:1d}, #eta/#phi: {:}/{:}",
700 idHelper.multilayer(hitId), idHelper.gasGap(hitId),
701 hit->measuresEta() ?
"si" :
"nay", hit->measuresPhi() ?
"si" :
"nay");
704 legendstream =
"Ext. constaint";
710 const double chi2 = SeedingAux::chi2Term(
pos,
dir,*hit);
713 legendstream+=
", #chi^{2}: ---";
715 primitives.push_back(
drawLabel(legendstream, legX, startLegY, 14));
717 if (startLegY<= endLegY) {
723 if (!m_outFile)
return;
724 ATH_MSG_INFO(
"Close summary pdf & root file "<<m_allCanName);
727 m_allCan->SaveAs((m_allCanName +
".pdf]").c_str());
733 const std::array<double, 4>& canvasDim,
734 const int view)
const {
735 std::stringstream canvasName{};
736 canvasName<<
name()<<
"_"<<ctx.eventID().event_number()<<
"_"<<m_canvCounter;
737 ATH_MSG_VERBOSE(
"Create new canvas "<<canvasName.str()<<
" "<<canvasDim);
738 auto canvas = std::make_unique<TCanvas>(canvasName.str().c_str(),
"all", m_canvasWidth, m_canvasHeight);
740 TH1F* frame =
canvas->DrawFrame(canvasDim[Edges::yLow],canvasDim[Edges::zLow], canvasDim[Edges::yHigh], canvasDim[Edges::zHigh]);
742 frame->GetYaxis()->SetTitle(
"z [mm]");
748 const std::string& extraLabel)
const {
750 std::stringstream canvasName{};
751 canvasName<<m_canvasPrefix.value()<<
"_"<<ctx.eventID().event_number()<<
"_"<<(m_canvCounter++)<<
"_"
752 <<m_idHelperSvc->stationNameString(chambId)
753 <<std::abs(m_idHelperSvc->stationEta(chambId))
754 <<(m_idHelperSvc->stationEta(chambId) >0 ?
"A" :
"C")
755 <<m_idHelperSvc->stationPhi(chambId);
756 if (!extraLabel.empty()) canvasName<<
"_"<<removeNonAlphaNum(extraLabel);
758 if (m_saveSinglePDFs) {
759 canvas.SaveAs((
"Plots/" + m_canvasPrefix+
"/" + canvasName.str()+
".pdf").c_str());
761 if (m_saveSummaryPDF) {
762 canvas.SaveAs((m_allCanName+
".pdf").c_str());
764 m_outFile->WriteObject(&
canvas, canvasName.str().c_str());