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.");
52 return StatusCode::SUCCESS;
57 const std::vector<const xAOD::MdtDriftCircle*>& driftCircles,
59 std::vector<HitInfo>& hitInfos)
const {
62 hitInfos.reserve(driftCircles.size());
73 const Amg::Vector3D gpos = locToGlob * dc->localMeasurementPos();
77 info.z =
static_cast<float>(gpos.z());
78 info.R =
static_cast<float>(gpos.perp());
79 info.driftRadius = std::abs(dc->driftRadius());
81 hitInfos.push_back(info);
83 return StatusCode::SUCCESS;
95 pars.seedTheta = std::atan2(-1.f, seedM);
100 const float bLocal = seedM + seedB;
102 pars.seedR = bLocal * std::sin(pars.seedTheta);
105 const float rAxisSize =
static_cast<float>(
m_rBins) *
m_rRes;
107 pars.thetaMin = pars.seedTheta - 0.5f * thetaAxisSize;
108 pars.thetaMax = pars.seedTheta + 0.5f * thetaAxisSize;
110 pars.rMin = pars.seedR - 0.5f * rAxisSize;
111 pars.rMax = pars.seedR + 0.5f * rAxisSize;
118 const int bin =
static_cast<int>(std::floor((value -
min) / binSize));
119 if (bin < 0 || bin >= nBins)
return -1;
125 std::vector<std::vector<BinCell>>&
bins,
130 float rPoint)
const {
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;
139 auto it = std::find(cell.hits.begin(), cell.hits.end(), dc);
140 if (it != cell.hits.end())
return;
142 cell.hits.push_back(dc);
143 cell.zVals.push_back(zPoint);
144 cell.RVals.push_back(rPoint);
150 const std::vector<HitInfo>& hitInfos,
153 std::vector<std::vector<BinCell>>&
bins)
const {
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;
161 const float c = std::cos(
theta);
162 const float s = std::sin(
theta);
166 const float rPlus = hit.z * c + hit.R * s + hit.driftRadius;
167 const float rMinus = hit.z * c + hit.R * s - hit.driftRadius;
169 const float zPlus = hit.z + hit.driftRadius * c;
170 const float RPlus = hit.R + hit.driftRadius * s;
172 const float zMinus = hit.z - hit.driftRadius * c;
173 const float RMinus = hit.R - hit.driftRadius * s;
179 fillBin(
bins, iTheta, rBinPlus, hit.dc, zPlus, RPlus);
181 if (rBinMinus >= 0) {
182 fillBin(
bins, iTheta, rBinMinus, hit.dc, zMinus, RMinus);
190 const std::vector<std::vector<BinCell>>&
bins,
196 std::vector<int> thetaMaxBins;
197 std::vector<int> rMaxBins;
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) {
206 thetaMaxBins.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);
219 const float thetaMean =
220 std::accumulate(thetaMaxBins.begin(), thetaMaxBins.end(), 0.f) /
221 static_cast<float>(thetaMaxBins.size());
224 std::accumulate(rMaxBins.begin(), rMaxBins.end(), 0.f) /
225 static_cast<float>(rMaxBins.size());
227 maxBin.
thetaBin =
static_cast<int>(std::lround(thetaMean));
228 maxBin.
rBin =
static_cast<int>(std::lround(rMean));
243 if (!maxBin.
valid)
return out;
246 const float r = rMin + (
static_cast<float>(maxBin.
rBin) + 0.5f) *
m_rRes;
249 if (std::abs(std::sin(
theta)) < 1e-6f)
return out;
251 out.m = -1.f / std::tan(
theta);
252 out.b =
r / std::sin(
theta);
261 const std::vector<float>& zVals,
262 const std::vector<float>& RVals,
267 const std::size_t n = zVals.size();
268 if (n < 2 || RVals.size() != n)
return out;
275 for (std::size_t i = 0; i < n; ++i) {
278 sumZZ += zVals[i] * zVals[i];
279 sumZR += zVals[i] * RVals[i];
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;
286 out.m = (N * sumZR - sumZ * sumR) / den;
287 out.b = (sumR - out.m * sumZ) / N;
290 for (std::size_t i = 0; i < n; ++i) {
291 const float res = (RVals[i] - (out.m * zVals[i] + out.b)) / sigma;
302 const std::vector<const xAOD::MdtDriftCircle*>& driftCircles,
306 std::vector<L0MDT::Segment>& segments)
const {
310 ATH_MSG_DEBUG(
"In LegendreSegmentFinderTool::findSegments()");
312 <<
", current output segments: " << segments.size());
315 std::vector<HitInfo> hitInfos;
318 if (hitInfos.size() < 2) {
319 ATH_MSG_DEBUG(
"Not enough hits for temporary Legendre segment finding");
320 return StatusCode::SUCCESS;
328 <<
"seedTheta=" << pars.seedTheta
329 <<
" seedR=" << pars.seedR
330 <<
" thetaMin=" << pars.thetaMin
331 <<
" thetaMax=" << pars.thetaMax
332 <<
" rMin=" << pars.rMin
333 <<
" rMax=" << pars.rMax);
337 std::vector<std::vector<BinCell>>
bins;
344 return StatusCode::SUCCESS;
350 ATH_MSG_DEBUG(
"Failed to convert temporary Legendre maximum into a line estimate");
351 return StatusCode::SUCCESS;
354 const float thetaMaxCenter =
356 const float rMaxCenter =
357 pars.rMin + (
static_cast<float>(maxBin.
rBin) + 0.5f) *
m_rRes;
369 <<
"theta=" << thetaMaxCenter
370 <<
" r=" << rMaxCenter
373 <<
" chi2=" << fit.chi2
374 <<
" nHits=" << bestCell.
zVals.size());
394 ATH_MSG_DEBUG(
"Temporary LegendreSegmentFinderTool finished without populating the final segment container");
396 return StatusCode::SUCCESS;
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
std::pair< std::vector< unsigned int >, bool > res
static const std::vector< std::string > bins
size_t size() const
Number of registered mappings.
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
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...
double chi2(TH1 *h0, TH1 *h1)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Compact Segment Finder algorithm overview.
MdtDriftCircle_v1 MdtDriftCircle