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.");
53 return StatusCode::SUCCESS;
58 const std::vector<const xAOD::MdtDriftCircle*>& driftCircles,
60 std::vector<HitInfo>& hitInfos)
const {
63 hitInfos.reserve(driftCircles.size());
74 const Amg::Vector3D gpos = locToGlob * dc->localMeasurementPos();
78 info.z =
static_cast<float>(gpos.z());
79 info.R =
static_cast<float>(gpos.perp());
80 info.driftRadius = std::abs(dc->driftRadius());
82 hitInfos.push_back(info);
84 return StatusCode::SUCCESS;
101 const float bLocal = seedM + seedB;
106 const float rAxisSize =
static_cast<float>(
m_rBins) *
m_rRes;
111 pars.
rMin = pars.
seedR - 0.5f * rAxisSize;
112 pars.
rMax = pars.
seedR + 0.5f * rAxisSize;
119 const int bin =
static_cast<int>(std::floor((value -
min) / binSize));
120 if (bin < 0 || bin >= nBins)
return -1;
126 std::vector<std::vector<BinCell>>&
bins,
131 float rPoint)
const {
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;
140 auto it = std::find(cell.hits.begin(), cell.hits.end(), dc);
141 if (it != cell.hits.end())
return;
143 cell.hits.push_back(dc);
144 cell.zVals.push_back(zPoint);
145 cell.RVals.push_back(rPoint);
151 const std::vector<HitInfo>& hitInfos,
154 std::vector<std::vector<BinCell>>&
bins)
const {
159 for (
int iTheta = 0; iTheta <
m_thetaBins; ++iTheta) {
160 const float theta = thetaMin + (
static_cast<float>(iTheta) + 0.5f) *
m_thetaRes;
162 const float c = std::cos(
theta);
163 const float s = std::sin(
theta);
167 const float rPlus =
hit.z * c +
hit.R * s +
hit.driftRadius;
168 const float rMinus =
hit.z * c +
hit.R * s -
hit.driftRadius;
170 const float zPlus =
hit.z +
hit.driftRadius * c;
171 const float RPlus =
hit.R +
hit.driftRadius * s;
173 const float zMinus =
hit.z -
hit.driftRadius * c;
174 const float RMinus =
hit.R -
hit.driftRadius * s;
182 if (rBinMinus >= 0) {
191 const std::vector<std::vector<BinCell>>&
bins,
197 std::vector<int> thetaMaxBins;
198 std::vector<int> rMaxBins;
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) {
207 thetaMaxBins.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);
220 const float thetaMean =
221 std::accumulate(thetaMaxBins.begin(), thetaMaxBins.end(), 0.f) /
222 static_cast<float>(thetaMaxBins.size());
225 std::accumulate(rMaxBins.begin(), rMaxBins.end(), 0.f) /
226 static_cast<float>(rMaxBins.size());
228 maxBin.
thetaBin =
static_cast<int>(std::lround(thetaMean));
229 maxBin.
rBin =
static_cast<int>(std::lround(rMean));
247 if (!maxBin.
valid)
return out;
250 const float r = rMin + (
static_cast<float>(maxBin.
rBin) + 0.5f) *
m_rRes;
253 if (std::abs(std::sin(
theta)) < 1e-6f)
return out;
255 out.m = -1.f / std::tan(
theta);
256 out.b =
r / std::sin(
theta);
265 const std::vector<float>& zVals,
266 const std::vector<float>& RVals,
271 const std::size_t n = zVals.size();
272 if (n < 2 || RVals.size() != n)
return out;
279 for (std::size_t i = 0; i < n; ++i) {
282 sumZZ += zVals[i] * zVals[i];
283 sumZR += zVals[i] * RVals[i];
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;
290 out.m = (N * sumZR - sumZ * sumR) / den;
291 out.b = (sumR - out.m * sumZ) / N;
294 for (std::size_t i = 0; i < n; ++i) {
295 const float res = (RVals[i] - (out.m * zVals[i] + out.b)) / sigma;
306 const std::vector<const xAOD::MdtDriftCircle*>& driftCircles,
310 std::vector<L0MDT::Segment>& segments)
const {
314 ATH_MSG_DEBUG(
"In LegendreSegmentFinderTool::findSegments()");
316 <<
", current output segments: " << segments.size());
319 std::vector<HitInfo> hitInfos;
322 if (hitInfos.size() < 2) {
323 ATH_MSG_DEBUG(
"Not enough hits for temporary Legendre segment finding");
324 return StatusCode::SUCCESS;
332 <<
"seedTheta=" << pars.seedTheta
333 <<
" seedR=" << pars.seedR
334 <<
" thetaMin=" << pars.thetaMin
335 <<
" thetaMax=" << pars.thetaMax
336 <<
" rMin=" << pars.rMin
337 <<
" rMax=" << pars.rMax);
341 std::vector<std::vector<BinCell>>
bins;
348 return StatusCode::SUCCESS;
354 ATH_MSG_DEBUG(
"Failed to convert temporary Legendre maximum into a line estimate");
355 return StatusCode::SUCCESS;
358 const float thetaMaxCenter =
360 const float rMaxCenter =
361 pars.rMin + (
static_cast<float>(maxBin.
rBin) + 0.5f) *
m_rRes;
373 <<
"theta=" << thetaMaxCenter
374 <<
" r=" << rMaxCenter
377 <<
" chi2=" << fit.chi2
378 <<
" nHits=" << bestCell.
zVals.size());
398 ATH_MSG_DEBUG(
"Temporary LegendreSegmentFinderTool finished without populating the final segment container");
400 return StatusCode::SUCCESS;
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(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::Isometry3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const override final
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
Tell the compiler to optimize assuming that FP may trap.
#define CXXUTILS_TRAPPING_FP