File indexing completed on 2025-01-18 09:11:39
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/TrackFinding/MuonHoughSeeder.hpp"
0010
0011 #include "ActsExamples/EventData/MuonSimHit.hpp"
0012
0013 #include <algorithm>
0014 #include <cmath>
0015 #include <iterator>
0016 #include <ostream>
0017 #include <stdexcept>
0018 #include <variant>
0019
0020 #include "TBox.h"
0021 #include "TLatex.h"
0022 #include "TLegend.h"
0023
0024 namespace {
0025
0026 static const std::map<int, std::string> stationDict{
0027 {0, "BIL"}, {1, "BIS"}, {7, "BIR"}, {2, "BML"}, {3, "BMS"},
0028 {8, "BMF"}, {53, "BME"}, {54, "BMG"}, {52, "BIM"}, {4, "BOL"},
0029 {5, "BOS"}, {9, "BOF"}, {10, "BOG"}, {6, "BEE"}, {14, "EEL"},
0030 {15, "EES"}, {13, "EIL"}, {49, "EIS"}, {17, "EML"}, {18, "EMS"},
0031 {20, "EOL"}, {21, "EOS"}};
0032
0033 }
0034
0035 ActsExamples::MuonHoughSeeder::MuonHoughSeeder(
0036 ActsExamples::MuonHoughSeeder::Config cfg, Acts::Logging::Level lvl)
0037 : ActsExamples::IAlgorithm("MuonHoughSeeder", lvl),
0038 m_cfg(std::move(cfg)),
0039 m_logger(Acts::getDefaultLogger("MuonHoughSeeder", lvl)) {
0040 if (m_cfg.inDriftCircles.empty()) {
0041 throw std::invalid_argument(
0042 "MuonHoughSeeder: Missing drift circle collection");
0043 }
0044 if (m_cfg.inSimHits.empty()) {
0045 throw std::invalid_argument("MuonHoughSeeder: Missing sim hit collection");
0046 }
0047
0048 m_inputDriftCircles.initialize(m_cfg.inDriftCircles);
0049 m_inputSimHits.initialize(m_cfg.inSimHits);
0050 }
0051
0052 using PatternSeed = std::pair<double, double>;
0053
0054 ActsExamples::ProcessCode ActsExamples::MuonHoughSeeder::execute(
0055 const AlgorithmContext& ctx) const {
0056
0057 auto gotSH = m_inputSimHits(ctx);
0058 auto gotDC = m_inputDriftCircles(ctx);
0059
0060
0061 Acts::HoughTransformUtils::HoughPlaneConfig planeCfg;
0062 planeCfg.nBinsX = 1000;
0063 planeCfg.nBinsY = 1000;
0064
0065
0066 Acts::HoughTransformUtils::PeakFinders::IslandsAroundMaxConfig peakFinderCfg;
0067 peakFinderCfg.fractionCutoff = 0.7;
0068 peakFinderCfg.threshold = 3.;
0069 peakFinderCfg.minSpacingBetweenPeaks = {0., 30.};
0070
0071
0072
0073 Acts::HoughTransformUtils::HoughAxisRanges axisRanges{-3., 3., -2000., 2000.};
0074
0075
0076
0077
0078
0079 auto houghParam_fromDC_left = [](double tanTheta, const DriftCircle& DC) {
0080 return DC.y() - tanTheta * DC.z() -
0081 DC.rDrift() / std::cos(std::atan(tanTheta));
0082 };
0083
0084 auto houghParam_fromDC_right = [](double tanTheta, const DriftCircle& DC) {
0085 return DC.y() - tanTheta * DC.z() +
0086 DC.rDrift() / std::cos(std::atan(tanTheta));
0087 };
0088
0089
0090 auto houghWidth_fromDC = [](double, const DriftCircle& DC) {
0091
0092
0093 return std::min(DC.rDriftError() * 3., 1.0);
0094 };
0095
0096
0097 std::vector<PatternSeed> truePatterns;
0098
0099
0100 Acts::HoughTransformUtils::HoughPlane<Acts::GeometryIdentifier::Value>
0101 houghPlane(planeCfg);
0102
0103 Acts::HoughTransformUtils::PeakFinders::IslandsAroundMax<
0104 Acts::GeometryIdentifier::Value>
0105 peakFinder(peakFinderCfg);
0106
0107
0108 for (auto& SH : gotSH) {
0109
0110 MuonMdtIdentifierFields detailedInfo =
0111 ActsExamples::splitId(SH.geometryId().value());
0112
0113 truePatterns.emplace_back(SH.direction().y() / SH.direction().z(),
0114 SH.fourPosition().y());
0115
0116 ACTS_VERBOSE("direction = " << SH.direction().y());
0117 ACTS_VERBOSE("fourposition y = " << SH.fourPosition().y());
0118 std::cin.ignore();
0119
0120 houghPlane.reset();
0121 int foundDC = 0;
0122
0123 for (DriftCircle& DC : gotDC) {
0124 if (DC.stationEta() == detailedInfo.stationEta &&
0125 DC.stationPhi() == detailedInfo.stationPhi &&
0126 DC.stationName() == detailedInfo.stationName) {
0127
0128 MuonMdtIdentifierFields idf;
0129 idf.multilayer = DC.multilayer();
0130 idf.stationEta = DC.stationEta();
0131 idf.stationPhi = DC.stationPhi();
0132 idf.stationName = DC.stationName();
0133 idf.tubeLayer = DC.tubeLayer();
0134 idf.tube = DC.tube();
0135 auto identifier = compressId(idf);
0136 auto effectiveLayer = 3 * (DC.multilayer() - 1) + (DC.tubeLayer() - 1);
0137 ++foundDC;
0138
0139 houghPlane.fill<DriftCircle>(DC, axisRanges, houghParam_fromDC_left,
0140 houghWidth_fromDC, identifier,
0141 effectiveLayer, 1.0);
0142 houghPlane.fill<DriftCircle>(DC, axisRanges, houghParam_fromDC_right,
0143 houghWidth_fromDC, identifier,
0144 effectiveLayer, 1.0);
0145 }
0146 }
0147
0148 auto maxima = peakFinder.findPeaks(houghPlane, axisRanges);
0149
0150
0151
0152 TH2D houghHistoForPlot("houghHist", "HoughPlane;tan(#theta);z0 [mm]",
0153 houghPlane.nBinsX(), axisRanges.xMin,
0154 axisRanges.xMax, houghPlane.nBinsY(),
0155 axisRanges.yMin, axisRanges.yMax);
0156 for (int bx = 0; bx < houghHistoForPlot.GetNbinsX(); ++bx) {
0157 for (int by = 0; by < houghHistoForPlot.GetNbinsY(); ++by) {
0158 houghHistoForPlot.SetBinContent(bx + 1, by + 1,
0159 houghPlane.nHits(bx, by));
0160 }
0161 }
0162 m_outCanvas->SetTitle(Form("Station %s, Eta %i, Phi %i",
0163 stationDict.at(detailedInfo.stationName).c_str(),
0164 static_cast<int>(detailedInfo.stationEta),
0165 static_cast<int>(detailedInfo.stationPhi)));
0166 houghHistoForPlot.SetTitle(
0167 Form("Station %s, Eta %i, Phi %i",
0168 stationDict.at(detailedInfo.stationName).c_str(),
0169 static_cast<int>(detailedInfo.stationEta),
0170 static_cast<int>(detailedInfo.stationPhi)));
0171 m_outCanvas->cd();
0172 int maxHitsAsInt = static_cast<int>(houghPlane.maxHits());
0173 houghHistoForPlot.SetContour(maxHitsAsInt + 1);
0174 for (int k = 0; k < maxHitsAsInt + 1; ++k) {
0175 houghHistoForPlot.SetContourLevel(k, k - 0.5);
0176 }
0177 std::vector<std::unique_ptr<TMarker>> markers;
0178 std::vector<std::unique_ptr<TBox>> boxes;
0179 houghHistoForPlot.SetContourLevel(maxHitsAsInt + 1,
0180 houghHistoForPlot.GetMaximum() + 0.5);
0181 houghHistoForPlot.Draw("COLZ");
0182
0183 auto trueMarker = std::make_unique<TMarker>(
0184 truePatterns.back().first, truePatterns.back().second, kOpenCrossX);
0185 trueMarker->SetMarkerSize(3);
0186 trueMarker->SetMarkerColor(kRed);
0187 trueMarker->Draw();
0188
0189
0190 for (auto& max : maxima) {
0191 markers.push_back(std::make_unique<TMarker>(max.x, max.y, kFullSquare));
0192 markers.back()->SetMarkerSize(1);
0193 markers.back()->SetMarkerColor(kBlue);
0194 markers.back()->Draw();
0195 boxes.push_back(std::make_unique<TBox>(max.x - max.wx, max.y - max.wy,
0196 max.x + max.wx, max.y + max.wy));
0197 boxes.back()->SetLineColor(kBlue);
0198 boxes.back()->SetFillStyle(1001);
0199 boxes.back()->SetFillColorAlpha(kBlue, 0.1);
0200 boxes.back()->SetLineWidth(0);
0201 boxes.back()->Draw();
0202 }
0203 TLegend legend(0.5, 0.7, 1. - gPad->GetRightMargin(),
0204 1. - gPad->GetTopMargin());
0205 legend.AddEntry(trueMarker.get(), "True coordinates");
0206 legend.SetBorderSize(0);
0207 legend.SetFillStyle(0);
0208 legend.Draw();
0209
0210 if (!boxes.empty()) {
0211 legend.AddEntry(markers.back().get(), "Hough maxima");
0212 legend.AddEntry(boxes.back().get(), "Hough uncertainties");
0213 }
0214 TLatex tl(gPad->GetLeftMargin() + 0.03, 1. - gPad->GetTopMargin() - 0.1,
0215 Form("%i drift circles on station", foundDC));
0216 tl.SetTextFont(43);
0217 tl.SetTextSize(24);
0218 tl.SetNDC();
0219 tl.Draw();
0220 m_outCanvas->SaveAs("HoughHistograms.pdf");
0221 }
0222
0223 ACTS_VERBOSE("SH: " << gotSH.size());
0224 ACTS_VERBOSE("DC: " << gotDC.size());
0225 return ActsExamples::ProcessCode::SUCCESS;
0226 }
0227
0228 ActsExamples::ProcessCode ActsExamples::MuonHoughSeeder::initialize() {
0229
0230 m_outCanvas = std::make_unique<TCanvas>("canvas", "", 800, 800);
0231 m_outCanvas->SaveAs("HoughHistograms.pdf[");
0232 m_outCanvas->SetRightMargin(0.12);
0233 m_outCanvas->SetLeftMargin(0.12);
0234 gStyle->SetPalette(kGreyScale);
0235 gStyle->SetOptStat(0);
0236 return ProcessCode::SUCCESS;
0237 }
0238 ActsExamples::ProcessCode ActsExamples::MuonHoughSeeder::finalize() {
0239 m_outCanvas->SaveAs("HoughHistograms.pdf]");
0240 return ProcessCode::SUCCESS;
0241 }