ATLAS Offline Software
Loading...
Searching...
No Matches
L0MDT::LegendreSegmentFinderTool Class Reference

#include <LegendreSegmentFinderTool.h>

Inheritance diagram for L0MDT::LegendreSegmentFinderTool:
Collaboration diagram for L0MDT::LegendreSegmentFinderTool:

Classes

struct  HitInfo
struct  BinCell
struct  MaxBin
struct  FitResult
struct  LegendreSpacePars

Public Member Functions

virtual ~LegendreSegmentFinderTool () override=default
virtual StatusCode initialize () override
virtual StatusCode findSegments (const std::vector< const xAOD::MdtDriftCircle * > &driftCircles, const ActsTrk::GeometryContext &gctx, float m, float b, std::vector< L0MDT::Segment > &segments) const override

Private Member Functions

StatusCode buildHitInfo (const std::vector< const xAOD::MdtDriftCircle * > &driftCircles, const ActsTrk::GeometryContext &gctx, std::vector< HitInfo > &hitInfos) const
LegendreSpacePars setLegendreSpacePars (float seedM, float seedB) const
void fillBin (std::vector< std::vector< BinCell > > &bins, int thetaBin, int rBin, const xAOD::MdtDriftCircle *dc, float zPoint, float rPoint) const
void fillSinogram (const std::vector< HitInfo > &hitInfos, float thetaMin, float rMin, std::vector< std::vector< BinCell > > &bins) const
bool findMaxBin (const std::vector< std::vector< BinCell > > &bins, MaxBin &maxBin) const
FitResult extractSegmentFromMaxBin (const MaxBin &maxBin, float thetaMin, float rMin) const
FitResult fitLine (const std::vector< float > &zVals, const std::vector< float > &RVals, float sigma=1.f/8.f) const
int findBin (float value, float min, float binSize, int nBins) const

Private Attributes

int m_thetaBins {64}
float m_thetaRes {0.002f}
int m_rBins {64}
float m_rRes {2.0f}
int m_minEntriesInMaxBin {3}
bool m_doRefit {true}
bool m_debugLegendre {false}

Detailed Description

Definition at line 22 of file LegendreSegmentFinderTool.h.

Constructor & Destructor Documentation

◆ ~LegendreSegmentFinderTool()

virtual L0MDT::LegendreSegmentFinderTool::~LegendreSegmentFinderTool ( )
overridevirtualdefault

Member Function Documentation

◆ buildHitInfo()

StatusCode L0MDT::LegendreSegmentFinderTool::buildHitInfo ( const std::vector< const xAOD::MdtDriftCircle * > & driftCircles,
const ActsTrk::GeometryContext & gctx,
std::vector< HitInfo > & hitInfos ) const
private

Definition at line 57 of file LegendreSegmentFinderTool.cxx.

60 {
61
62 hitInfos.clear();
63 hitInfos.reserve(driftCircles.size());
64
65 for (const xAOD::MdtDriftCircle* dc : driftCircles) {
66 if (!dc) continue;
67
68 const MuonGMR4::MdtReadoutElement* detEl = dc->readoutElement();
69 if (!detEl) continue;
70
71 // Build global hit coordinates from the MDT measurement
72 const Amg::Transform3D& locToGlob =
73 detEl->localToGlobalTransform(gctx, dc->measurementHash());
74 const Amg::Vector3D gpos = locToGlob * dc->localMeasurementPos();
75
77 info.dc = dc;
78 info.z = static_cast<float>(gpos.z());
79 info.R = static_cast<float>(gpos.perp());
80 info.driftRadius = std::abs(dc->driftRadius());
81
82 hitInfos.push_back(info);
83 }
84 return StatusCode::SUCCESS;
85 }
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const override final
Returns the transformation from the local coordinate system of the readout element into the global AT...
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
MdtDriftCircle_v1 MdtDriftCircle

◆ extractSegmentFromMaxBin()

LegendreSegmentFinderTool::FitResult L0MDT::LegendreSegmentFinderTool::extractSegmentFromMaxBin ( const MaxBin & maxBin,
float thetaMin,
float rMin ) const
private

Definition at line 238 of file LegendreSegmentFinderTool.cxx.

