ATLAS Offline Software
SpacePointMakerAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "SpacePointMakerAlg.h"
5 
10 #include "StoreGate/ReadHandle.h"
11 #include "StoreGate/WriteHandle.h"
12 #include <GaudiKernel/IMessageSvc.h>
13 #include <memory>
14 #include <type_traits>
21 
22 
23 #include "Acts/Surfaces/detail/LineHelper.hpp"
24 namespace {
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 ActsGeometryContext& 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  }
53  template<typename MeasType>
54  Amg::Vector3D positionInChamber(const MeasType& meas,
55  const Amg::Transform3D& toChamberTrans) {
56  if constexpr (std::is_same_v<MeasType, xAOD::MdtDriftCircle>){
57  return toChamberTrans * meas.localCirclePosition();
58  } else if constexpr (std::is_same_v<MeasType, xAOD::RpcMeasurement>){
59  return toChamberTrans * meas.localMeasurementPos();
60  } else if constexpr (std::is_same_v<MeasType, xAOD::TgcStrip>){
61  const auto& stripLay = meas.readoutElement()->sensorLayout(meas.layerHash());
62  return toChamberTrans * stripLay->to3D(meas.template localPosition<1>()[0]*Amg::Vector2D::UnitX(),
63  meas.measuresPhi());
64  } else if constexpr (std::is_same_v<MeasType, xAOD::MMCluster>){
65  return toChamberTrans * (meas.template localPosition<1>()[Trk::locX] * Amg::Vector3D::UnitX());
66  } else if constexpr (std::is_same_v<MeasType, xAOD::sTgcMeasurement>){
67  if (meas.channelType() == sTgcIdHelper::sTgcChannelTypes::Strip ||
68  meas.channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
69  return toChamberTrans * (meas.template localPosition<1>()[Trk::locX] * Amg::Vector3D::UnitX());
70  }
72  locPos.block<2,1>(0,0) = xAOD::toEigen(meas.template localPosition<2>());
73  return toChamberTrans * locPos;
74  } else {
75  static_assert(std::false_type::value, "Unsupported measurement type.");
76  }
77  return Amg::Vector3D::Zero();
78  }
81  template <typename PrdType>
82  double sensorHalfLength(const PrdType& prd) {
83  const auto* re = prd.readoutElement();
84  if constexpr(std::is_same_v<PrdType, xAOD::MdtDriftCircle>) {
85  return 0.5 * re->activeTubeLength(prd.measurementHash());
86  } else if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement>) {
87  return 0.5*(prd.measuresPhi() ? re->stripPhiLength() : re->stripEtaLength());
88  } else if constexpr(std::is_same_v<PrdType, xAOD::TgcStrip>) {
89  return 0.5 * re->sensorLayout(prd.layerHash())->design().stripLength(prd.channelNumber());
90  } else if constexpr(std::is_same_v<PrdType, xAOD::MMCluster>) {
91  return 0.5* re->stripLayer(prd.layerHash()).design().stripLength(prd.channelNumber());
92  } else if constexpr(std::is_same_v<PrdType, xAOD::sTgcMeasurement>) {
93  return 0.5* re->stripLayer(prd.layerHash()).design().stripLength(prd.channelNumber());
94  }
95  return 0.;
96  }
97 }
98 
99 namespace MuonR4 {
100 
105  if (techIdx != other.techIdx) {
106  return static_cast<int>(techIdx) < static_cast<int>(other.techIdx);
107  }
108  if (stIdx != other.stIdx) {
109  return static_cast<int>(stIdx) < static_cast<int>(other.stIdx);
110  }
111  return eta < other.eta;
112 }
114  return measEta + measPhi + measEtaPhi;
115 }
117  m_idHelperSvc{idHelperSvc}{}
118 
120  std::lock_guard guard{m_mutex};
121  for (const SpacePoint& sp : spacePoints){
122  FieldKey key{};
123  key.stIdx = m_idHelperSvc->stationIndex(sp.identify());
124  key.techIdx = m_idHelperSvc->technologyIndex(sp.identify());
125  key.eta = m_idHelperSvc->stationEta(sp.identify());
126  StatField & stats = m_map[key];
127  if (sp.measuresEta() && sp.measuresPhi()) {
128  ++stats.measEtaPhi;
129  } else {
130  stats.measEta += sp.measuresEta();
131  stats.measPhi += sp.measuresPhi();
132  }
133  }
134 }
136  using KeyVal = std::pair<FieldKey, StatField>;
137  std::vector<KeyVal> sortedstats{};
138  sortedstats.reserve(m_map.size());
140  for (const auto & [key, stats] : m_map){
141  sortedstats.emplace_back(std::make_pair(key, stats));
142  }
143  std::stable_sort(sortedstats.begin(), sortedstats.end(), [](const KeyVal& a, const KeyVal&b) {
144  return a.second.allHits() > b.second.allHits();
145  });
146  msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
147  for (const auto & [key, stats] : sortedstats) {
149  <<" "<<Muon::MuonStationIndex::stName(key.stIdx)
150  <<" "<<std::abs(key.eta)<<(key.eta < 0 ? "A" : "C")
151  <<" "<<std::setw(8)<<stats.measEtaPhi
152  <<" "<<std::setw(8)<<stats.measEta
153  <<" "<<std::setw(8)<<stats.measPhi<<endmsg;
154  }
155  msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
156 
157 }
162 
163 
165  if (m_statCounter) {
166  m_statCounter->dumpStatisics(msgStream());
167  }
168  return StatusCode::SUCCESS;
169 }
172  ATH_CHECK(m_mdtKey.initialize(!m_mdtKey.empty()));
173  ATH_CHECK(m_rpcKey.initialize(!m_rpcKey.empty()));
174  ATH_CHECK(m_tgcKey.initialize(!m_tgcKey.empty()));
175  ATH_CHECK(m_mmKey.initialize(!m_mmKey.empty()));
176  ATH_CHECK(m_stgcKey.initialize(!m_stgcKey.empty()));
177  ATH_CHECK(m_idHelperSvc.retrieve());
179  if (m_doStat) {
180  m_statCounter = std::make_unique<SpacePointStatistics>(m_idHelperSvc.get());
181  }
182  return StatusCode::SUCCESS;
183 }
184 
185 template <>
186  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::TgcStrip*>& etaHits,
187  const std::vector<const xAOD::TgcStrip*>& phiHits) const {
188  if (etaHits.empty() || phiHits.empty()) {
189  return false;
190  }
191  const MuonGMR4::TgcReadoutElement* re = etaHits[0]->readoutElement();
192  ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
193  return ((1.*etaHits.size()) / ((1.*re->numChannels(etaHits[0]->measurementHash())))) < m_maxOccTgcEta &&
194  ((1.*phiHits.size()) / ((1.*re->numChannels(phiHits[0]->measurementHash())))) < m_maxOccTgcPhi;
195  }
196 template <>
197  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::RpcMeasurement*>& etaHits,
198  const std::vector<const xAOD::RpcMeasurement*>& phiHits) const {
199  if (etaHits.empty() || phiHits.empty()) {
200  return false;
201  }
202  const MuonGMR4::RpcReadoutElement* re = etaHits[0]->readoutElement();
203  ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
204  return ((1.*etaHits.size()) / (1.*re->nEtaStrips())) < m_maxOccRpcEta &&
205  ((1.*phiHits.size()) / (1.*re->nPhiStrips())) < m_maxOccRpcPhi;
206  }
207 
208 template <>
209  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::sTgcMeasurement*>& etaHits,
210  const std::vector<const xAOD::sTgcMeasurement*>& phiHits) const {
211  if (etaHits.empty() || phiHits.empty()) {
212  return false;
213  }
214  const MuonGMR4::sTgcReadoutElement* re = etaHits[0]->readoutElement();
215  return ((1.*etaHits.size()) / (1.*re->numChannels(etaHits[0]->measurementHash()))) < m_maxOccStgcEta &&
216  ((1.*phiHits.size()) / (1.*re->numChannels(phiHits[0]->measurementHash()))) < m_maxOccStgcPhi;
217  }
218 template <>
219  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::MMCluster*>& /*etaHits*/,
220  const std::vector<const xAOD::MMCluster*>& /*phiHits*/) const {
221  return false;
222  }
223 template <typename PrdType>
225  const Amg::Transform3D& sectorTrans,
226  const std::vector<const PrdType*>& prdsToFill,
227  std::vector<SpacePoint>& outColl) const {
228  if (prdsToFill.empty()) {
229  return;
230  }
231  const Amg::Transform3D toSectorTrans = toChamberTransform(gctx, sectorTrans, *prdsToFill.front());
233  Amg::Vector3D sensorDir = toSectorTrans.rotation().col(Amg::y);
234  Amg::Vector3D toNextSen = toSectorTrans.rotation().col(Amg::x);
235  outColl.reserve(outColl.size() + prdsToFill.size());
236  for (const PrdType* prd: prdsToFill) {
237  SpacePoint& newSp = outColl.emplace_back(prd);
238  if constexpr (std::is_same_v<PrdType, xAOD::TgcStrip>) {
239  const bool isStrip = prd->measuresPhi();
240  const auto& stripLay = prd->readoutElement()->sensorLayout(prd->layerHash());
241  if (isStrip) {
242  const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(isStrip));
243  toNextSen = toSectorTrans.rotation() * stripLay->to3D(radialDesign.stripNormal(prd->channelNumber()), isStrip);
244  sensorDir = toSectorTrans.rotation() * stripLay->to3D(radialDesign.stripDir(prd->channelNumber()), isStrip);
245  } else {
246  toNextSen = toSectorTrans.rotation() * stripLay->to3D(Amg::Vector2D::UnitX(), isStrip);
247  sensorDir = toSectorTrans.rotation() * stripLay->to3D(Amg::Vector2D::UnitY(), isStrip);
248  }
249  }
250  newSp.setPosition(positionInChamber(*prd, toSectorTrans));
251  newSp.setDirection(sensorDir, toNextSen);
252  auto cov = Acts::filledArray<double,3>(0.);
253  if (prd->numDimensions() == 2) {
254  if constexpr(std::is_same_v<PrdType, xAOD::RpcMeasurement>) {
255  cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<2>()(0,0);
256  cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<2>()(1,1);
257  } else if constexpr(std::is_same_v<PrdType, xAOD::sTgcMeasurement>) {
258  cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<2>()(0,0);
259  cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<2>()(1,1);
260  } else {
261  ATH_MSG_WARNING("Unsupported measurement type. "<<typeid(PrdType).name());
262  // Prevent division by zero later on.
263  cov[Acts::toUnderlying(CovIdx::phiCov)] = 1;
264  cov[Acts::toUnderlying(CovIdx::etaCov)] = 1;
265  }
266  } else {
268  if (newSp.measuresEta()) {
269  cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->template localCovariance<1>()[0];
270  cov[Acts::toUnderlying(CovIdx::phiCov)] = Acts::square(sensorHalfLength(*prd));
271  } else {
272  cov[Acts::toUnderlying(CovIdx::phiCov)] = prd->template localCovariance<1>()[0];
273  cov[Acts::toUnderlying(CovIdx::etaCov)] = Acts::square(sensorHalfLength(*prd));
274  }
275  }
276  newSp.setCovariance(std::move(cov));
277  }
278 }
279 template <class ContType>
283  const ContType* measurementCont{nullptr};
284  ATH_CHECK(SG::get(measurementCont, key, ctx));
285  if (!measurementCont || measurementCont->empty()){
286  ATH_MSG_DEBUG("nothing to do");
287  return StatusCode::SUCCESS;
288  }
289  const ActsGeometryContext* gctx{nullptr};
290  ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
291 
292  using PrdType = typename ContType::const_value_type;
293  using PrdVec = std::vector<PrdType>;
294  xAOD::ChamberViewer viewer{*measurementCont};
295  do {
296  SpacePointsPerChamber& pointsInChamb = fillContainer[viewer.at(0)->readoutElement()->msSector()];
297  const Amg::Transform3D sectorTrans = viewer.at(0)->readoutElement()->msSector()->globalToLocalTrans(*gctx);
298  ATH_MSG_DEBUG("Fill space points for chamber "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
299  if constexpr( std::is_same_v<ContType, xAOD::MdtDriftCircleContainer>){
300  pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.capacity() + viewer.size());
301  for (const PrdType prd : viewer) {
302  Amg::Transform3D toChamberTrans{toChamberTransform(*gctx, sectorTrans, *prd)};
303  SpacePoint& sp{pointsInChamb.etaHits.emplace_back(prd)};
304  sp.setPosition(positionInChamber(*prd, toChamberTrans));
305  sp.setDirection(toChamberTrans.rotation().col(Amg::z),
306  toChamberTrans.rotation().col(Amg::y));
307  std::array<double, 3> cov{Acts::filledArray<double,3>(0.)};
308  cov[Acts::toUnderlying(CovIdx::etaCov)] = prd->driftRadiusCov();
309  cov[Acts::toUnderlying(CovIdx::phiCov)] = Acts::square(sensorHalfLength(*prd));
310  if (ATH_UNLIKELY(prd->numDimensions() == 2)){
311  cov[Acts::toUnderlying(CovIdx::phiCov)] = static_cast<const xAOD::MdtTwinDriftCircle*>(prd)->posAlongWireCov();
312  }
313  sp.setCovariance(std::move(cov));
314  }
315  } else {
317  using EtaPhi2DHits = std::array<PrdVec, 3>;
318  std::vector<EtaPhi2DHits> hitsPerGasGap{};
319  for (const PrdType prd : viewer) {
320  ATH_MSG_VERBOSE("Create space point from "<<m_idHelperSvc->toString(prd->identify())
321  <<", hash: "<<prd->identifierHash());
322 
323  unsigned gapIdx = prd->gasGap() -1;
324  if constexpr (std::is_same_v<ContType, xAOD::RpcMeasurementContainer>) {
325  gapIdx = prd->readoutElement()->createHash(0, prd->gasGap(), prd->doubletPhi(), false);
326  }
327  if (hitsPerGasGap.size() <= gapIdx) {
328  hitsPerGasGap.resize(gapIdx + 1);
329  }
330  bool measPhi{false};
331  if constexpr(std::is_same_v<ContType, xAOD::sTgcMeasContainer>) {
333  measPhi = prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
334  } else if constexpr(!std::is_same_v<ContType, xAOD::MMClusterContainer>) {
336  measPhi = prd->measuresPhi();
337  }
338 
339  if (prd->numDimensions() == 2) {
340  hitsPerGasGap[gapIdx][2].push_back(prd);
341  continue;
342  }
344  PrdVec& toPush = hitsPerGasGap[gapIdx][measPhi];
345  if (toPush.capacity() == toPush.size()) {
346  toPush.reserve(toPush.size() + m_capacityBucket);
347  }
348  toPush.push_back(prd);
349  }
350 
351  for (auto& [etaHits, phiHits, two2DHits] : hitsPerGasGap) {
352  ATH_MSG_DEBUG("Found "<<etaHits.size()<<"/"<<phiHits.size()<<" 1D and "<<two2DHits.size()<<" 2D hits in chamber "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
354  fillUncombinedSpacePoints(*gctx, sectorTrans, two2DHits, pointsInChamb.etaHits);
356  if (!passOccupancy2D(etaHits, phiHits)) {
357  fillUncombinedSpacePoints(*gctx, sectorTrans, etaHits, pointsInChamb.etaHits);
358  fillUncombinedSpacePoints(*gctx, sectorTrans, phiHits, pointsInChamb.phiHits);
359  continue;
360  }
361 
362  std::vector<std::shared_ptr<unsigned>> etaCounts{matchCountVec(etaHits.size())},
363  phiCounts{matchCountVec(phiHits.size())};
364  pointsInChamb.etaHits.reserve(etaHits.size()*phiHits.size());
366  const Amg::Transform3D toSectorTransEta = toChamberTransform(*gctx,sectorTrans, *etaHits.front());
367  const Amg::Transform3D toSectorTransPhi = toChamberTransform(*gctx,sectorTrans, *phiHits.front());
368 
369  Amg::Vector3D toNextDir = toSectorTransEta.rotation().col(Amg::x);
370  Amg::Vector3D sensorDir = toSectorTransPhi.rotation().col(Amg::x);
371  using namespace Acts::detail::LineHelper;
372  for (unsigned etaP = 0; etaP < etaHits.size(); ++etaP) {
374  for (unsigned phiP = 0; phiP < phiHits.size(); ++ phiP) {
377  if (!(etaHits[etaP]->bcBitMap() & phiHits[phiP]->bcBitMap())){
378  continue;
379  }
380  const auto& stripLay = phiHits[phiP]->readoutElement()->sensorLayout(phiHits[phiP]->layerHash());
381  const auto& radialDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(true));
382  toNextDir = toSectorTransPhi.rotation() * stripLay->to3D(radialDesign.stripDir(phiHits[phiP]->channelNumber()), true);
383  }
384  SpacePoint& newSp = pointsInChamb.etaHits.emplace_back(etaHits[etaP], phiHits[phiP]);
385  newSp.setInstanceCounts(etaCounts[etaP], phiCounts[phiP]);
386 
387  auto spIsect = lineIntersect(positionInChamber(*etaHits[etaP], toSectorTransEta), sensorDir,
388  positionInChamber(*phiHits[phiP], toSectorTransPhi), toNextDir);
389  newSp.setPosition(spIsect.position());
390  newSp.setDirection(sensorDir, toNextDir);
391  auto cov = Acts::filledArray<double, 3>(0.);
392  cov[Acts::toUnderlying(CovIdx::etaCov)] = etaHits[etaP]->template localCovariance<1>()[0];
393  cov[Acts::toUnderlying(CovIdx::phiCov)] = phiHits[phiP]->template localCovariance<1>()[0];
394  newSp.setCovariance(std::move(cov));
395  }
396  }
397  }
398  }
399  } while (viewer.next());
400  return StatusCode::SUCCESS;
401 }
402 
403 
404 StatusCode SpacePointMakerAlg::execute(const EventContext& ctx) const {
405  PreSortedSpacePointMap preSortedContainer{};
406  ATH_CHECK(loadContainerAndSort(ctx, m_mdtKey, preSortedContainer));
407  ATH_CHECK(loadContainerAndSort(ctx, m_rpcKey, preSortedContainer));
408  ATH_CHECK(loadContainerAndSort(ctx, m_tgcKey, preSortedContainer));
409  ATH_CHECK(loadContainerAndSort(ctx, m_mmKey, preSortedContainer));
410  ATH_CHECK(loadContainerAndSort(ctx, m_stgcKey, preSortedContainer));
411  std::unique_ptr<SpacePointContainer> outContainer = std::make_unique<SpacePointContainer>();
412 
413  for (auto &[chamber, hitsPerChamber] : preSortedContainer){
414  ATH_MSG_DEBUG("Fill space points for chamber "<<chamber->identString() << " with "<<hitsPerChamber.etaHits.size()
415  <<" primary and "<<hitsPerChamber.phiHits.size()<<" phi space points.");
416  distributePointsAndStore(std::move(hitsPerChamber), *outContainer);
417  }
419  ATH_CHECK(writeHandle.record(std::move(outContainer)));
420  return StatusCode::SUCCESS;
421 }
422 
424  SpacePointContainer& finalContainer) const {
425  SpacePointBucketVec splittedHits{};
426  splittedHits.emplace_back();
427  if (m_statCounter){
428  m_statCounter->addToStat(hitsPerChamber.etaHits);
429  m_statCounter->addToStat(hitsPerChamber.phiHits);
430 
431  }
432  distributePrimaryPoints(std::move(hitsPerChamber.etaHits), splittedHits);
433  splittedHits.erase(std::remove_if(splittedHits.begin(), splittedHits.end(),
434  [](const SpacePointBucket& bucket) {
435  return bucket.size() <= 1;
436  }), splittedHits.end());
437  distributePhiPoints(std::move(hitsPerChamber.phiHits), splittedHits);
438 
439  for (SpacePointBucket& bucket : splittedHits) {
440 
441  std::ranges::sort(bucket, MuonR4::SpacePointPerLayerSorter{});
442 
443  if (msgLvl(MSG::VERBOSE)){
444  std::stringstream spStr{};
445  for (const std::shared_ptr<SpacePoint>& sp : bucket){
446  spStr<<"SpacePoint: PrimaryMeas: " <<(*sp)<<std::endl;
447  }
448  ATH_MSG_VERBOSE("Created a bucket, printing all spacepoints..."<<std::endl<<spStr.str());
449  }
450  bucket.populateChamberLocations();
451  finalContainer.push_back(std::make_unique<SpacePointBucket>(std::move(bucket)));
452  }
453 
454 }
456  SpacePointBucketVec& splittedContainer) const{
457  for (SpacePoint& sp : spacePoints) {
458  auto phiPoint = std::make_shared<SpacePoint>(std::move(sp));
459  const double dY = std::sqrt(phiPoint->covariance()[Acts::toUnderlying(CovIdx::etaCov)]);
460  const double minY = phiPoint->localPosition().y() - dY;
461  const double maxY = phiPoint->localPosition().y() + dY;
462  for (SpacePointBucket& bucket : splittedContainer){
465  if (! (maxY < bucket.coveredMin() || bucket.coveredMax() < minY) ) {
466  bucket.emplace_back(phiPoint);
467  }
468  }
469  }
470 }
472  const double firstSpPos,
473  const SpacePointBucketVec& sortedPoints) const {
475  const double spY = spacePoint.localPosition().y();
476  if (spY - firstSpPos > m_maxBucketLength){
477  return true;
478  }
479 
480  if (sortedPoints.empty() || sortedPoints.back().empty()) {
481  return false;
482  }
483  return spY - sortedPoints.back().back()->localPosition().y() > m_spacePointWindow;
484 }
485 void SpacePointMakerAlg::newBucket(const SpacePoint& refSpacePoint,
486  SpacePointBucketVec& sortedPoints) const {
487  SpacePointBucket& newContainer = sortedPoints.emplace_back();
488  newContainer.setBucketId(sortedPoints.size() -1);
489 
491  SpacePointBucket& overlap{sortedPoints[sortedPoints.size() - 2]};
492  overlap.setCoveredRange(overlap.front()->localPosition().y(),
493  overlap.back()->localPosition().y());
494 
495  const double refBound = refSpacePoint.localPosition().y();
496 
498  for (const std::shared_ptr<SpacePoint>& pointInBucket : overlap | std::views::reverse) {
499  const double overlapPos = pointInBucket->localPosition().y() +
500  std::sqrt(pointInBucket->covariance()[Acts::toUnderlying(CovIdx::etaCov)]);
501  if (refBound - overlapPos < m_spacePointOverlap) {
502  newContainer.insert(newContainer.begin(), pointInBucket);
503  } else {
504  break;
505  }
506  }
507 
508 }
509 
511  SpacePointBucketVec& splittedHits) const {
512 
513  if (spacePoints.empty()) return;
514 
516  std::ranges::sort(spacePoints,
517  [] (const SpacePoint& a, const SpacePoint& b) {
518  return a.localPosition().y() < b.localPosition().y();
519  });
520 
521  double firstPointPos = spacePoints.front().localPosition().y();
522 
523  for (SpacePoint& toSort : spacePoints) {
524  ATH_MSG_VERBOSE("Add new primary space point "<<toSort);
525 
526  if (splitBucket(toSort, firstPointPos, splittedHits)){
527  newBucket(toSort, splittedHits);
528  firstPointPos = splittedHits.back().empty() ? toSort.localPosition().y() : splittedHits.back().front()->localPosition().y();
529  ATH_MSG_VERBOSE("New bucket: id " << splittedHits.back().bucketId() << " Coverage: " << firstPointPos);
530  }
531  std::shared_ptr<SpacePoint> spacePoint = std::make_shared<SpacePoint>(std::move(toSort));
532  splittedHits.back().emplace_back(spacePoint);
533  }
534  SpacePointBucket& lastBucket{splittedHits.back()};
535  lastBucket.setCoveredRange(lastBucket.front()->localPosition().y(),
536  lastBucket.back()->localPosition().y());
537 }
538 
539 }
MuonR4::SpacePoint::setCovariance
void setCovariance(Cov_t &&cov)
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:66
MuonR4::SpacePointMakerAlg::SpacePointStatistics::StatField::allHits
unsigned allHits() const
Helper method returning the sum of the three space point type counts.
Definition: SpacePointMakerAlg.cxx:113
UncalibratedMeasurement.h
MuonR4::SpacePointMakerAlg::PreSortedSpacePointMap
std::unordered_map< const MuonGMR4::SpectrometerSector *, SpacePointsPerChamber > PreSortedSpacePointMap
Container abrivation of the presorted space point container per MuonChambers.
Definition: SpacePointMakerAlg.h:93
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::operator<
bool operator<(const FieldKey &other) const
Definition: SpacePointMakerAlg.cxx:104
MuonR4::SpacePointMakerAlg::m_stgcKey
SG::ReadHandleKey< xAOD::sTgcMeasContainer > m_stgcKey
Definition: SpacePointMakerAlg.h:176
MuonR4::SpacePoint::setDirection
void setDirection(const Amg::Vector3D &sensorDir, const Amg::Vector3D &toNextSensor)
Setter for the direction of the measurement channel in the sector frame.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:67
MuonR4::SpacePointMakerAlg::SpacePointStatistics::addToStat
void addToStat(const std::vector< SpacePoint > &spacePoints)
Adds the vector of space points to the overall statistics.
Definition: SpacePointMakerAlg.cxx:119
MuonR4::SpacePointBucket
: The muon space point bucket represents a collection of points that will bre processed together in t...
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/MuonSpacePoint/SpacePointContainer.h:21
Trk::locX
@ locX
Definition: ParamDefs.h:37
AthMsgStreamMacros.h
MuonR4::SpacePointPerLayerSorter
The SpacePointPerLayerSorter sort two given space points by their layer Identifier.
Definition: SpacePointPerLayerSorter.h:15
calibdata.chamber
chamber
Definition: calibdata.py:31
MuonR4::SpacePointMakerAlg::initialize
StatusCode initialize() override
Definition: SpacePointMakerAlg.cxx:170
MuonR4::SpacePointMakerAlg::execute
StatusCode execute(const EventContext &ctx) const override
Definition: SpacePointMakerAlg.cxx:404
MuonR4::SpacePointMakerAlg::distributePrimaryPoints
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.
Definition: SpacePointMakerAlg.cxx:510
Muon::MuonStationIndex::stName
const std::string & stName(StIndex index)
convert StIndex into a string
Definition: MuonStationIndex.cxx:104
MuonR4::SpacePointMakerAlg::splitBucket
bool splitBucket(const SpacePoint &spacePoint, const double firstSpPos, const SpacePointBucketVec &sortedPoints) const
Returns whether the space point is beyond the bucket boundary.
Definition: SpacePointMakerAlg.cxx:471
Amg::y
@ y
Definition: GeoPrimitives.h:35
MuonR4::SpacePointMakerAlg::m_maxOccStgcPhi
Gaudi::Property< double > m_maxOccStgcPhi
Definition: SpacePointMakerAlg.h:213
MuonR4::SpacePointBucket::populateChamberLocations
void populateChamberLocations()
populate the chamber location list.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePointContainer.cxx:23
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:200
MuonGMR4::MuonReadoutElement
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:38
MuonR4::SpacePointBucket::setCoveredRange
void setCoveredRange(double min, double max)
set the range in the precision plane covered by the bucket
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePointContainer.cxx:16
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
MuonR4::SpacePointMakerAlg::SpacePointStatistics::m_idHelperSvc
const Muon::IMuonIdHelperSvc * m_idHelperSvc
Definition: SpacePointMakerAlg.h:78
MuonR4::SpacePointMakerAlg::SpacePointsPerChamber::etaHits
std::vector< SpacePoint > etaHits
Vector of all hits that contain an eta measurement including the ones which are combined with phi mea...
Definition: SpacePointMakerAlg.h:88
AthCommonMsg< Gaudi::Algorithm >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
athena.value
value
Definition: athena.py:124
MuonR4::SpacePointMakerAlg::m_rpcKey
SG::ReadHandleKey< xAOD::RpcMeasurementContainer > m_rpcKey
Definition: SpacePointMakerAlg.h:167
MdtTwinDriftCircle.h
ATH_UNLIKELY
#define ATH_UNLIKELY(x)
Definition: AthUnlikelyMacros.h:17
MuonR4::SpacePointMakerAlg::distributePhiPoints
void distributePhiPoints(std::vector< SpacePoint > &&spacePoints, SpacePointBucketVec &splittedContainer) const
Distributs the vector phi space points into the buckets.
Definition: SpacePointMakerAlg.cxx:455
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::ReadHandleKey
Property holding a SG store/key/clid from which a ReadHandle is made.
Definition: StoreGate/StoreGate/ReadHandleKey.h:39
MuonR4::SpacePoint::CovIdx::etaCov
@ etaCov
trigbs_dumpHLTContentInBS.stats
stats
Definition: trigbs_dumpHLTContentInBS.py:91
MuonGMR4::RpcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:17
MuonR4::SpacePointMakerAlg::m_mmKey
SG::ReadHandleKey< xAOD::MMClusterContainer > m_mmKey
Definition: SpacePointMakerAlg.h:173
RpcStrip.h
MuonR4::SpacePointMakerAlg::newBucket
void newBucket(const SpacePoint &refSp, SpacePointBucketVec &sortedPoints) const
Closes the current processed bucket and creates a new one.
Definition: SpacePointMakerAlg.cxx:485
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
GeoPrimitives.h
xAOD::ChamberViewer
Definition: ChamberViewer.h:59
WriteHandle.h
Handle class for recording to StoreGate.
Amg::z
@ z
Definition: GeoPrimitives.h:36
MuonR4::SpacePointMakerAlg::SpacePointBucketVec
std::vector< SpacePointBucket > SpacePointBucketVec
Abrivation of a MuonSapcePoint bucket vector.
Definition: SpacePointMakerAlg.h:96
MuonR4::SpacePointMakerAlg::SpacePointsPerChamber
: Helper struct to collect the space point per muon chamber, which are later sorted into the space po...
Definition: SpacePointMakerAlg.h:85
MuonR4::SpacePointMakerAlg::m_tgcKey
SG::ReadHandleKey< xAOD::TgcStripContainer > m_tgcKey
Definition: SpacePointMakerAlg.h:170
MuonR4::SpacePointMakerAlg::m_writeKey
SG::WriteHandleKey< SpacePointContainer > m_writeKey
Definition: SpacePointMakerAlg.h:183
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
MuonR4::SpacePointBucket::setBucketId
void setBucketId(unsigned int id)
sets the Identifier of the MuonSpacePointBucket in context of the associated muonChamber
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePointContainer.cxx:20
MuonR4::SpacePointMakerAlg::m_maxOccStgcEta
Gaudi::Property< double > m_maxOccStgcEta
Definition: SpacePointMakerAlg.h:211
EventPrimitivesToStringConverter.h
TrigConf::MSGTC::ALWAYS
@ ALWAYS
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:29
SG::get
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
Definition: ReadCondHandle.h:287
beamspotman.n
n
Definition: beamspotman.py:727
MuonR4::SpacePointMakerAlg::SpacePointStatistics::StatField
Helper struct to count the space-points in each detector category.
Definition: SpacePointMakerAlg.h:57
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
MuonR4::SpacePoint::setPosition
void setPosition(Amg::Vector3D &&pos)
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:73
Amg::x
@ x
Definition: GeoPrimitives.h:34
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MuonR4::SpacePointMakerAlg::SpacePointsPerChamber::phiHits
std::vector< SpacePoint > phiHits
Vector of all space points that are built from single phi hits.
Definition: SpacePointMakerAlg.h:90
MuonR4::SpacePointMakerAlg::m_maxOccTgcEta
Gaudi::Property< double > m_maxOccTgcEta
Definition: SpacePointMakerAlg.h:206
xAOD::MdtTwinDriftCircle_v1
Definition: MdtTwinDriftCircle_v1.h:12
MuonR4::SpacePointMakerAlg::SpacePointStatistics::dumpStatisics
void dumpStatisics(MsgStream &msg) const
Print the statistics table of the built space points per category into the log-file / console.
Definition: SpacePointMakerAlg.cxx:135
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
Muon::MuonStationIndex::technologyName
const std::string & technologyName(TechnologyIndex index)
convert LayerIndex into a string
Definition: MuonStationIndex.cxx:169
F600IntegrationConfig.spacePoints
spacePoints
Definition: F600IntegrationConfig.py:122
MeasurementDefs.h
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
MuonR4::SpacePointMakerAlg::m_maxOccTgcPhi
Gaudi::Property< double > m_maxOccTgcPhi
Definition: SpacePointMakerAlg.h:208
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
MuonR4::SpacePointMakerAlg::fillUncombinedSpacePoints
void fillUncombinedSpacePoints(const ActsGeometryContext &gctx, const Amg::Transform3D &sectorTrans, const std::vector< const PrdType * > &prdsToFill, std::vector< SpacePoint > &outColl) const
Fills all space points that are beloni.
Definition: SpacePointMakerAlg.cxx:224
MuonR4::SpacePoint
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/MuonSpacePoint/SpacePoint.h:24
MuonR4::SpacePointMakerAlg::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: SpacePointMakerAlg.h:181
NSWL1::PadTriggerAdapter::fillContainer
StatusCode fillContainer(const std::unique_ptr< Muon::NSW_PadTriggerDataContainer > &out, const std::vector< std::unique_ptr< NSWL1::PadTrigger >> &triggers, const uint32_t l1id)
Definition: PadTriggerAdapter.cxx:17
dumpTgcDigiThreshold.isStrip
list isStrip
Definition: dumpTgcDigiThreshold.py:33
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::techIdx
TechIdx_t techIdx
Definition: SpacePointMakerAlg.h:73
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::stIdx
StIdx_t stIdx
Definition: SpacePointMakerAlg.h:72
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
MuonR4::SpacePoint::CovIdx::phiCov
@ phiCov
MuonR4::SpacePointMakerAlg::loadContainerAndSort
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 ...
Definition: SpacePointMakerAlg.cxx:280
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
ChamberViewer.h
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonGMR4::sTgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/sTgcReadoutElement.h:20
MuonR4::SpacePointMakerAlg::m_mdtKey
SG::ReadHandleKey< xAOD::MdtDriftCircleContainer > m_mdtKey
Definition: SpacePointMakerAlg.h:164
MuonR4
This header ties the generic definitions in this package.
Definition: HoughEventData.h:16
MuonR4::SpacePoint::setInstanceCounts
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.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:100
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
MuonR4::SpacePointMakerAlg::m_capacityBucket
Gaudi::Property< unsigned > m_capacityBucket
Definition: SpacePointMakerAlg.h:198
MuonR4::SpacePoint::localPosition
const Amg::Vector3D & localPosition() const
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:50
MuonR4::SpacePointMakerAlg::passOccupancy2D
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.
MuonR4::SpacePointMakerAlg::m_maxBucketLength
Gaudi::Property< double > m_maxBucketLength
Definition: SpacePointMakerAlg.h:188
MuonR4::SpacePointMakerAlg::m_spacePointWindow
Gaudi::Property< double > m_spacePointWindow
Definition: SpacePointMakerAlg.h:185
MuonR4::SpacePointMakerAlg::SpacePointStatistics::SpacePointStatistics
SpacePointStatistics(const Muon::IMuonIdHelperSvc *idHelperSvc)
Standard constructor.
Definition: SpacePointMakerAlg.cxx:116
a
TList * a
Definition: liststreamerinfos.cxx:10
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
y
#define y
MuonR4::SpacePoint::measuresEta
bool measuresEta() const
: Does the space point contain an eta measurement
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:94
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
re
const boost::regex re(r_e)
MuonR4::SpacePointMakerAlg::finalize
StatusCode finalize() override
Definition: SpacePointMakerAlg.cxx:164
AthCommonMsg< Gaudi::Algorithm >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
GeoPrimitivesToStringConverter.h
Muon::IMuonIdHelperSvc
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
Definition: IMuonIdHelperSvc.h:27
MuonGMR4::MuonReadoutElement::localToGlobalTrans
const Amg::Transform3D & localToGlobalTrans(const ActsGeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:81
MuonR4::SpacePointMakerAlg::m_doStat
Gaudi::Property< bool > m_doStat
Definition: SpacePointMakerAlg.h:195
MuonR4::SpacePointMakerAlg::m_geoCtxKey
SG::ReadHandleKey< ActsGeometryContext > m_geoCtxKey
Definition: SpacePointMakerAlg.h:179
MuonR4::SpacePoint::CovIdx
CovIdx
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/MuonSpacePoint/SpacePoint.h:30
MuonR4::SpacePointMakerAlg::m_maxOccRpcEta
Gaudi::Property< double > m_maxOccRpcEta
Definition: SpacePointMakerAlg.h:201
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
ReadHandle.h
Handle class for reading from StoreGate.
SpacePointMakerAlg.h
MuonGMR4::RadialStripDesign
Definition: RadialStripDesign.h:23
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::eta
int eta
Definition: SpacePointMakerAlg.h:74
SpacePointPerLayerSorter.h
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:19
MuonR4::SpacePointMakerAlg::distributePointsAndStore
void distributePointsAndStore(SpacePointsPerChamber &&hitsPerChamber, SpacePointContainer &finalContainer) const
Distribute the premade spacepoints per chamber into their individual SpacePoint buckets.
Definition: SpacePointMakerAlg.cxx:423
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey
Helper struct to define the counting categories.
Definition: SpacePointMakerAlg.h:69
MuonR4::SpacePointMakerAlg::m_spacePointOverlap
Gaudi::Property< double > m_spacePointOverlap
Definition: SpacePointMakerAlg.h:191
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
MuonR4::SpacePointMakerAlg::m_maxOccRpcPhi
Gaudi::Property< double > m_maxOccRpcPhi
Definition: SpacePointMakerAlg.h:203