ATLAS Offline Software
Loading...
Searching...
No Matches
SpacePointMakerAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
5
11#include <GaudiKernel/IMessageSvc.h>
12#include <memory>
13#include <sstream>
14#include <optional>
15#include <type_traits>
22
23
24#include "Acts/Surfaces/detail/LineHelper.hpp"
25namespace {
26 using CovIdx = MuonR4::SpacePoint::CovIdx;
27
28 inline std::vector<std::shared_ptr<unsigned>> matchCountVec(unsigned n) {
29 std::vector<std::shared_ptr<unsigned>> out{};
30 out.reserve(n);
31 for (unsigned p = 0; p < n ;++p) {
32 out.emplace_back(std::make_shared<unsigned>(0));
33 }
34 return out;
35 }
41 template<class MeasType>
42 #if defined(FLATTEN)
43 // We compile this package with optimization, even in debug builds; otherwise,
44 // the heavy use of Eigen makes it too slow. However, from here we may call
45 // to out-of-line Eigen code that is linked from other DSOs; in that case,
46 // it would not be optimized. Avoid this by forcing all Eigen code
47 // to be inlined here if possible.
49 #endif
50 Amg::Transform3D toChamberTransform(const ActsTrk::GeometryContext& gctx,
51 const Amg::Transform3D& sectorTrans,
52 const MeasType& meas) {
53 const MuonGMR4::MuonReadoutElement* reEle{meas.readoutElement()};
54 if constexpr(std::is_same_v<MeasType, xAOD::MdtDriftCircle>) {
55 return sectorTrans * reEle->localToGlobalTransform(gctx, meas.measurementHash());
56 } else {
57 return sectorTrans * reEle->localToGlobalTransform(gctx, meas.layerHash());
58 }
59 }
62 template <typename PrdType>
63 double sensorHalfLength(const PrdType& prd) {
64 const auto* re = prd.readoutElement();
65 if constexpr(std::is_same_v<PrdType, xAOD::MdtDriftCircle>) {
66 return 0.5 * re->activeTubeLength(prd.measurementHash());
67 } else if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement>) {
68 return 0.5*(prd.measuresPhi() ? re->stripPhiLength() : re->stripEtaLength());
69 } else if constexpr(std::is_same_v<PrdType, xAOD::TgcStrip>) {
70 return 0.5 * re->sensorLayout(prd.layerHash())->design(prd.measuresPhi()).stripLength(prd.channelNumber());
71 } else if constexpr(std::is_same_v<PrdType, xAOD::MMCluster>) {
72 return 0.5* re->stripLayer(prd.layerHash()).design().stripLength(prd.channelNumber());
73 } else if constexpr(std::is_same_v<PrdType, xAOD::sTgcMeasurement>) {
74 return 0.5* re->stripLayer(prd.layerHash()).design().stripLength(prd.channelNumber());
75 }
76 return 0.;
77 }
82 inline double covElement(const xAOD::sTgcMeasurement& m,
83 const CovIdx covIdx) {
84 if (m.numDimensions() == 2) {
85 const unsigned i = (covIdx != CovIdx::etaCov);
86 return m.localCovariance<2>()(i,i);
87 }
88 return m.localCovariance<1>()[0];
89 }
90}
91
92namespace MuonR4 {
93
98 if (techIdx != other.techIdx) {
99 return static_cast<int>(techIdx) < static_cast<int>(other.techIdx);
100 }
101 if (stIdx != other.stIdx) {
102 return static_cast<int>(stIdx) < static_cast<int>(other.stIdx);
103 }
104 return eta < other.eta;
105}
111
112void SpacePointMakerAlg::SpacePointStatistics::addToStat(const std::vector<SpacePoint>& spacePoints){
113 std::lock_guard guard{m_mutex};
114 for (const SpacePoint& sp : spacePoints){
115 FieldKey key{};
116 key.stIdx = m_idHelperSvc->stationIndex(sp.identify());
117 key.techIdx = m_idHelperSvc->technologyIndex(sp.identify());
118 key.eta = m_idHelperSvc->stationEta(sp.identify());
119 StatField & stats = m_map[key];
120 if (sp.measuresEta() && sp.measuresPhi()) {
121 ++stats.measEtaPhi;
122 } else {
123 stats.measEta += sp.measuresEta();
124 stats.measPhi += sp.measuresPhi();
125 }
126 }
127}
129 using KeyVal = std::pair<FieldKey, StatField>;
130 std::vector<KeyVal> sortedstats{};
131 sortedstats.reserve(m_map.size());
133 for (const auto & [key, stats] : m_map){
134 sortedstats.emplace_back(std::make_pair(key, stats));
135 }
136 std::stable_sort(sortedstats.begin(), sortedstats.end(), [](const KeyVal& a, const KeyVal&b) {
137 return a.second.allHits() > b.second.allHits();
138 });
139 msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
140 for (const auto & [key, stats] : sortedstats) {
141 msg<<MSG::ALWAYS<<" "<<Muon::MuonStationIndex::technologyName(key.techIdx)
142 <<" "<<Muon::MuonStationIndex::stName(key.stIdx)
143 <<" "<<std::abs(key.eta)<<(key.eta < 0 ? "A" : "C")
144 <<" "<<std::setw(8)<<stats.measEtaPhi
145 <<" "<<std::setw(8)<<stats.measEta
146 <<" "<<std::setw(8)<<stats.measPhi<<endmsg;
147 }
148 msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
149
150}
151
155 if (m_statCounter) {
156 m_statCounter->dumpStatisics(msgStream());
157 }
158 return StatusCode::SUCCESS;
159}
161 ATH_CHECK(m_geoCtxKey.initialize());
162 ATH_CHECK(m_mdtKey.initialize(!m_mdtKey.empty()));
163 ATH_CHECK(m_rpcKey.initialize(!m_rpcKey.empty()));
164 ATH_CHECK(m_tgcKey.initialize(!m_tgcKey.empty()));
165 ATH_CHECK(m_mmKey.initialize(!m_mmKey.empty()));
166 ATH_CHECK(m_stgcKey.initialize(!m_stgcKey.empty()));
167 ATH_CHECK(m_idHelperSvc.retrieve());
168 ATH_CHECK(m_writeKey.initialize());
169 if (m_doStat) {
170 m_statCounter = std::make_unique<SpacePointStatistics>(m_idHelperSvc.get());
171 }
172
173
174 //Initialize the chamber-based bucket windows and max bucket lengths
176 .spacePointWindow = m_spacePointWindow.value(),
177 .maxBucketLength = m_maxBucketLength.value(),
178 .spacePointOverlap= m_spacePointOverlap.value()
179 };
180
181 ATH_CHECK(detStore()->retrieve(m_detMgr));
182 const auto chambers = m_detMgr->getAllChambers();
183
184 m_bucketParameters.reserve(chambers.size());
185 for (const MuonGMR4::Chamber* chamber : chambers) {
186 const std::optional<BucketParameters> parameters = resolveBucketParameters(*chamber);
187
188 //Fill only the chambers for which we have at least one match, the rest will be filled with the default parameters on demand
189 if (!parameters) {
190 continue;
191 }
192
193 m_bucketParameters.emplace( chamber, *parameters);
194 }
195
196 ATH_MSG_DEBUG( "Configured chamber-dependent bucket parameters for " << m_bucketParameters.size() << " chambers out of " << chambers.size());
197
198
199 return StatusCode::SUCCESS;
200}
201
202template <>
204 const PrdVec_t<const xAOD::TgcStrip*>& phiHits) const {
205 if (etaHits.empty() || phiHits.empty()) {
206 return false;
207 }
208 const MuonGMR4::TgcReadoutElement* re = etaHits[0]->readoutElement();
209 ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
210 return ((1.*etaHits.size()) / ((1.*re->numChannels(etaHits[0]->measurementHash())))) < m_maxOccTgcEta &&
211 ((1.*phiHits.size()) / ((1.*re->numChannels(phiHits[0]->measurementHash())))) < m_maxOccTgcPhi;
212 }
213template <>
215 const PrdVec_t<const xAOD::RpcMeasurement*>& phiHits) const {
216 if (etaHits.empty() || phiHits.empty()) {
217 return false;
218 }
219 const MuonGMR4::RpcReadoutElement* re = etaHits[0]->readoutElement();
220 ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
221 return ((1.*etaHits.size()) / (1.*re->nEtaStrips())) < m_maxOccRpcEta &&
222 ((1.*phiHits.size()) / (1.*re->nPhiStrips())) < m_maxOccRpcPhi;
223 }
224
225template <>
227 const PrdVec_t<const xAOD::MMCluster*>& /*phiHits*/) const {
228 return false;
229 }
230template <typename PrdType>
232 const Amg::Transform3D& sectorTrans,
233 const PrdVec_t<const PrdType*>& prdsToFill,
234 std::vector<SpacePoint>& outColl) const {
235 if (prdsToFill.empty()) {
236 return;
237 }
238 const PrdType* refMeas = prdsToFill.front();
239 bool allSpArePhi{false};
240
241 const Amg::Transform3D toSectorTrans = toChamberTransform(gctx, sectorTrans, *refMeas);
243 Amg::Vector3D sensorDir{Amg::Vector3D::Zero()}, toNextSen{Amg::Vector3D::Zero()};
245 if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement> ||
246 std::is_same_v<PrdType, xAOD::TgcStrip>) {
247 allSpArePhi = refMeas->measuresPhi();
248 const auto& stripLayout = refMeas->readoutElement()->sensorLayout(refMeas->layerHash());
249 const auto& design = stripLayout->design(allSpArePhi);
250 sensorDir = toSectorTrans.linear() * stripLayout->to3D(design.stripDir(), allSpArePhi);
251 toNextSen = toSectorTrans.linear() * stripLayout->to3D(design.stripNormal(), allSpArePhi);
252 ATH_MSG_VERBOSE("Fill space points for "<<m_idHelperSvc->toString(refMeas->identify())
253 <<" -> sensor: "<<Amg::toString(sensorDir)<<", "<<Amg::toString(toNextSen));
254 } else if constexpr (std::is_same_v<PrdType, xAOD::sTgcMeasurement>){
255 allSpArePhi = refMeas->channelType() == xAOD::sTgcMeasurement::sTgcChannelTypes::Wire;
256 const auto& stripLayout = refMeas->readoutElement()->stripLayer(refMeas->measurementHash());
257 const auto& design = stripLayout.design(allSpArePhi);
258 sensorDir = toSectorTrans.linear() * stripLayout.to3D(design.stripDir(), allSpArePhi);
259 toNextSen = toSectorTrans.linear() * stripLayout.to3D(design.stripNormal(), allSpArePhi);
260 } else {
261 sensorDir = toSectorTrans.linear().col(Amg::y);
262 toNextSen = toSectorTrans.linear().col(Amg::x);
263 }
264 outColl.reserve(outColl.size() + prdsToFill.size());
265 for (const PrdType* prd: prdsToFill) {
266 SpacePoint& newSp = outColl.emplace_back(prd);
267 if constexpr (std::is_same_v<PrdType, xAOD::TgcStrip>) {
268 if (allSpArePhi) {
269 const auto& stripLayout = refMeas->readoutElement()->sensorLayout(refMeas->layerHash());
270 const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLayout->design(allSpArePhi));
271 toNextSen = toSectorTrans.linear() * stripLayout->to3D(radialDesign.stripNormal(prd->channelNumber()), allSpArePhi);
272 sensorDir = toSectorTrans.linear() * stripLayout->to3D(radialDesign.stripDir(prd->channelNumber()), allSpArePhi);
273 }
274 }
275 newSp.setPosition(toSectorTrans * prd->localMeasurementPos());
276 newSp.setDirection(sensorDir, toNextSen);
277 auto cov = Acts::filledArray<double,3>(0.);
278 if (prd->numDimensions() == 2) {
279 cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<2>()(0,0);
280 cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<2>()(1,1);
281 } else {
283 auto covIdx{Acts::toUnderlying(CovIdx::etaCov)},
284 lenIdx{Acts::toUnderlying(CovIdx::phiCov)};
285 if (!newSp.measuresEta()) {
286 std::swap(covIdx, lenIdx);
287 }
288 cov[covIdx] = prd->template localCovariance<1>()[0];
289 cov[lenIdx] = Acts::square(sensorHalfLength(*prd));
290 }
291 newSp.setCovariance(std::move(cov));
292 }
293}
294
295
296template <typename ContType>
299 std::vector<EtaPhi2DHits<typename ContType::const_value_type>> hitsPerGasGap{};
300 for (const auto& prd : viewer) {
301 ATH_MSG_VERBOSE("Create space point from "<<m_idHelperSvc->toString(prd->identify())
302 <<", hash: "<<prd->identifierHash());
303
304 unsigned gapIdx = prd->gasGap() -1;
305 if constexpr (std::is_same_v<ContType, xAOD::RpcMeasurementContainer>) {
306 gapIdx = prd->readoutElement()->createHash(0, prd->gasGap(), prd->doubletPhi(), false);
307 }
308 if (hitsPerGasGap.size() <= gapIdx) {
309 hitsPerGasGap.resize(gapIdx + 1);
310 }
311 bool measPhi{false};
312 if constexpr(std::is_same_v<ContType, xAOD::sTgcMeasContainer>) {
314 measPhi = prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
315 } else if constexpr(!std::is_same_v<ContType, xAOD::MMClusterContainer>) {
317 measPhi = prd->measuresPhi();
318 }
319
320 if (prd->numDimensions() == 2) {
321 hitsPerGasGap[gapIdx][2].push_back(prd);
322 continue;
323 }
325 auto& toPush = hitsPerGasGap[gapIdx][measPhi];
326 if (toPush.capacity() == toPush.size()) {
327 toPush.reserve(toPush.size() + m_capacityBucket);
328 }
329 toPush.push_back(prd);
330 }
331 return hitsPerGasGap;
332}
333
334template <typename ContType>
335 StatusCode SpacePointMakerAlg::loadContainerAndSort(const EventContext& ctx,
337 PreSortedSpacePointMap& fillContainer) const {
338 const ContType* measurementCont{nullptr};
339 ATH_CHECK(SG::get(measurementCont, key, ctx));
340 if (!measurementCont || measurementCont->empty()){
341 ATH_MSG_DEBUG("nothing to do");
342 return StatusCode::SUCCESS;
343 }
344 const ActsTrk::GeometryContext* gctx{nullptr};
345 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
346
347 xAOD::ChamberViewer viewer{*measurementCont};
348
349 do {
350 SpacePointsPerChamber& pointsInChamb = fillContainer[viewer.at(0)->readoutElement()->msSector()];
351 const Amg::Transform3D sectorTrans = viewer.at(0)->readoutElement()->msSector()->globalToLocalTransform(*gctx);
352 ATH_MSG_DEBUG("Fill space points for chamber "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
353 if constexpr( std::is_same_v<ContType, xAOD::MdtDriftCircleContainer>) {
354 pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.capacity() + viewer.size());
355 for (const auto& prd : viewer) {
356 Amg::Transform3D toChamberTrans{toChamberTransform(*gctx, sectorTrans, *prd)};
357 SpacePoint& sp{pointsInChamb.etaHits.emplace_back(prd)};
358 sp.setPosition(toChamberTrans*prd->localMeasurementPos());
359 sp.setDirection(toChamberTrans.linear().col(Amg::z),
360 toChamberTrans.linear().col(Amg::y));
361 std::array<double, 3> cov{Acts::filledArray<double,3>(0.)};
362 cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->driftRadiusCov();
363 cov[Acts::toUnderlying(CovIdx::phiCov)] = Acts::square(sensorHalfLength(*prd));
364 if (ATH_UNLIKELY(prd->numDimensions() == 2)){
365 cov[Acts::toUnderlying(CovIdx::phiCov)] = static_cast<const xAOD::MdtTwinDriftCircle*>(prd)->posAlongWireCov();
366 }
367 sp.setCovariance(std::move(cov));
368 }
369 } else {
371 for (auto& [etaHits, phiHits, two2DHits] : splitHitsPerGasGap(viewer)) {
372 ATH_MSG_DEBUG("Found "<<etaHits.size()<<"/"<<phiHits.size()
373 <<" 1D and "<<two2DHits.size()<<" 2D hits in chamber "
374 <<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
376 fillUncombinedSpacePoints(*gctx, sectorTrans, two2DHits, pointsInChamb.etaHits);
378 // Check if we do not have 2D occupancy (missing phi or eta hits)
379 if (!passOccupancy2D(etaHits, phiHits)) {
380 fillUncombinedSpacePoints(*gctx, sectorTrans, etaHits, pointsInChamb.etaHits);
381 fillUncombinedSpacePoints(*gctx, sectorTrans, phiHits, pointsInChamb.phiHits);
382 continue;
383 }
384
385 std::vector<std::shared_ptr<unsigned>> etaCounts{matchCountVec(etaHits.size())},
386 phiCounts{matchCountVec(phiHits.size())};
387
388 pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.size() + etaHits.size()*phiHits.size());
390 const auto& firstEta{etaHits.front()};
391 const Amg::Transform3D toSectorTrans = toChamberTransform(*gctx, sectorTrans, *firstEta);
392
393 Amg::Vector3D toNextDir{Amg::Vector3D::Zero()}, sensorDir{Amg::Vector3D::Zero()};
394 if constexpr (std::is_same_v<xAOD::RpcMeasurementContainer, ContType> ||
395 std::is_same_v<xAOD::TgcStripContainer, ContType>) {
396 const auto& stripLayout = firstEta->readoutElement()->sensorLayout(firstEta->layerHash());
397 const auto& design = stripLayout->design();
398 sensorDir = toSectorTrans.linear() * stripLayout->to3D(design.stripDir(), false);
399 toNextDir = toSectorTrans.linear() * stripLayout->to3D(design.stripNormal(), false);
400 } else if constexpr (std::is_same_v<xAOD::sTgcMeasContainer, ContType>){
401 const auto& stripLayout = firstEta->readoutElement()->stripLayer(firstEta->measurementHash());
402 const auto& design = stripLayout.design(false);
403 sensorDir = toSectorTrans.linear() * stripLayout.to3D(design.stripDir(), false);
404 toNextDir = toSectorTrans.linear() * stripLayout.to3D(design.stripNormal(), false);
405 } else {
406 ATH_MSG_ERROR("Unsupported container type");
407 return StatusCode::FAILURE;
408 }
409
410 using namespace Acts::detail::LineHelper;
411 for (unsigned etaP = 0; etaP < etaHits.size(); ++etaP) {
413 for (unsigned phiP = 0; phiP < phiHits.size(); ++ phiP) {
415 if constexpr(std::is_same_v<xAOD::TgcStripContainer, ContType>) {
416 if (!(etaHits[etaP]->bcBitMap() & phiHits[phiP]->bcBitMap())){
417 continue;
418 }
419 const auto& stripLay = phiHits[phiP]->readoutElement()->sensorLayout(phiHits[phiP]->layerHash());
420 const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(true));
421 toNextDir = toSectorTrans.linear() * stripLay->to3D(radialDesign.stripDir(phiHits[phiP]->channelNumber()), true);
422 }
423
424 SpacePoint& newSp = pointsInChamb.etaHits.emplace_back(etaHits[etaP], phiHits[phiP]);
425 newSp.setInstanceCounts(etaCounts[etaP], phiCounts[phiP]);
426
427 auto spIsect = lineIntersect(toSectorTrans*etaHits[etaP]->localMeasurementPos(), sensorDir,
428 toSectorTrans*phiHits[phiP]->localMeasurementPos(), toNextDir);
429 newSp.setPosition(spIsect.position());
430 newSp.setDirection(sensorDir, toNextDir);
431 auto cov = Acts::filledArray<double, 3>(0.);
432 cov[Acts::toUnderlying(CovIdx::etaCov)] = etaHits[etaP]->template localCovariance<1>()[0];
433 cov[Acts::toUnderlying(CovIdx::phiCov)] = phiHits[phiP]->template localCovariance<1>()[0];
435 if constexpr(std::is_same_v<xAOD::TgcStripContainer, ContType>) {
436 const auto& stripLay = phiHits[phiP]->readoutElement()->sensorLayout(phiHits[phiP]->layerHash());
437 const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(true));
438 const Amg::Vector2D planePos = stripLay->to2D(toSectorTrans.inverse()*spIsect.position(), true);
439 cov[Acts::toUnderlying(CovIdx::phiCov)] =
440 Acts::square(radialDesign.stripPitch(phiHits[phiP]->channelNumber(), planePos)) / 12.;
441 }
442
443 newSp.setCovariance(std::move(cov));
444 ATH_MSG_VERBOSE("Created new space point "<<newSp);
445 }
446 }
447 }
448 }
449 } while (viewer.next());
450 return StatusCode::SUCCESS;
451}
452
453template<>
454StatusCode SpacePointMakerAlg::loadContainerAndSort(const EventContext& ctx,
456 PreSortedSpacePointMap& fillContainer) const {
457
458 const xAOD::sTgcMeasContainer* measurementCont{nullptr};
459 ATH_CHECK(SG::get(measurementCont, key, ctx));
460 if (!measurementCont || measurementCont->empty()){
461 ATH_MSG_DEBUG("nothing to do");
462 return StatusCode::SUCCESS;
463 }
464 const ActsTrk::GeometryContext* gctx{nullptr};
465 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
466 xAOD::ChamberViewer viewer{*measurementCont};
467 using namespace Acts::detail::LineHelper;
468 do {
469 SpacePointsPerChamber& pointsInChamb = fillContainer[viewer.at(0)->readoutElement()->msSector()];
470 const Amg::Transform3D sectorTrans = viewer.at(0)->readoutElement()->msSector()->globalToLocalTransform(*gctx);
471 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Fill space points for multiplet "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
472 for(auto& HitColls: splitHitsPerGasGap(viewer)){
473 auto& [etaHits, phiHits, two2DHits] = HitColls;
474 std::array<std::vector<std::shared_ptr<unsigned>>, 3> instanceCounts{matchCountVec(etaHits.size()),
475 matchCountVec(phiHits.size()),
476 matchCountVec(two2DHits.size())};
477
478 //loop through the Prds and try to combine according` to the hierarchy
479 // Strip+Wire
480 // Strip+Pad
481 // Wire+Pad
482 // Pad
490 auto combineMe = [&](const std::size_t collIdxA,
491 const std::size_t collIdxB,
492 const std::function<bool(const xAOD::sTgcMeasurement*,
493 const xAOD::sTgcMeasurement*)>& combFunc) {
494 std::vector<char> combinedFlagsA{}, combinedFlagsB{};
495 std::ranges::transform(instanceCounts[collIdxA], std::back_inserter(combinedFlagsA),
496 [](const std::shared_ptr<unsigned>& countPtr){
497 return (*countPtr) == 0;
498 });
499 std::ranges::transform(instanceCounts[collIdxB], std::back_inserter(combinedFlagsB),
500 [](const std::shared_ptr<unsigned>& countPtr){
501 return (*countPtr) == 0;
502 });
503
504 const auto& collA = HitColls[collIdxA];
505 const auto& collB = HitColls[collIdxB];
506
508 if(collA.empty() || collB.empty()) {
509 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Skipping combination: both collections empty");
510 return;
511 }
512
514 const xAOD::sTgcMeasurement* firstHit = collB.front();
515 const Amg::Transform3D toSectorTrans = toChamberTransform(*gctx, sectorTrans, *firstHit);
516
517 for(std::size_t idxA = 0; idxA < collA.size(); ++idxA) {
519 if(!combinedFlagsA[idxA]) {
520 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Hit "<<m_idHelperSvc->toString(collA[idxA]->identify())
521 <<" has been used in previous iteration");
522 continue;
523 }
524 for(std::size_t idxB = 0; idxB < collB.size(); ++idxB) {
525 if(!combinedFlagsB[idxB] || !combFunc(collA[idxA], collB[idxB])){
526 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Hit "<<m_idHelperSvc->toString(collB[idxB]->identify())
527 <<" has been used in previous iteration. Or is incompatible with "
528 <<m_idHelperSvc->toString(collA[idxA]->identify()));
529 continue;
530 }
531 //create space point
532 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Combine sTgc measurements "
533 <<m_idHelperSvc->toString(collA[idxA]->identify())<<" and "
534 <<m_idHelperSvc->toString(collB[idxB]->identify())<< "with local positions"
535 << Amg::toString(collA[idxA]->localMeasurementPos()) << " and "
536 << Amg::toString(collB[idxB]->localMeasurementPos())
537 <<" to new space point");
538
539 SpacePoint& newSp = pointsInChamb.etaHits.emplace_back(collB[idxB], collA[idxA]);
540 auto crossPoint = lineIntersect<3>(collA[idxA]->localMeasurementPos(),
541 Amg::Vector3D::UnitX(),
542 collB[idxB]->localMeasurementPos(),
543 Amg::Vector3D::UnitY());
544
545 newSp.setPosition(toSectorTrans*crossPoint.position());
546 newSp.setDirection(Amg::Vector3D::UnitX(), Amg::Vector3D::UnitY());
547 auto cov = Acts::filledArray<double, 3>(0.);
548 cov[Acts::toUnderlying(CovIdx::phiCov)] = covElement(*collA[idxA], CovIdx::phiCov);
549 cov[Acts::toUnderlying(CovIdx::etaCov)] = covElement(*collB[idxB], CovIdx::etaCov);
550 newSp.setCovariance(std::move(cov));
551 newSp.setInstanceCounts(instanceCounts[collIdxB][idxB], instanceCounts[collIdxA][idxA]);
552 ATH_MSG_VERBOSE("Created new space point "<<newSp);
553 }
554 }
555 };
556
557 //try to combine strip with wire measurements first
558 combineMe(1, 0, [&](const xAOD::sTgcMeasurement* wire,
560 // do not combine the strips with the wire that are in the etaZero region
561 const MuonGMR4::sTgcReadoutElement* readoutElement = strip->readoutElement();
562 if(readoutElement->isEtaZero(strip->measurementHash(),
563 strip->localMeasurementPos().block<2,1>(0,0))){
564 return false;
565 }
566 //ignore combinations where the wire and the strip are not crossing
567 //check if the projection of the crossing point is within the bounds of the layer
568 Amg::Vector3D crossPoint = strip->localMeasurementPos() + wire->localMeasurementPos();
569 const Acts::Surface& surf = readoutElement->surface(strip->layerHash());
570 return surf.insideBounds(crossPoint.block<2,1>(0,0));
571 });
572
573 //combine strip and pad measurements
574 combineMe(2, 0, [&](const xAOD::sTgcMeasurement* pad,
576 // do not combine the strips with the pads that are not overlayed
577 const MuonGMR4::sTgcReadoutElement* readoutElement = pad ->readoutElement();
578 const MuonGMR4::PadDesign& padDesign = readoutElement->padDesign(pad->measurementHash());
579 double padHeight = padDesign.padHeight();
580 const Amg::Vector3D padCenter = pad->localMeasurementPos();
581
582 return std::abs(strip->localMeasurementPos().x() - padCenter.x()) < 0.5*padHeight;
583 });
584
585 //finally combine wire and pad measurements
586 combineMe(1, 2, [&](const xAOD::sTgcMeasurement* wire,
587 const xAOD::sTgcMeasurement* pad){
588 // do not combine the wires with the pads that are not overlayed
589 const MuonGMR4::sTgcReadoutElement* readoutElement = pad ->readoutElement();
590 const std::array<Amg::Vector2D, 4> localPadCorners = readoutElement->localPadCorners(pad->measurementHash());
591 auto [min,max] = std::ranges::minmax_element(localPadCorners.begin(), localPadCorners.end(),
592 [](const Amg::Vector2D& a, const Amg::Vector2D& b){
593 return a.y() < b.y();
594 });
595 return (wire->localMeasurementPos().y() > min->y() || wire->localMeasurementPos().y() < max->y());
596
597 });
598
599 //fill uncombined strip, wire and pad measurements that have not been used in combination
600 for(std::size_t collIdx = 0; collIdx < HitColls.size(); ++collIdx){
601 const auto& hits = HitColls[collIdx];
602 std::vector<const xAOD::sTgcMeasurement*> unusedHits{};
603 unusedHits.reserve(hits.size());
604
605 for(std::size_t idx = 0; idx < hits.size(); ++idx){
606 if((*instanceCounts[collIdx][idx]) == 0){
607 unusedHits.push_back(hits[idx]);
608 }
609 }
610 fillUncombinedSpacePoints(*gctx, sectorTrans, unusedHits, pointsInChamb.etaHits);
611 }
612 }
613 } while (viewer.next());
614 return StatusCode::SUCCESS;
615}
616
617
618StatusCode SpacePointMakerAlg::execute(const EventContext& ctx) const {
619 PreSortedSpacePointMap preSortedContainer{};
620 ATH_CHECK(loadContainerAndSort(ctx, m_mdtKey, preSortedContainer));
621 ATH_CHECK(loadContainerAndSort(ctx, m_rpcKey, preSortedContainer));
622 ATH_CHECK(loadContainerAndSort(ctx, m_tgcKey, preSortedContainer));
623 ATH_CHECK(loadContainerAndSort(ctx, m_mmKey, preSortedContainer));
624 ATH_CHECK(loadContainerAndSort(ctx, m_stgcKey, preSortedContainer));
625 std::unique_ptr<SpacePointContainer> outContainer = std::make_unique<SpacePointContainer>();
626
627 for (auto &[chamber, hitsPerChamber] : preSortedContainer){
628 ATH_MSG_DEBUG("Fill space points for chamber "<<chamber->identString() << " with "<<hitsPerChamber.etaHits.size()
629 <<" primary and "<<hitsPerChamber.phiHits.size()<<" phi space points.");
630 distributePointsAndStore(std::move(hitsPerChamber), *outContainer);
631 }
632 SG::WriteHandle writeHandle{m_writeKey, ctx};
633 ATH_CHECK(writeHandle.record(std::move(outContainer)));
634 return StatusCode::SUCCESS;
635}
636
638 SpacePointContainer& finalContainer) const {
639 SpacePointBucketVec splittedHits{};
640 splittedHits.emplace_back();
641 if (m_statCounter){
642 m_statCounter->addToStat(hitsPerChamber.etaHits);
643 m_statCounter->addToStat(hitsPerChamber.phiHits);
644
645 }
646 distributePrimaryPoints(std::move(hitsPerChamber.etaHits), splittedHits);
647 splittedHits.erase(std::remove_if(splittedHits.begin(), splittedHits.end(),
648 [](const SpacePointBucket& bucket) {
649 return bucket.size() <= 1;
650 }), splittedHits.end());
651 distributePhiPoints(std::move(hitsPerChamber.phiHits), splittedHits);
652
653 for (SpacePointBucket& bucket : splittedHits) {
654
655 std::ranges::sort(bucket, MuonR4::SpacePointPerLayerSorter{});
656
657 if (msgLvl(MSG::VERBOSE)){
658 std::stringstream spStr{};
659 for (const std::shared_ptr<SpacePoint>& sp : bucket){
660 spStr<<"SpacePoint: PrimaryMeas: " <<(*sp)<<std::endl;
661 }
662 ATH_MSG_VERBOSE("Created a bucket, printing all spacepoints..."<<std::endl<<spStr.str());
663 }
665 finalContainer.push_back(std::make_unique<SpacePointBucket>(std::move(bucket)));
666 }
667
668}
669void SpacePointMakerAlg::distributePhiPoints(std::vector<SpacePoint>&& spacePoints,
670 SpacePointBucketVec& splittedContainer) const{
671 for (SpacePoint& sp : spacePoints) {
672 auto phiPoint = std::make_shared<SpacePoint>(std::move(sp));
673 const double dY = std::sqrt(phiPoint->covariance()[Acts::toUnderlying(CovIdx::etaCov)]);
674 const double minY = phiPoint->localPosition().y() - dY;
675 const double maxY = phiPoint->localPosition().y() + dY;
676 for (SpacePointBucket& bucket : splittedContainer){
679 if (! (maxY < bucket.coveredMin() || bucket.coveredMax() < minY) ) {
680 bucket.emplace_back(phiPoint);
681 }
682 }
683 }
684}
686 const double firstSpPos,
687 const SpacePointBucketVec& sortedPoints, const BucketParameters& bucketParams) const {
688
690 const double spY = spacePoint.localPosition().y();
691
692 if (spY - firstSpPos > bucketParams.maxBucketLength){
693 ATH_MSG_DEBUG("Splitting bucket based on maxLength. First space point Y=" << firstSpPos
694 << " current space point Y =" << spY
695 << " m_maxBucketLength=" << bucketParams.maxBucketLength );
696 return true;
697 }
698
699 if (sortedPoints.empty() || sortedPoints.back().empty()) {
700 return false;
701 }
702
703 const double gap = spY - sortedPoints.back().back()->localPosition().y();
704
705
706 if (gap > bucketParams.spacePointWindow){
707 ATH_MSG_DEBUG("Splitting bucket based on gap. Last space point Y=" << sortedPoints.back().back()->localPosition().y()
708 << " current space point Y =" << spY
709 << " gap=" << gap
710 << " window=" << bucketParams.spacePointWindow);
711 }
712
713 return gap > bucketParams.spacePointWindow;
714}
716 SpacePointBucketVec& sortedPoints,
717 const BucketParameters& bucketParams) const {
718 SpacePointBucket& newContainer = sortedPoints.emplace_back();
719 newContainer.setBucketId(sortedPoints.size() -1);
720
722 SpacePointBucket& overlap{sortedPoints[sortedPoints.size() - 2]};
723 overlap.setCoveredRange(overlap.front()->localPosition().y(),
724 overlap.back()->localPosition().y());
725
726 const double refBound = refSpacePoint.localPosition().y();
727
728
730 for (const std::shared_ptr<SpacePoint>& pointInBucket : overlap | std::views::reverse) {
731 const double overlapPos = pointInBucket->localPosition().y() +
732 std::sqrt(pointInBucket->covariance()[Acts::toUnderlying(CovIdx::etaCov)]);
733 if (refBound - overlapPos < bucketParams.spacePointOverlap) {
734 newContainer.insert(newContainer.begin(), pointInBucket);
735 } else {
736 break;
737 }
738 }
739
740}
741
742void SpacePointMakerAlg::distributePrimaryPoints(std::vector<SpacePoint>&& spacePoints,
743 SpacePointBucketVec& splittedHits) const {
744
745 if (spacePoints.empty()) return;
746
748 std::ranges::sort(spacePoints,
749 [] (const SpacePoint& a, const SpacePoint& b) {
750 return a.localPosition().y() < b.localPosition().y();
751 });
752
753 double firstPointPos = spacePoints.front().localPosition().y();
754
755 //Base the bucket parameters on the first space point in the chamber. This is a good approximation since all space points in the same chamber should have similar properties with the exception of the edge space points and overlapping chambers
756 const BucketParameters& bucketParams = getBucketParameters(spacePoints.front());
757
758 ATH_MSG_DEBUG("Distributing "<<spacePoints.size()<<" primary space points into buckets with parameters: "
759 << "maxBucketLength=" << bucketParams.maxBucketLength
760 << ", spacePointWindow=" << bucketParams.spacePointWindow
761 << ", spacePointOverlap=" << bucketParams.spacePointOverlap);
762
763 for (SpacePoint& toSort : spacePoints) {
764 ATH_MSG_VERBOSE("Add new primary space point "<<toSort);
765
766 if (splitBucket(toSort, firstPointPos, splittedHits, bucketParams)){
767 newBucket(toSort, splittedHits, bucketParams);
768 firstPointPos = splittedHits.back().empty() ? toSort.localPosition().y() : splittedHits.back().front()->localPosition().y();
769 ATH_MSG_VERBOSE("New bucket: id " << splittedHits.back().bucketId() << " Coverage: " << firstPointPos);
770 }
771 std::shared_ptr<SpacePoint> spacePoint = std::make_shared<SpacePoint>(std::move(toSort));
772 splittedHits.back().emplace_back(spacePoint);
773 }
774 SpacePointBucket& lastBucket{splittedHits.back()};
775 lastBucket.setCoveredRange(lastBucket.front()->localPosition().y(),
776 lastBucket.back()->localPosition().y());
777}
778
779
780
781std::string SpacePointMakerAlg::chamberConfigKey( const MuonGMR4::Chamber& chamber) const {
782 return std::format("{:}_eta{:}_phi{:}", Muon::MuonStationIndex::chName(chamber.chamberIndex()), chamber.stationEta(), chamber.stationPhi());
783}
784
786 const MuonGMR4::Chamber* chamber = spacePoint.chamber();
787
788 ATH_MSG_DEBUG("Resolving bucket parameters for chamber "<<chamber->identString());
789
790 if (const auto itr = m_bucketParameters.find(chamber);
791 itr != m_bucketParameters.end()) {
792 ATH_MSG_DEBUG("FOUNDPARAMS!" );
793 return itr->second;
794 }
795
797}
798
800 const std::string_view chamberKey,
801 const double defaultValue,
802 const BucketPatternMap& patterns) const {
803
804 // Exact match (e.g. BIL_eta-3_phi3) has the highest priority.
805 if (const auto exactItr = patterns.find(chamberKey);
806 exactItr != patterns.end()) {
807 return {
808 .value = exactItr->second,
809 .matched = true
810 };
811 }
812
813 double resolvedValue = defaultValue;
814 std::size_t bestPrefixLength = 0;
815 bool matched = false;
816
817 // Otherwise select the most-specific matching prefix wildcard (e.g. BIL_eta-3* or BIL*).
818 for (const auto& [pattern, value] : patterns) {
819 if (pattern.empty() || pattern.back() != '*') {
820 continue;
821 }
822
823 const std::string_view prefix{
824 pattern.data(),
825 pattern.size() - 1
826 };
827
828 if (chamberKey.starts_with(prefix) &&
829 prefix.size() > bestPrefixLength) {
830 bestPrefixLength = prefix.size();
831 resolvedValue = value;
832 matched = true;
833 }
834 }
835
836 return {
837 .value = resolvedValue,
838 .matched = matched
839 };
840}
841
842std::optional<SpacePointMakerAlg::BucketParameters> SpacePointMakerAlg::resolveBucketParameters(
843 const MuonGMR4::Chamber& chamber) const {
844
845 const std::string chamberKey = chamberConfigKey(chamber);
846
847 const ResolvedParameter maxLength = resolveParameter(
848 chamberKey,
849 m_maxBucketLength.value(),
851
852 const ResolvedParameter hitWindow = resolveParameter(
853 chamberKey,
854 m_spacePointWindow.value(),
856
857 const ResolvedParameter overlap = resolveParameter(
858 chamberKey,
859 m_spacePointOverlap.value(),
861
862 // No chamber-dependent setting matched.
863 if (!maxLength.matched &&
864 !hitWindow.matched &&
865 !overlap.matched) {
866 return std::nullopt;
867 }
868
869 BucketParameters parameters{
870 .spacePointWindow = hitWindow.value,
871 .maxBucketLength = maxLength.value,
872 .spacePointOverlap = overlap.value
873 };
874
876 "Resolved bucket override for " << chamberKey
877 << ": maxBucketLength=" << parameters.maxBucketLength
878 << (maxLength.matched ? " [override]" : " [default]")
879 << ", spacePointWindow=" << parameters.spacePointWindow
880 << (hitWindow.matched ? " [override]" : " [default]")
881 << ", spacePointOverlap=" << parameters.spacePointOverlap
882 << (overlap.matched ? " [override]" : " [default]"));
883
884 return parameters;
885}
886
887
888}
const std::regex re(r_e)
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define ATH_UNLIKELY(x)
static Double_t sp
static Double_t a
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
value_type push_back(value_type pElem)
Add an element to the end of the collection.
bool empty() const noexcept
Returns true if the collection is empty.
Chamber represent the volume enclosing a muon station.
Definition Chamber.h:29
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
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...
const Acts::Surface & surface() const override final
Returns the surface associated with the readout element.
double padHeight() const
Returns the height of all the pads that are not adjacent to the bottom edge of the trapezoid active a...
const PadDesign & padDesign(const IdentifierHash &measHash) const
Retrieves the readoutElement Layer given the Identifier/Hash.
localCornerArray localPadCorners(const IdentifierHash &measHash) const
bool isEtaZero(const IdentifierHash &measurementHash, const Amg::Vector2D &localPosition) const
: The muon space point bucket represents a collection of points that will bre processed together in t...
void setCoveredRange(double min, double max)
set the range in the precision plane covered by the bucket
void setBucketId(unsigned int id)
sets the Identifier of the MuonSpacePointBucket in context of the associated muonChamber
SpacePointStatistics(const Muon::IMuonIdHelperSvc *idHelperSvc)
Standard constructor.
void addToStat(const std::vector< SpacePoint > &spacePoints)
Adds the vector of space points to the overall statistics.
void dumpStatisics(MsgStream &msg) const
Print the statistics table of the built space points per category into the log-file / console.
Gaudi::Property< double > m_maxOccRpcEta
BucketParameters m_defaultBucketParameters
Default bucket parameters used if no chamber-specific parameters are found, defaults into m_spacePoin...
Gaudi::Property< double > m_maxOccTgcEta
const MuonGMR4::MuonDetectorManager * m_detMgr
Gaudi::Property< double > m_maxOccTgcPhi
Gaudi::Property< double > m_spacePointWindow
Default space point window size (Max distance between the two eta hits).
Gaudi::Property< bool > m_doStat
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::vector< EtaPhi2DHits< T > > EtaPhi2DHitsVec
SG::ReadHandleKey< xAOD::TgcStripContainer > m_tgcKey
bool splitBucket(const SpacePoint &spacePoint, const double firstSpPos, const SpacePointBucketVec &sortedPoints, const BucketParameters &bucketParams) const
Returns whether the space point is beyond the bucket boundary.
void distributePhiPoints(std::vector< SpacePoint > &&spacePoints, SpacePointBucketVec &splittedContainer) const
Distributs the vector phi space points into the buckets.
Gaudi::Property< double > m_maxOccRpcPhi
Gaudi::Property< double > m_maxBucketLength
Default maximum bucket length (the width of the bucket in local y coordinate).
ResolvedParameter resolveParameter(const std::string_view chamberKey, const double defaultValue, const BucketPatternMap &patterns) const
Resolves a specific parameter for a given chamber key, based on the configured patterns.
SG::ReadHandleKey< xAOD::MMClusterContainer > m_mmKey
bool passOccupancy2D(const PrdVec_t< PrdType > &etaHits, const PrdVec_t< PrdType > &phiHits) const
: Check whether the occupancy cuts of hits in a gasGap are surpassed.
std::vector< SpacePointBucket > SpacePointBucketVec
Abrivation of a MuonSapcePoint bucket vector.
void fillUncombinedSpacePoints(const ActsTrk::GeometryContext &gctx, const Amg::Transform3D &sectorTrans, const PrdVec_t< const PrdType * > &prdsToFill, std::vector< SpacePoint > &outColl) const
Transform the uncombined space prd measurements to space points.
void newBucket(const SpacePoint &refSp, SpacePointBucketVec &sortedPoints, const BucketParameters &bucketParams) const
Closes the current processed bucket and creates a new one.
Gaudi::Property< BucketPatternMap > m_spacePointOverlapPatterns
Chamber-pattern dependent space point overlap.
SG::WriteHandleKey< SpacePointContainer > m_writeKey
StatusCode loadContainerAndSort(const EventContext &ctx, const SG::ReadHandleKey< ContType > &key, PreSortedSpacePointMap &fillContainer) const
Retrieve an uncalibrated measurement container <ContType> and fill the hits into the presorted space ...
SG::ReadHandleKey< xAOD::RpcMeasurementContainer > m_rpcKey
Gaudi::Property< double > m_spacePointOverlap
Default space point overlap (the margin around the edge of the bucket which is also coppied into anot...
StatusCode execute(const EventContext &ctx) const override
std::optional< BucketParameters > resolveBucketParameters(const MuonGMR4::Chamber &chamber) const
Resolves the bucket parameters for a given chamber, based on the chamber key and the configured patte...
std::vector< Prd_t > PrdVec_t
void distributePrimaryPoints(std::vector< SpacePoint > &&spacePoints, SpacePointBucketVec &splittedContainer) const
Distributes the vector of primary eta or eta + phi space points and fills them into the buckets.
StatusCode initialize() override
SG::ReadHandleKey< xAOD::sTgcMeasContainer > m_stgcKey
void distributePointsAndStore(SpacePointsPerChamber &&hitsPerChamber, SpacePointContainer &finalContainer) const
Distribute the premade spacepoints per chamber into their individual SpacePoint buckets.
EtaPhi2DHitsVec< typename ContType::const_value_type > splitHitsPerGasGap(xAOD::ChamberViewer< ContType > &viewer) const
Splits the chamber hits of the viewer per gas gap.
StatusCode finalize() override
########################################## SpacePointMakerAlg #######################################...
const BucketParameters & getBucketParameters(const SpacePoint &spacePoint) const
Returns the bucket parameters for a given space point.
Gaudi::Property< BucketPatternMap > m_maxBucketLengthPatterns
Chamber-pattern dependent maximum bucket length.
std::string chamberConfigKey(const MuonGMR4::Chamber &chamber) const
Returns a string key for a chamber, based on the space point identifier.
Gaudi::Property< BucketPatternMap > m_spacePointWindowPatterns
Chamber-pattern dependent space point window.
std::unordered_map< const MuonGMR4::SpectrometerSector *, SpacePointsPerChamber > PreSortedSpacePointMap
Container abrivation of the presorted space point container per MuonChambers.
Gaudi::Property< unsigned > m_capacityBucket
SG::ReadHandleKey< xAOD::MdtDriftCircleContainer > m_mdtKey
ActsTrk::GeoContextReadKey_t m_geoCtxKey
std::map< std::string, double, std::less<> > BucketPatternMap
std::unordered_map< const MuonGMR4::Chamber *, BucketParameters > m_bucketParameters
Map of bucket parameters for each chamber.
The SpacePointPerLayerSorter sort two given space points by their layer Identifier.
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
void setDirection(const Amg::Vector3D &sensorDir, const Amg::Vector3D &toNextSensor)
Setter for the direction of the measurement channel in the sector frame.
void setInstanceCounts(std::shared_ptr< unsigned > etaCounts, std::shared_ptr< unsigned > phiCounts)
Set the number of space points built with the same eta / phi prd.
const MuonGMR4::Chamber * chamber() const
: Pointer to the associated chamber
bool measuresEta() const
: Does the space point contain an eta measurement
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
Property holding a SG store/key/clid from which a ReadHandle is made.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
const_ref at(const std::size_t idx) const
Returns the i-the measurement from the current chamber.
std::size_t size() const noexcept
Returns how many hits are in the current chamber.
bool next()
Loads the hits from the next chamber.
const MuonGMR4::sTgcReadoutElement * readoutElement() const override final
Retrieve the associated sTgcReadoutElement.
IdentifierHash measurementHash() const override final
Returns the hash of the measurement channel w.r.t ReadoutElement.
Amg::Vector3D localMeasurementPos() const override final
Returns the local measurement position as 3-vector.
#define ATH_FLATTEN
std::vector< std::string > patterns
Definition listroot.cxx:187
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
This header ties the generic definitions in this package.
DataVector< SpacePointBucket > SpacePointContainer
Abrivation of the space point container type.
const std::string & stName(StIndex index)
convert StIndex into a string
const std::string & technologyName(TechnologyIndex index)
convert LayerIndex into a string
const std::string & chName(ChIndex index)
convert ChIndex into a string
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
MdtTwinDriftCircle_v1 MdtTwinDriftCircle
sTgcMeasContainer_v1 sTgcMeasContainer
sTgcMeasurement_v1 sTgcMeasurement
Helper struct to define the bucket parameters for a given chamber.
Helper struct to store the resolved bucket parameters for a given chamber.
Helper struct to define the counting categories.
bool operator<(const FieldKey &other) const
################################################################ SpacePointStatistics ###############...
Helper struct to count the space-points in each detector category.
unsigned measEtaPhi
Number of space points measuring eta & phi.
unsigned measEta
Number of space points measuring eta only.
unsigned measPhi
Number of space points measuring phi only.
unsigned allHits() const
Helper method returning the sum of the three space point type counts.
: Helper struct to collect the space point per muon chamber, which are later sorted into the space po...
std::vector< SpacePoint > etaHits
Vector of all hits that contain an eta measurement including the ones which are combined with phi mea...
std::vector< SpacePoint > phiHits
Vector of all space points that are built from single phi hits.