241 {
242
243 // Tell clang that FP operations may trap.
245
247 if (!maxBin.valid) return out;
248
249 const float theta = thetaMin + (static_cast<float>(maxBin.thetaBin) + 0.5f) * m_thetaRes;
250 const float r = rMin + (static_cast<float>(maxBin.rBin) + 0.5f) * m_rRes;
251
252 // Convert the temporary Legendre maximum back to a line in the (z, R) plane
253 if (std::abs(std::sin(theta)) < 1e-6f) return out;
254
255 out.m = -1.f / std::tan(theta);
256 out.b = r / std::sin(theta);
257 out.valid = true;
258
259 return out;
260 }
Scalar theta() const
theta method
int r
Definition globals.cxx:22
#define CXXUTILS_TRAPPING_FP
Definition trapping_fp.h:24

◆ fillBin()

void L0MDT::LegendreSegmentFinderTool::fillBin ( std::vector< std::vector< BinCell > > & bins,
int thetaBin,
int rBin,
const xAOD::MdtDriftCircle * dc,
float zPoint,
float rPoint ) const
private

Definition at line 125 of file LegendreSegmentFinderTool.cxx.

131 {
132
133 if (thetaBin < 0 || rBin < 0) return;
134 if (thetaBin >= static_cast<int>(bins.size())) return;
135 if (rBin >= static_cast<int>(bins[thetaBin].size())) return;
136
137 BinCell& cell = bins[thetaBin][rBin];
138
139 // Avoid double-counting the same MDT hit in the same Legendre bin
140 auto it = std::find(cell.hits.begin(), cell.hits.end(), dc);
141 if (it != cell.hits.end()) return;
142
143 cell.hits.push_back(dc);
144 cell.zVals.push_back(zPoint);
145 cell.RVals.push_back(rPoint);
146 ++cell.entries;
147 }
static const std::vector< std::string > bins
size_t size() const
Number of registered mappings.

◆ fillSinogram()

void L0MDT::LegendreSegmentFinderTool::fillSinogram ( const std::vector< HitInfo > & hitInfos,
float thetaMin,
float rMin,
std::vector< std::vector< BinCell > > & bins ) const
private

Definition at line 150 of file LegendreSegmentFinderTool.cxx.

154 {
155
156 bins.assign(m_thetaBins, std::vector<BinCell>(m_rBins));
157
158 for (const HitInfo& hit : hitInfos) {
159 for (int iTheta = 0; iTheta < m_thetaBins; ++iTheta) {
160 const float theta = thetaMin + (static_cast<float>(iTheta) + 0.5f) * m_thetaRes;
161
162 const float c = std::cos(theta);
163 const float s = std::sin(theta);
164
165 // Temporary simplified treatment of the left/right ambiguity:
166 // both tangent branches are filled symmetrically in Legendre space.
167 const float rPlus = hit.z * c + hit.R * s + hit.driftRadius;
168 const float rMinus = hit.z * c + hit.R * s - hit.driftRadius;
169
170 const float zPlus = hit.z + hit.driftRadius * c;
171 const float RPlus = hit.R + hit.driftRadius * s;
172
173 const float zMinus = hit.z - hit.driftRadius * c;
174 const float RMinus = hit.R - hit.driftRadius * s;
175
176 const int rBinPlus = findBin(rPlus, rMin, m_rRes, m_rBins);
177 const int rBinMinus = findBin(rMinus, rMin, m_rRes, m_rBins);
178
179 if (rBinPlus >= 0) {
180 fillBin(bins, iTheta, rBinPlus, hit.dc, zPlus, RPlus);
181 }
182 if (rBinMinus >= 0) {
183 fillBin(bins, iTheta, rBinMinus, hit.dc, zMinus, RMinus);
184 }
185 }
186 }
187 }
bool hit(const Container &ids, int pdgId)
void fillBin(std::vector< std::vector< BinCell > > &bins, int thetaBin, int rBin, const xAOD::MdtDriftCircle *dc, float zPoint, float rPoint) const
int findBin(float value, float min, float binSize, int nBins) const

◆ findBin()

