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 56 of file LegendreSegmentFinderTool.cxx.

59 {
60
61 hitInfos.clear();
62 hitInfos.reserve(driftCircles.size());
63
64 for (const xAOD::MdtDriftCircle* dc : driftCircles) {
65 if (!dc) continue;
66
67 const MuonGMR4::MdtReadoutElement* detEl = dc->readoutElement();
68 if (!detEl) continue;
69
70 // Build global hit coordinates from the MDT measurement
71 const Amg::Transform3D& locToGlob =
72 detEl->localToGlobalTransform(gctx, dc->measurementHash());
73 const Amg::Vector3D gpos = locToGlob * dc->localMeasurementPos();
74
76 info.dc = dc;
77 info.z = static_cast<float>(gpos.z());
78 info.R = static_cast<float>(gpos.perp());
79 info.driftRadius = std::abs(dc->driftRadius());
80
81 hitInfos.push_back(info);
82 }
83 return StatusCode::SUCCESS;
84 }
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const
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 237 of file LegendreSegmentFinderTool.cxx.

240 {
241
243 if (!maxBin.valid) return out;
244
245 const float theta = thetaMin + (static_cast<float>(maxBin.thetaBin) + 0.5f) * m_thetaRes;
246 const float r = rMin + (static_cast<float>(maxBin.rBin) + 0.5f) * m_rRes;
247
248 // Convert the temporary Legendre maximum back to a line in the (z, R) plane
249 if (std::abs(std::sin(theta)) < 1e-6f) return out;
250
251 out.m = -1.f / std::tan(theta);
252 out.b = r / std::sin(theta);
253 out.valid = true;
254
255 return out;
256 }
Scalar theta() const
theta method
int r
Definition globals.cxx:22

◆ 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 124 of file LegendreSegmentFinderTool.cxx.

130 {
131
132 if (thetaBin < 0 || rBin < 0) return;
133 if (thetaBin >= static_cast<int>(bins.size())) return;
134 if (rBin >= static_cast<int>(bins[thetaBin].size())) return;
135
136 BinCell& cell = bins[thetaBin][rBin];
137
138 // Avoid double-counting the same MDT hit in the same Legendre bin
139 auto it = std::find(cell.hits.begin(), cell.hits.end(), dc);
140 if (it != cell.hits.end()) return;
141
142 cell.hits.push_back(dc);
143 cell.zVals.push_back(zPoint);
144 cell.RVals.push_back(rPoint);
145 ++cell.entries;
146 }
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 149 of file LegendreSegmentFinderTool.cxx.

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

117 {
118 const int bin = static_cast<int>(std::floor((value - min) / binSize));
119 if (bin < 0 || bin >= nBins) return -1;
120 return bin;
121 }
#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 189 of file LegendreSegmentFinderTool.cxx.

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

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

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

◆ initialize()

StatusCode L0MDT::LegendreSegmentFinderTool::initialize ( )
overridevirtual

Definition at line 44 of file LegendreSegmentFinderTool.cxx.

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

◆ setLegendreSpacePars()

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

Definition at line 88 of file LegendreSegmentFinderTool.cxx.

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

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: