49 return StatusCode::SUCCESS;
54 const std::vector<const xAOD::MdtDriftCircle*>& driftCircles,
58 std::vector<L0MDT::Segment>& segments)
const {
64 ATH_MSG_DEBUG(
"Size of drift circles vector: " << driftCircles.size()
65 <<
", size of segments vector: " << segments.size());
69 std::vector<HitInfo> hitInfos;
73 if (hitInfos.size() < 2) {
75 return StatusCode::SUCCESS;
80 std::array<std::vector<std::size_t>, 2> hitsPerML;
81 for (std::size_t i = 0; i < hitInfos.size(); ++i) {
82 hitsPerML[hitInfos[i].multilayer].push_back(i);
87 for (
auto& indices : hitsPerML) {
89 [&hitInfos](std::size_t
a, std::size_t b) {
90 return hitInfos[a].driftRadius < hitInfos[b].driftRadius;
95 std::array<std::vector<Cluster>, 2> clustersPerML;
96 std::array<std::optional<Cluster>, 2> bestClusters;
99 for (
int ml = 0; ml < 2; ++ml) {
100 clusterHits(hitInfos, hitsPerML[ml], clustersPerML[ml]);
103 ATH_MSG_INFO(
"ML " << ml <<
" has " << clustersPerML[ml].
size() <<
" clusters");
104 for (
const Cluster& cl : clustersPerML[ml]) {
105 ATH_MSG_INFO(
" refB=" << cl.refB <<
" nHits=" << cl.hitIndices.size());
115 std::vector<float> correctedZ;
116 std::vector<float> correctedR;
117 correctedZ.reserve(hitInfos.size());
118 correctedR.reserve(hitInfos.size());
120 for (
int ml = 0; ml < 2; ++ml) {
121 if (!bestClusters[ml])
continue;
123 const Cluster& cl = *bestClusters[ml];
124 for (std::size_t i = 0; i < cl.hitIndices.size(); ++i) {
125 const HitInfo&
h = hitInfos[cl.hitIndices[i]];
126 const bool plus = cl.plusFlags[i];
131 correctedZ.push_back(
h.z -
h.deltaZ);
132 correctedR.push_back(
h.r +
h.deltaR);
134 correctedZ.push_back(
h.z +
h.deltaZ);
135 correctedR.push_back(
h.r -
h.deltaR);
141 if (correctedZ.size() < 2) {
142 ATH_MSG_DEBUG(
"Not enough corrected hits after cluster selection");
143 return StatusCode::SUCCESS;
150 return StatusCode::SUCCESS;
154 float segZMin = *std::min_element(correctedZ.begin(), correctedZ.end());
155 float segZMax = *std::max_element(correctedZ.begin(), correctedZ.end());
157 for (
float z : correctedZ) {
160 segZRef /=
static_cast<float>(correctedZ.size());
163 float segRRef = fit.m * segZRef + fit.b;
178 segments.push_back(seg);
185 <<
" chi2=" << fit.chi2
186 <<
" nHits=" << correctedZ.size()
187 <<
" zMin=" << segZMin
188 <<
" zMax=" << segZMax
189 <<
" zRef=" << segZRef
190 <<
" rRef=" << segRRef);
191 return StatusCode::SUCCESS;
197 const std::vector<const xAOD::MdtDriftCircle*>& driftCircles,
200 std::vector<HitInfo>& hitInfos)
const {
204 hitInfos.reserve(driftCircles.size());
208 const float slopeNormalization = std::sqrt(1.f + m * m);
219 const int ml = idh.multilayer(
id) - 1;
226 const float zHit = gpos.z();
227 const float rHit = gpos.perp();
233 const float driftRadius = dc->driftRadius();
239 info.driftRadius = driftRadius;
240 info.multilayer = ml;
243 info.bPlus = (rHit - m * zHit) + slopeNormalization * driftRadius;
244 info.bMinus = (rHit - m * zHit) - slopeNormalization * driftRadius;
247 info.deltaZ = (m / slopeNormalization) * driftRadius;
248 info.deltaR = (1.f / slopeNormalization) * driftRadius;
250 hitInfos.push_back(info);
253 return StatusCode::SUCCESS;
258 const std::vector<std::size_t>& orderedIndices,
259 std::vector<Cluster>& clusters)
const {
263 for (std::size_t idx : orderedIndices) {
264 const HitInfo& hit = hitInfos[idx];
265 bool assigned =
false;
270 const float dPlus = std::abs(hit.
bPlus - cl.refB);
271 const float dMinus = std::abs(hit.
bMinus - cl.refB);
275 cl.hitIndices.push_back(idx);
276 cl.plusFlags.push_back(
true);
283 cl.hitIndices.push_back(idx);
284 cl.plusFlags.push_back(
false);
292 if (!assigned &&
static_cast<int>(clusters.size()) + 2 <=
m_maxClusters) {
297 clusters.push_back(std::move(plusCluster));
303 clusters.push_back(std::move(minusCluster));
309 std::optional<CompactSegmentFinderTool::Cluster>
313 if (clusters.empty())
return std::nullopt;
316 std::size_t maxSize = 0;
317 for (
const Cluster& cl : clusters) {
318 maxSize = std::max(maxSize, cl.hitIndices.size());
322 std::vector<const Cluster*> candidates;
323 for (
const Cluster& cl : clusters) {
324 if (cl.hitIndices.size() == maxSize) {
325 candidates.push_back(&cl);
330 auto it = std::min_element(
331 candidates.begin(), candidates.end(),
333 return std::abs(cl_a->refB - rpcB) < std::abs(cl_b->refB - rpcB);
342 const std::vector<float>& rVals,
346 const std::size_t n = zVals.size();
350 if (n < 2 || rVals.size() != n)
return out;
358 for (std::size_t i = 0; i < n; ++i) {
361 sumZZ += zVals[i] * zVals[i];
362 sumZR += zVals[i] * rVals[i];
365 const float N =
static_cast<float>(n);
366 const float den = N * sumZZ - sumZ * sumZ;
369 if (std::abs(den) < 1e-6f)
return out;
372 out.m = (N * sumZR - sumZ * sumR) / den;
373 out.b = (sumR - out.m * sumZ) / N;
377 for (std::size_t i = 0; i < n; ++i) {
378 const float res = (rVals[i] - (out.m * zVals[i] + out.b)) / sigma;
#define ATH_CHECK
Evaluate an expression and check for errors.
std::pair< std::vector< unsigned int >, bool > res
size_t size() const
Number of registered mappings.
Header file for AthHistogramAlgorithm.
Class describing a reconstructed MDT segment used by the L0Muon trigger.
void setNHits(unsigned int x)
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
Amg::Vector3D globalTubePos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the tube mid point in the ATLAS coordinate frame.
double chi2(TH1 *h0, TH1 *h1)
Eigen::Matrix< double, 3, 1 > Vector3D
Compact Segment Finder algorithm overview.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
MdtDriftCircle_v1 MdtDriftCircle