int L0MDT::LegendreSegmentFinderTool::findBin ( float value,
float min,
float binSize,
int nBins ) const
private

Definition at line 118 of file LegendreSegmentFinderTool.cxx.

118 {
119 const int bin = static_cast<int>(std::floor((value - min) / binSize));
120 if (bin < 0 || bin >= nBins) return -1;
121 return bin;
122 }
#define min(a, b)
Definition cfImp.cxx:40

◆ findMaxBin()

bool L0MDT::LegendreSegmentFinderTool::findMaxBin ( const std::vector< std::vector< BinCell > > & bins,
MaxBin & maxBin ) const
private

Definition at line 190 of file LegendreSegmentFinderTool.cxx.

192 {
193
194 maxBin = MaxBin{};
195
196 int maxEntries = 0;
197 std::vector<int> thetaMaxBins;
198 std::vector<int> rMaxBins;
199
200 for (int iTheta = 0; iTheta < static_cast<int>(bins.size()); ++iTheta) {
201 for (int iR = 0; iR < static_cast<int>(bins[iTheta].size()); ++iR) {
202 const int entries = bins[iTheta][iR].entries;
203 if (entries < m_minEntriesInMaxBin) continue;
204
205 if (entries > maxEntries) {
206 maxEntries = entries;
207 thetaMaxBins.clear();
208 rMaxBins.clear();
209 thetaMaxBins.push_back(iTheta);
210 rMaxBins.push_back(iR);
211 } else if (entries == maxEntries) {
212 thetaMaxBins.push_back(iTheta);
213 rMaxBins.push_back(iR);
214 }
215 }
216 }
217
218 if (maxEntries < m_minEntriesInMaxBin || thetaMaxBins.empty()) return false;
219
220 const float thetaMean =
221 std::accumulate(thetaMaxBins.begin(), thetaMaxBins.end(), 0.f) /
222 static_cast<float>(thetaMaxBins.size());
223
224 const float rMean =
225 std::accumulate(rMaxBins.begin(), rMaxBins.end(), 0.f) /
226 static_cast<float>(rMaxBins.size());
227
228 maxBin.thetaBin = static_cast<int>(std::lround(thetaMean));
229 maxBin.rBin = static_cast<int>(std::lround(rMean));
230 maxBin.entries = maxEntries;
231 maxBin.valid = true;
232
233 return true;
234 }
double entries
Definition listroot.cxx:49

◆ findSegments()

StatusCode L0MDT::LegendreSegmentFinderTool::findSegments ( const std::vector< const xAOD::MdtDriftCircle * > & driftCircles,
const ActsTrk::GeometryContext & gctx,
float m,
float b,
std::vector< L0MDT::Segment > & segments ) const
overridevirtual

Definition at line 305 of file LegendreSegmentFinderTool.cxx.

