ATLAS Offline Software
Loading...
Searching...
No Matches
SpacePointMakerAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
5
12#include <GaudiKernel/IMessageSvc.h>
13#include <memory>
14#include <type_traits>
21
22
23#include "Acts/Surfaces/detail/LineHelper.hpp"
24namespace {
25 inline std::vector<std::shared_ptr<unsigned>> matchCountVec(unsigned n) {
26 std::vector<std::shared_ptr<unsigned>> out{};
27 out.reserve(n);
28 for (unsigned p = 0; p < n ;++p) {
29 out.emplace_back(std::make_shared<unsigned>(0));
30 }
31 return out;
32 }
38 template<class MeasType>
39 Amg::Transform3D toChamberTransform(const ActsTrk::GeometryContext& gctx,
40 const Amg::Transform3D& sectorTrans,
41 const MeasType& meas) {
42 const MuonGMR4::MuonReadoutElement* reEle{meas.readoutElement()};
43 if constexpr(std::is_same_v<MeasType, xAOD::MdtDriftCircle>) {
44 return sectorTrans * reEle->localToGlobalTrans(gctx, meas.measurementHash());
45 } else {
46 return sectorTrans * reEle->localToGlobalTrans(gctx, meas.layerHash());
47 }
48 }
51 template <typename PrdType>
52 double sensorHalfLength(const PrdType& prd) {
53 const auto* re = prd.readoutElement();
54 if constexpr(std::is_same_v<PrdType, xAOD::MdtDriftCircle>) {
55 return 0.5 * re->activeTubeLength(prd.measurementHash());
56 } else if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement>) {
57 return 0.5*(prd.measuresPhi() ? re->stripPhiLength() : re->stripEtaLength());
58 } else if constexpr(std::is_same_v<PrdType, xAOD::TgcStrip>) {
59 return 0.5 * re->sensorLayout(prd.layerHash())->design(prd.measuresPhi()).stripLength(prd.channelNumber());
60 } else if constexpr(std::is_same_v<PrdType, xAOD::MMCluster>) {
61 return 0.5* re->stripLayer(prd.layerHash()).design().stripLength(prd.channelNumber());
62 } else if constexpr(std::is_same_v<PrdType, xAOD::sTgcMeasurement>) {
63 return 0.5* re->stripLayer(prd.layerHash()).design().stripLength(prd.channelNumber());
64 }
65 return 0.;
66 }
67}
68
69namespace MuonR4 {
70
75 if (techIdx != other.techIdx) {
76 return static_cast<int>(techIdx) < static_cast<int>(other.techIdx);
77 }
78 if (stIdx != other.stIdx) {
79 return static_cast<int>(stIdx) < static_cast<int>(other.stIdx);
80 }
81 return eta < other.eta;
82}
88
89void SpacePointMakerAlg::SpacePointStatistics::addToStat(const std::vector<SpacePoint>& spacePoints){
90 std::lock_guard guard{m_mutex};
91 for (const SpacePoint& sp : spacePoints){
92 FieldKey key{};
93 key.stIdx = m_idHelperSvc->stationIndex(sp.identify());
94 key.techIdx = m_idHelperSvc->technologyIndex(sp.identify());
95 key.eta = m_idHelperSvc->stationEta(sp.identify());
96 StatField & stats = m_map[key];
97 if (sp.measuresEta() && sp.measuresPhi()) {
98 ++stats.measEtaPhi;
99 } else {
100 stats.measEta += sp.measuresEta();
101 stats.measPhi += sp.measuresPhi();
102 }
103 }
104}
106 using KeyVal = std::pair<FieldKey, StatField>;
107 std::vector<KeyVal> sortedstats{};
108 sortedstats.reserve(m_map.size());
110 for (const auto & [key, stats] : m_map){
111 sortedstats.emplace_back(std::make_pair(key, stats));
112 }
113 std::stable_sort(sortedstats.begin(), sortedstats.end(), [](const KeyVal& a, const KeyVal&b) {
114 return a.second.allHits() > b.second.allHits();
115 });
116 msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
117 for (const auto & [key, stats] : sortedstats) {
118 msg<<MSG::ALWAYS<<" "<<Muon::MuonStationIndex::technologyName(key.techIdx)
119 <<" "<<Muon::MuonStationIndex::stName(key.stIdx)
120 <<" "<<std::abs(key.eta)<<(key.eta < 0 ? "A" : "C")
121 <<" "<<std::setw(8)<<stats.measEtaPhi
122 <<" "<<std::setw(8)<<stats.measEta
123 <<" "<<std::setw(8)<<stats.measPhi<<endmsg;
124 }
125 msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
126
127}
128
132
133
135 if (m_statCounter) {
136 m_statCounter->dumpStatisics(msgStream());
137 }
138 return StatusCode::SUCCESS;
139}
141 ATH_CHECK(m_geoCtxKey.initialize());
142 ATH_CHECK(m_mdtKey.initialize(!m_mdtKey.empty()));
143 ATH_CHECK(m_rpcKey.initialize(!m_rpcKey.empty()));
144 ATH_CHECK(m_tgcKey.initialize(!m_tgcKey.empty()));
145 ATH_CHECK(m_mmKey.initialize(!m_mmKey.empty()));
146 ATH_CHECK(m_stgcKey.initialize(!m_stgcKey.empty()));
147 ATH_CHECK(m_idHelperSvc.retrieve());
148 ATH_CHECK(m_writeKey.initialize());
149 if (m_doStat) {
150 m_statCounter = std::make_unique<SpacePointStatistics>(m_idHelperSvc.get());
151 }
152 return StatusCode::SUCCESS;
153}
154
155template <>
156 bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::TgcStrip*>& etaHits,
157 const std::vector<const xAOD::TgcStrip*>& phiHits) const {
158 if (etaHits.empty() || phiHits.empty()) {
159 return false;
160 }
161 const MuonGMR4::TgcReadoutElement* re = etaHits[0]->readoutElement();
162 ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
163 return ((1.*etaHits.size()) / ((1.*re->numChannels(etaHits[0]->measurementHash())))) < m_maxOccTgcEta &&
164 ((1.*phiHits.size()) / ((1.*re->numChannels(phiHits[0]->measurementHash())))) < m_maxOccTgcPhi;
165 }
166template <>
167 bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::RpcMeasurement*>& etaHits,
168 const std::vector<const xAOD::RpcMeasurement*>& phiHits) const {
169 if (etaHits.empty() || phiHits.empty()) {
170 return false;
171 }
172 const MuonGMR4::RpcReadoutElement* re = etaHits[0]->readoutElement();
173 ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
174 return ((1.*etaHits.size()) / (1.*re->nEtaStrips())) < m_maxOccRpcEta &&
175 ((1.*phiHits.size()) / (1.*re->nPhiStrips())) < m_maxOccRpcPhi;
176 }
177
178template <>
179 bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::sTgcMeasurement*>& etaHits,
180 const std::vector<const xAOD::sTgcMeasurement*>& phiHits) const {
181 if (etaHits.empty() || phiHits.empty()) {
182 return false;
183 }
184 const MuonGMR4::sTgcReadoutElement* re = etaHits[0]->readoutElement();
185 return ((1.*etaHits.size()) / (1.*re->numChannels(etaHits[0]->measurementHash()))) < m_maxOccStgcEta &&
186 ((1.*phiHits.size()) / (1.*re->numChannels(phiHits[0]->measurementHash()))) < m_maxOccStgcPhi;
187 }
188template <>
189 bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::MMCluster*>& /*etaHits*/,
190 const std::vector<const xAOD::MMCluster*>& /*phiHits*/) const {
191 return false;
192 }
193template <typename PrdType>
195 const Amg::Transform3D& sectorTrans,
196 const std::vector<const PrdType*>& prdsToFill,
197 std::vector<SpacePoint>& outColl) const {
198 if (prdsToFill.empty()) {
199 return;
200 }
201 const PrdType* refMeas = prdsToFill.front();
202 bool allSpArePhi{false};
203
204 const Amg::Transform3D toSectorTrans = toChamberTransform(gctx, sectorTrans, *refMeas);
206 Amg::Vector3D sensorDir{Amg::Vector3D::Zero()}, toNextSen{Amg::Vector3D::Zero()};
208 if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement> ||
209 std::is_same_v<PrdType, xAOD::TgcStrip>) {
210 allSpArePhi = refMeas->measuresPhi();
211 const auto& stripLayout = refMeas->readoutElement()->sensorLayout(refMeas->layerHash());
212 const auto& design = stripLayout->design(allSpArePhi);
213 sensorDir = toSectorTrans.rotation() * stripLayout->to3D(design.stripDir(), allSpArePhi);
214 toNextSen = toSectorTrans.rotation() * stripLayout->to3D(design.stripNormal(), allSpArePhi);
215 } else {
216 sensorDir = toSectorTrans.rotation().col(Amg::y);
217 toNextSen = toSectorTrans.rotation().col(Amg::x);
218 }
219 outColl.reserve(outColl.size() + prdsToFill.size());
220 for (const PrdType* prd: prdsToFill) {
221 SpacePoint& newSp = outColl.emplace_back(prd);
222 if constexpr (std::is_same_v<PrdType, xAOD::TgcStrip>) {
223 if (allSpArePhi) {
224 const auto& stripLayout = refMeas->readoutElement()->sensorLayout(refMeas->layerHash());
225 const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLayout->design(allSpArePhi));
226 toNextSen = toSectorTrans.rotation() * stripLayout->to3D(radialDesign.stripNormal(prd->channelNumber()), allSpArePhi);
227 sensorDir = toSectorTrans.rotation() * stripLayout->to3D(radialDesign.stripDir(prd->channelNumber()), allSpArePhi);
228 }
229 }
230 newSp.setPosition(toSectorTrans * prd->localMeasurementPos());
231 newSp.setDirection(sensorDir, toNextSen);
232 auto cov = Acts::filledArray<double,3>(0.);
233 if (prd->numDimensions() == 2) {
234 if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement>) {
235 cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<2>()(0,0);
236 cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<2>()(1,1);
237 } else if constexpr(std::is_same_v<PrdType, xAOD::sTgcMeasurement>) {
238 cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<2>()(0,0);
239 cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<2>()(1,1);
240 } else {
241 ATH_MSG_WARNING("Unsupported measurement type. "<<typeid(PrdType).name());
242 // Prevent division by zero later on.
243 cov[Acts::toUnderlying(CovIdx::phiCov)] = 1;
244 cov[Acts::toUnderlying(CovIdx::etaCov)] = 1;
245 }
246 } else {
248 if (newSp.measuresEta()) {
249 cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<1>()[0];
250 cov[Acts::toUnderlying(CovIdx::phiCov)] = Acts::square(sensorHalfLength(*prd));
251 } else {
252 cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<1>()[0];
253 cov[Acts::toUnderlying(CovIdx::etaCov)] = Acts::square(sensorHalfLength(*prd));
254 }
255 }
256 newSp.setCovariance(std::move(cov));
257 }
258}
259template <class ContType>
260 StatusCode SpacePointMakerAlg::loadContainerAndSort(const EventContext& ctx,
262 PreSortedSpacePointMap& fillContainer) const {
263 const ContType* measurementCont{nullptr};
264 ATH_CHECK(SG::get(measurementCont, key, ctx));
265 if (!measurementCont || measurementCont->empty()){
266 ATH_MSG_DEBUG("nothing to do");
267 return StatusCode::SUCCESS;
268 }
269 const ActsTrk::GeometryContext* gctx{nullptr};
270 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
271
272 using PrdType = typename ContType::const_value_type;
273 using PrdVec = std::vector<PrdType>;
274 xAOD::ChamberViewer viewer{*measurementCont};
275 do {
276 SpacePointsPerChamber& pointsInChamb = fillContainer[viewer.at(0)->readoutElement()->msSector()];
277 const Amg::Transform3D sectorTrans = viewer.at(0)->readoutElement()->msSector()->globalToLocalTrans(*gctx);
278 ATH_MSG_DEBUG("Fill space points for chamber "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
279 if constexpr( std::is_same_v<ContType, xAOD::MdtDriftCircleContainer>) {
280 pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.capacity() + viewer.size());
281 for (const PrdType prd : viewer) {
282 Amg::Transform3D toChamberTrans{toChamberTransform(*gctx, sectorTrans, *prd)};
283 SpacePoint& sp{pointsInChamb.etaHits.emplace_back(prd)};
284 sp.setPosition(toChamberTrans*prd->localMeasurementPos());
285 sp.setDirection(toChamberTrans.rotation().col(Amg::z),
286 toChamberTrans.rotation().col(Amg::y));
287 std::array<double, 3> cov{Acts::filledArray<double,3>(0.)};
288 cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->driftRadiusCov();
289 cov[Acts::toUnderlying(CovIdx::phiCov)] = Acts::square(sensorHalfLength(*prd));
290 if (ATH_UNLIKELY(prd->numDimensions() == 2)){
291 cov[Acts::toUnderlying(CovIdx::phiCov)] = static_cast<const xAOD::MdtTwinDriftCircle*>(prd)->posAlongWireCov();
292 }
293 sp.setCovariance(std::move(cov));
294 }
295 } else {
297 using EtaPhi2DHits = std::array<PrdVec, 3>;
298 std::vector<EtaPhi2DHits> hitsPerGasGap{};
299 for (const PrdType prd : viewer) {
300 ATH_MSG_VERBOSE("Create space point from "<<m_idHelperSvc->toString(prd->identify())
301 <<", hash: "<<prd->identifierHash());
302
303 unsigned gapIdx = prd->gasGap() -1;
304 if constexpr (std::is_same_v<ContType, xAOD::RpcMeasurementContainer>) {
305 gapIdx = prd->readoutElement()->createHash(0, prd->gasGap(), prd->doubletPhi(), false);
306 }
307 if (hitsPerGasGap.size() <= gapIdx) {
308 hitsPerGasGap.resize(gapIdx + 1);
309 }
310 bool measPhi{false};
311 if constexpr(std::is_same_v<ContType, xAOD::sTgcMeasContainer>) {
313 measPhi = prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
314 } else if constexpr(!std::is_same_v<ContType, xAOD::MMClusterContainer>) {
316 measPhi = prd->measuresPhi();
317 }
318
319 if (prd->numDimensions() == 2) {
320 hitsPerGasGap[gapIdx][2].push_back(prd);
321 continue;
322 }
324 PrdVec& toPush = hitsPerGasGap[gapIdx][measPhi];
325 if (toPush.capacity() == toPush.size()) {
326 toPush.reserve(toPush.size() + m_capacityBucket);
327 }
328 toPush.push_back(prd);
329 }
330
331 for (auto& [etaHits, phiHits, two2DHits] : hitsPerGasGap) {
332 ATH_MSG_DEBUG("Found "<<etaHits.size()<<"/"<<phiHits.size()<<" 1D and "<<two2DHits.size()<<" 2D hits in chamber "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
334 fillUncombinedSpacePoints(*gctx, sectorTrans, two2DHits, pointsInChamb.etaHits);
336 if (!passOccupancy2D(etaHits, phiHits)) {
337 fillUncombinedSpacePoints(*gctx, sectorTrans, etaHits, pointsInChamb.etaHits);
338 fillUncombinedSpacePoints(*gctx, sectorTrans, phiHits, pointsInChamb.phiHits);
339 continue;
340 }
341
342 std::vector<std::shared_ptr<unsigned>> etaCounts{matchCountVec(etaHits.size())},
343 phiCounts{matchCountVec(phiHits.size())};
344 pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.size() + etaHits.size()*phiHits.size());
346 const PrdType firstEta{etaHits.front()};
347 const PrdType firstPhi{phiHits.front()};
348
349 const Amg::Transform3D toSectorTransEta = toChamberTransform(*gctx, sectorTrans, *firstEta);
350 const Amg::Transform3D toSectorTransPhi = toChamberTransform(*gctx, sectorTrans, *firstPhi);
351
352 Amg::Vector3D toNextDir{Amg::Vector3D::Zero()}, sensorDir{Amg::Vector3D::Zero()};
353
354 if constexpr (std::is_same_v<xAOD::RpcMeasurementContainer, ContType> ||
355 std::is_same_v<xAOD::TgcStripContainer, ContType>) {
356 const auto& stripLayout = firstEta->readoutElement()->sensorLayout(firstEta->layerHash());
357 const auto& design = stripLayout->design();
358 sensorDir = toSectorTransEta.rotation() * stripLayout->to3D(design.stripDir(), false);
359 toNextDir = toSectorTransEta.rotation() * stripLayout->to3D(design.stripNormal(), false);
360 } else {
361 toNextDir = toSectorTransEta.rotation().col(Amg::x);
362 sensorDir = toSectorTransEta.rotation().col(Amg::y);
363 }
364 using namespace Acts::detail::LineHelper;
365 for (unsigned etaP = 0; etaP < etaHits.size(); ++etaP) {
367 for (unsigned phiP = 0; phiP < phiHits.size(); ++ phiP) {
369 if constexpr(std::is_same_v<xAOD::TgcStripContainer, ContType>) {
370 if (!(etaHits[etaP]->bcBitMap() & phiHits[phiP]->bcBitMap())){
371 continue;
372 }
373 const auto& stripLay = phiHits[phiP]->readoutElement()->sensorLayout(phiHits[phiP]->layerHash());
374 const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(true));
375 toNextDir = toSectorTransPhi.rotation() * stripLay->to3D(radialDesign.stripDir(phiHits[phiP]->channelNumber()), true);
376 }
377 SpacePoint& newSp = pointsInChamb.etaHits.emplace_back(etaHits[etaP], phiHits[phiP]);
378 newSp.setInstanceCounts(etaCounts[etaP], phiCounts[phiP]);
379
380 auto spIsect = lineIntersect(toSectorTransEta*etaHits[etaP]->localMeasurementPos(), sensorDir,
381 toSectorTransPhi*phiHits[phiP]->localMeasurementPos(), toNextDir);
382 newSp.setPosition(spIsect.position());
383 newSp.setDirection(sensorDir, toNextDir);
384 auto cov = Acts::filledArray<double, 3>(0.);
385 cov[Acts::toUnderlying(CovIdx::etaCov)] = etaHits[etaP]->template localCovariance<1>()[0];
386 cov[Acts::toUnderlying(CovIdx::phiCov)] = phiHits[phiP]->template localCovariance<1>()[0];
387 newSp.setCovariance(std::move(cov));
388 ATH_MSG_VERBOSE("Created new space point "<<newSp);
389 }
390 }
391 }
392 }
393 } while (viewer.next());
394 return StatusCode::SUCCESS;
395}
396
397
398StatusCode SpacePointMakerAlg::execute(const EventContext& ctx) const {
399 PreSortedSpacePointMap preSortedContainer{};
400 ATH_CHECK(loadContainerAndSort(ctx, m_mdtKey, preSortedContainer));
401 ATH_CHECK(loadContainerAndSort(ctx, m_rpcKey, preSortedContainer));
402 ATH_CHECK(loadContainerAndSort(ctx, m_tgcKey, preSortedContainer));
403 ATH_CHECK(loadContainerAndSort(ctx, m_mmKey, preSortedContainer));
404 ATH_CHECK(loadContainerAndSort(ctx, m_stgcKey, preSortedContainer));
405 std::unique_ptr<SpacePointContainer> outContainer = std::make_unique<SpacePointContainer>();
406
407 for (auto &[chamber, hitsPerChamber] : preSortedContainer){
408 ATH_MSG_DEBUG("Fill space points for chamber "<<chamber->identString() << " with "<<hitsPerChamber.etaHits.size()
409 <<" primary and "<<hitsPerChamber.phiHits.size()<<" phi space points.");
410 distributePointsAndStore(std::move(hitsPerChamber), *outContainer);
411 }
412 SG::WriteHandle writeHandle{m_writeKey, ctx};
413 ATH_CHECK(writeHandle.record(std::move(outContainer)));
414 return StatusCode::SUCCESS;
415}
416
418 SpacePointContainer& finalContainer) const {
419 SpacePointBucketVec splittedHits{};
420 splittedHits.emplace_back();
421 if (m_statCounter){
422 m_statCounter->addToStat(hitsPerChamber.etaHits);
423 m_statCounter->addToStat(hitsPerChamber.phiHits);
424
425 }
426 distributePrimaryPoints(std::move(hitsPerChamber.etaHits), splittedHits);
427 splittedHits.erase(std::remove_if(splittedHits.begin(), splittedHits.end(),
428 [](const SpacePointBucket& bucket) {
429 return bucket.size() <= 1;
430 }), splittedHits.end());
431 distributePhiPoints(std::move(hitsPerChamber.phiHits), splittedHits);
432
433 for (SpacePointBucket& bucket : splittedHits) {
434
435 std::ranges::sort(bucket, MuonR4::SpacePointPerLayerSorter{});
436
437 if (msgLvl(MSG::VERBOSE)){
438 std::stringstream spStr{};
439 for (const std::shared_ptr<SpacePoint>& sp : bucket){
440 spStr<<"SpacePoint: PrimaryMeas: " <<(*sp)<<std::endl;
441 }
442 ATH_MSG_VERBOSE("Created a bucket, printing all spacepoints..."<<std::endl<<spStr.str());
443 }
445 finalContainer.push_back(std::make_unique<SpacePointBucket>(std::move(bucket)));
446 }
447
448}
449void SpacePointMakerAlg::distributePhiPoints(std::vector<SpacePoint>&& spacePoints,
450 SpacePointBucketVec& splittedContainer) const{
451 for (SpacePoint& sp : spacePoints) {
452 auto phiPoint = std::make_shared<SpacePoint>(std::move(sp));
453 const double dY = std::sqrt(phiPoint->covariance()[Acts::toUnderlying(CovIdx::etaCov)]);
454 const double minY = phiPoint->localPosition().y() - dY;
455 const double maxY = phiPoint->localPosition().y() + dY;
456 for (SpacePointBucket& bucket : splittedContainer){
459 if (! (maxY < bucket.coveredMin() || bucket.coveredMax() < minY) ) {
460 bucket.emplace_back(phiPoint);
461 }
462 }
463 }
464}
466 const double firstSpPos,
467 const SpacePointBucketVec& sortedPoints) const {
469 const double spY = spacePoint.localPosition().y();
470 if (spY - firstSpPos > m_maxBucketLength){
471 return true;
472 }
473
474 if (sortedPoints.empty() || sortedPoints.back().empty()) {
475 return false;
476 }
477 return spY - sortedPoints.back().back()->localPosition().y() > m_spacePointWindow;
478}
480 SpacePointBucketVec& sortedPoints) const {
481 SpacePointBucket& newContainer = sortedPoints.emplace_back();
482 newContainer.setBucketId(sortedPoints.size() -1);
483
485 SpacePointBucket& overlap{sortedPoints[sortedPoints.size() - 2]};
486 overlap.setCoveredRange(overlap.front()->localPosition().y(),
487 overlap.back()->localPosition().y());
488
489 const double refBound = refSpacePoint.localPosition().y();
490
492 for (const std::shared_ptr<SpacePoint>& pointInBucket : overlap | std::views::reverse) {
493 const double overlapPos = pointInBucket->localPosition().y() +
494 std::sqrt(pointInBucket->covariance()[Acts::toUnderlying(CovIdx::etaCov)]);
495 if (refBound - overlapPos < m_spacePointOverlap) {
496 newContainer.insert(newContainer.begin(), pointInBucket);
497 } else {
498 break;
499 }
500 }
501
502}
503
504void SpacePointMakerAlg::distributePrimaryPoints(std::vector<SpacePoint>&& spacePoints,
505 SpacePointBucketVec& splittedHits) const {
506
507 if (spacePoints.empty()) return;
508
510 std::ranges::sort(spacePoints,
511 [] (const SpacePoint& a, const SpacePoint& b) {
512 return a.localPosition().y() < b.localPosition().y();
513 });
514
515 double firstPointPos = spacePoints.front().localPosition().y();
516
517 for (SpacePoint& toSort : spacePoints) {
518 ATH_MSG_VERBOSE("Add new primary space point "<<toSort);
519
520 if (splitBucket(toSort, firstPointPos, splittedHits)){
521 newBucket(toSort, splittedHits);
522 firstPointPos = splittedHits.back().empty() ? toSort.localPosition().y() : splittedHits.back().front()->localPosition().y();
523 ATH_MSG_VERBOSE("New bucket: id " << splittedHits.back().bucketId() << " Coverage: " << firstPointPos);
524 }
525 std::shared_ptr<SpacePoint> spacePoint = std::make_shared<SpacePoint>(std::move(toSort));
526 splittedHits.back().emplace_back(spacePoint);
527 }
528 SpacePointBucket& lastBucket{splittedHits.back()};
529 lastBucket.setCoveredRange(lastBucket.front()->localPosition().y(),
530 lastBucket.back()->localPosition().y());
531}
532
533}
const boost::regex re(r_e)
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(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.
bool msgLvl(const MSG::Level lvl) const
value_type push_back(value_type pElem)
Add an element to the end of the collection.
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
: 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
Gaudi::Property< double > m_maxOccTgcEta
Gaudi::Property< double > m_maxOccTgcPhi
Gaudi::Property< double > m_maxOccStgcPhi
Gaudi::Property< double > m_spacePointWindow
Gaudi::Property< bool > m_doStat
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::ReadHandleKey< xAOD::TgcStripContainer > m_tgcKey
bool passOccupancy2D(const std::vector< const PrdType * > &etaHits, const std::vector< const PrdType * > &phiHits) const
: Check whether the occupancy cuts of hits in a gasGap are surpassed.
void newBucket(const SpacePoint &refSp, SpacePointBucketVec &sortedPoints) const
Closes the current processed bucket and creates a new one.
void distributePhiPoints(std::vector< SpacePoint > &&spacePoints, SpacePointBucketVec &splittedContainer) const
Distributs the vector phi space points into the buckets.
Gaudi::Property< double > m_maxOccRpcPhi
void fillUncombinedSpacePoints(const ActsTrk::GeometryContext &gctx, const Amg::Transform3D &sectorTrans, const std::vector< const PrdType * > &prdsToFill, std::vector< SpacePoint > &outColl) const
Fills all space points that are beloni.
Gaudi::Property< double > m_maxBucketLength
SG::ReadHandleKey< xAOD::MMClusterContainer > m_mmKey
bool splitBucket(const SpacePoint &spacePoint, const double firstSpPos, const SpacePointBucketVec &sortedPoints) const
Returns whether the space point is beyond the bucket boundary.
Gaudi::Property< double > m_maxOccStgcEta
std::vector< SpacePointBucket > SpacePointBucketVec
Abrivation of a MuonSapcePoint bucket vector.
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
StatusCode execute(const EventContext &ctx) const override
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.
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
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 setInstanceCounts(std::shared_ptr< unsigned > etaCounts, std::shared_ptr< unsigned > phiCounts)
Set the number of space points built with the same eta / phi prd.
void setDirection(const Amg::Vector3D &sensorDir, const Amg::Vector3D &toNextSensor)
Setter for the direction of the measurement channel in the sector frame.
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.
bool next() noexcept
Loads the hits from the next chamber.
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.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
This header ties the generic definitions in this package.
SpacePoint::CovIdx CovIdx
########################################## SpacePointMakerAlg #######################################...
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 T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
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
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.