310 {
311
312 segments.clear();
313
314 ATH_MSG_DEBUG("In LegendreSegmentFinderTool::findSegments()");
315 ATH_MSG_DEBUG("Input drift circles: " << driftCircles.size()
316 << ", current output segments: " << segments.size());
317
318 // Step 1: build compact hit information
319 std::vector<HitInfo> hitInfos;
320 ATH_CHECK(buildHitInfo(driftCircles, gctx, hitInfos));
321
322 if (hitInfos.size() < 2) {
323 ATH_MSG_DEBUG("Not enough hits for temporary Legendre segment finding");
324 return StatusCode::SUCCESS;
325 }
326
327 // Step 2: define the Legendre window around the RPC seed
328 const auto pars = setLegendreSpacePars(m, b);
329
330 if (m_debugLegendre) {
331 ATH_MSG_INFO("Temporary Legendre seed window | "
332 << "seedTheta=" << pars.seedTheta
333 << " seedR=" << pars.seedR
334 << " thetaMin=" << pars.thetaMin
335 << " thetaMax=" << pars.thetaMax
336 << " rMin=" << pars.rMin
337 << " rMax=" << pars.rMax);
338 }
339
340 // Step 3: fill the sinogram
341 std::vector<std::vector<BinCell>> bins;
342 fillSinogram(hitInfos, pars.thetaMin, pars.rMin, bins);
343
344 // Step 4: find the maximum
345 MaxBin maxBin;
346 if (!findMaxBin(bins, maxBin)) {
347 ATH_MSG_DEBUG("No valid temporary Legendre maximum found");
348 return StatusCode::SUCCESS;
349 }
350
351 // Step 5: convert the maximum bin into a first line estimate
352 FitResult fit = extractSegmentFromMaxBin(maxBin, pars.thetaMin, pars.rMin);
353 if (!fit.valid) {
354 ATH_MSG_DEBUG("Failed to convert temporary Legendre maximum into a line estimate");
355 return StatusCode::SUCCESS;
356 }
357
358 const float thetaMaxCenter =
359 pars.thetaMin + (static_cast<float>(maxBin.thetaBin) + 0.5f) * m_thetaRes;
360 const float rMaxCenter =
361 pars.rMin + (static_cast<float>(maxBin.rBin) + 0.5f) * m_rRes;
362
363 // Step 6: optional straight-line refit using tangent points stored in the max bin
364 const BinCell& bestCell = bins[maxBin.thetaBin][maxBin.rBin];
365 if (m_doRefit && bestCell.zVals.size() >= 2) {
366 FitResult refit = fitLine(bestCell.zVals, bestCell.RVals);
367 if (refit.valid) {
368 fit = refit;
369 }
370 }
371
372 ATH_MSG_DEBUG("Temporary LT line estimate | "
373 << "theta=" << thetaMaxCenter
374 << " r=" << rMaxCenter
375 << " m=" << fit.m
376 << " b=" << fit.b
377 << " chi2=" << fit.chi2
378 << " nHits=" << bestCell.zVals.size());
379
380 // Temporary validation-only status:
381 // the fitted line parameters are computed and logged, but the final
382 // L0MDT::Segment EDM object is not yet fully filled and stored.
383 //
384 // Future updates are expected to:
385 // - define the final segment EDM content
386 // - populate the segment object consistently
387 // - validate the parameterization and quality variables
388 //
389 // Example placeholder:
390 //
391 // L0MDT::Segment seg;
392 // seg.setM(fit.m);
393 // seg.setB(fit.b);
394 // seg.setChi2(fit.chi2);
395 // seg.setNHits(bestCell.zVals.size());
396 // segments.push_back(seg);
397
398 ATH_MSG_DEBUG("Temporary LegendreSegmentFinderTool finished without populating the final segment container");
399
400 return StatusCode::SUCCESS;
401 }
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_INFO(x,...)
FitResult extractSegmentFromMaxBin(const MaxBin &maxBin, float thetaMin, float rMin) const
FitResult fitLine(const std::vector< float > &zVals, const std::vector< float > &RVals, float sigma=1.f/8.f) const
LegendreSpacePars setLegendreSpacePars(float seedM, float seedB) const
void fillSinogram(const std::vector< HitInfo > &hitInfos, float thetaMin, float rMin, std::vector< std::vector< BinCell > > &bins) const
bool findMaxBin(const std::vector< std::vector< BinCell > > &bins, MaxBin &maxBin) const
StatusCode buildHitInfo(const std::vector< const xAOD::MdtDriftCircle * > &driftCircles, const ActsTrk::GeometryContext &gctx, std::vector< HitInfo > &hitInfos) const

◆ fitLine()

LegendreSegmentFinderTool::FitResult L0MDT::LegendreSegmentFinderTool::fitLine ( const std::vector< float > & zVals,
const std::vector< float > & RVals,
float sigma = 1.f / 8.f ) const
private

Definition at line 264 of file LegendreSegmentFinderTool.cxx.

267 {
268
270
271 const std::size_t n = zVals.size();
272 if (n < 2 || RVals.size() != n) return out;
273
274 float sumZ = 0.f;
275 float sumR = 0.f;
276 float sumZZ = 0.f;
277 float sumZR = 0.f;
278
279 for (std::size_t i = 0; i < n; ++i) {
280 sumZ += zVals[i];
281 sumR += RVals[i];
282 sumZZ += zVals[i] * zVals[i];
283 sumZR += zVals[i] * RVals[i];
284 }
285
286 const float N = static_cast<float>(n);
287 const float den = N * sumZZ - sumZ * sumZ;
288 if (std::abs(den) < 1e-6f) return out;
289
290 out.m = (N * sumZR - sumZ * sumR) / den;
291 out.b = (sumR - out.m * sumZ) / N;
292
293 float chi2 = 0.f;
294 for (std::size_t i = 0; i < n; ++i) {
295 const float res = (RVals[i] - (out.m * zVals[i] + out.b)) / sigma;
296 chi2 += res * res;
297 }
298
299 out.chi2 = chi2;
300 out.valid = true;
301 return out;
302 }
std::pair< std::vector< unsigned int >, bool > res
double chi2(TH1 *h0, TH1 *h1)
constexpr std::size_t N

◆ initialize()

StatusCode L0MDT::LegendreSegmentFinderTool::initialize ( )
overridevirtual

Definition at line 45 of file LegendreSegmentFinderTool.cxx.

45 {
46 ATH_MSG_DEBUG("Initializing " << name() << "...");
47
49 "LegendreSegmentFinderTool is currently a temporary and simplified validation "
50 "implementation. It is not a full standalone-equivalent Legendre segment finder, "
51 "and the output segment container is not yet fully populated.");
52
53 return StatusCode::SUCCESS;
54 }
#define ATH_MSG_WARNING(x,...)

◆ setLegendreSpacePars()

LegendreSegmentFinderTool::LegendreSpacePars L0MDT::LegendreSegmentFinderTool::setLegendreSpacePars ( float seedM,
float seedB ) const
private

Definition at line 89 of file LegendreSegmentFinderTool.cxx.

89 {
90
92
93 // Temporary simplified conversion from seed line to Legendre-space coordinates.
94 // This parameterization is currently used only to define a validation window
95 // around the RPC seed and may need to be refined in future updates.
96 pars.seedTheta = std::atan2(-1.f, seedM);
97
98 // Temporary local intercept model used to center the r window.
99 // This is part of the current simplified implementation and is not yet
100 // a fully validated detector- or sector-aware treatment.
101 const float bLocal = seedM + seedB;
102
103 pars.seedR = bLocal * std::sin(pars.seedTheta);
104
105 const float thetaAxisSize = static_cast<float>(m_thetaBins) * m_thetaRes;
106 const float rAxisSize = static_cast<float>(m_rBins) * m_rRes;
107
108 pars.thetaMin = pars.seedTheta - 0.5f * thetaAxisSize;
109 pars.thetaMax = pars.seedTheta + 0.5f * thetaAxisSize;
110
111 pars.rMin = pars.seedR - 0.5f * rAxisSize;
112 pars.rMax = pars.seedR + 0.5f * rAxisSize;
113
114 return pars;
115 }

Member Data Documentation

◆ m_debugLegendre

bool L0MDT::LegendreSegmentFinderTool::m_debugLegendre {false}
private

Definition at line 117 of file LegendreSegmentFinderTool.h.

117{false};

◆ m_doRefit

bool L0MDT::LegendreSegmentFinderTool::m_doRefit {true}
private

Definition at line 116 of file LegendreSegmentFinderTool.h.

116{true};

◆ m_minEntriesInMaxBin

int L0MDT::LegendreSegmentFinderTool::m_minEntriesInMaxBin {3}
private

Definition at line 115 of file LegendreSegmentFinderTool.h.

115{3};

◆ m_rBins

int L0MDT::LegendreSegmentFinderTool::m_rBins {64}
private

Definition at line 113 of file LegendreSegmentFinderTool.h.

113{64};

◆ m_rRes

float L0MDT::LegendreSegmentFinderTool::m_rRes {2.0f}
private

Definition at line 114 of file LegendreSegmentFinderTool.h.

114{2.0f};

◆ m_thetaBins

int L0MDT::LegendreSegmentFinderTool::m_thetaBins {64}
private

Definition at line 111 of file LegendreSegmentFinderTool.h.

111{64};

◆ m_thetaRes

float L0MDT::LegendreSegmentFinderTool::m_thetaRes {0.002f}
private

Definition at line 112 of file LegendreSegmentFinderTool.h.

112{0.002f};

The documentation for this class was generated from the following files: