ATLAS Offline Software
SpacePointMakerAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 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>
20 namespace {
21  inline std::vector<std::shared_ptr<unsigned>> matchCountVec(unsigned int n) {
22  std::vector<std::shared_ptr<unsigned>> out{};
23  out.reserve(n);
24  for (unsigned int p = 0; p < n ;++p) {
25  out.emplace_back(std::make_shared<unsigned>(0));
26  }
27  return out;
28  }
29 }
30 
31 namespace MuonR4 {
32 
33 template<class MeasType>
35  const Amg::Transform3D& sectorTrans,
36  const MeasType* meas) const{
37  IdentifierHash hash = {};
38  if constexpr(std::is_same_v<MeasType, xAOD::MdtDriftCircle>) {
39  hash = meas->measurementHash();
40  } else {
41  hash = meas->layerHash();
42  }
43  const MuonGMR4::MuonReadoutElement* reEle{meas->readoutElement()};
44  return sectorTrans * reEle->localToGlobalTrans(gctx, hash);
45 }
46 
47 template<class MeasType>
49  const Amg::Transform3D& toChamberTrans) const{
50  if constexpr (std::is_same_v<MeasType, xAOD::MdtDriftCircle>){
51  return toChamberTrans * meas->localCirclePosition();
52  } else if constexpr (std::is_same_v<MeasType, xAOD::RpcMeasurement>){
53  return toChamberTrans * meas->localMeasurementPos();
54  } else if constexpr (std::is_same_v<MeasType, xAOD::TgcStrip>){
55  const auto& stripLay = meas->readoutElement()->sensorLayout(meas->layerHash());
56  return toChamberTrans * stripLay->to3D(meas->template localPosition<1>()[0]*Amg::Vector2D::UnitX(),
57  meas->measuresPhi());
58  } else if constexpr (std::is_same_v<MeasType, xAOD::MMCluster>){
59  return toChamberTrans * (meas->template localPosition<1>()[Trk::locX] * Amg::Vector3D::UnitX());
60  }
61  else if constexpr (std::is_same_v<MeasType, xAOD::sTgcMeasurement>){
62  if (meas->channelType() == sTgcIdHelper::sTgcChannelTypes::Strip ||
63  meas->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
64  return toChamberTrans * (meas->template localPosition<1>()[Trk::locX] * Amg::Vector3D::UnitX());
65  }
67  locPos.block<2,1>(0,0) = xAOD::toEigen(meas->template localPosition<2>());
68  return toChamberTrans * locPos;
69  }
70  else static_assert(std::false_type::value, "Unsupported measurement type.");
71  return Amg::Vector3D::Zero();
72 }
73 
74 template<class MeasType>
76  const Amg::Transform3D& toChamberTrans) const{
77  if constexpr (std::is_same_v<MeasType, xAOD::MdtDriftCircle>){
78  return toChamberTrans.linear() * Amg::Vector3D::UnitZ();
79  }
80  else if constexpr (std::is_same_v<MeasType, xAOD::RpcMeasurement> or
81  std::is_same_v<MeasType, xAOD::MMCluster> or
82  std::is_same_v<MeasType, xAOD::sTgcMeasurement>){
83  return toChamberTrans.linear() * Amg::Vector3D::UnitY();
84  }
85  else if constexpr (std::is_same_v<MeasType, xAOD::TgcStrip>) {
86  const auto& stripLay = meas->readoutElement()->sensorLayout(meas->layerHash());
87  if (meas->measuresPhi()) {
88  const auto& sDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(true));
89  return toChamberTrans.linear() * stripLay->to3D(sDesign.stripDir(meas->channelNumber()), true);
90  }
91  return toChamberTrans.linear() * stripLay->to3D(stripLay->design().stripDir(), false);
92  }
93  else static_assert(std::false_type::value, "Unsupported measurement type.");
94  return Amg::Vector3D::Zero();
95 }
96 
97 template<class MeasType>
99  const Amg::Transform3D& toChamberTrans) const{
100  if constexpr (std::is_same_v<MeasType, xAOD::MdtDriftCircle>){
101  return toChamberTrans.linear() * Amg::Vector3D::UnitY();
102  }
103  else if constexpr (std::is_same_v<MeasType, xAOD::RpcMeasurement> or
104  std::is_same_v<MeasType, xAOD::MMCluster> or
105  std::is_same_v<MeasType, xAOD::sTgcMeasurement>){
106  return toChamberTrans.linear() * Amg::Vector3D::UnitX();
107  }
108  else if constexpr (std::is_same_v<MeasType, xAOD::TgcStrip>) {
109  const auto& stripLay = meas->readoutElement()->sensorLayout(meas->layerHash());
110  if (meas->measuresPhi()) {
111  const auto& sDesign = static_cast<const MuonGMR4::RadialStripDesign&>(stripLay->design(true));
112  return toChamberTrans.linear() * stripLay->to3D(sDesign.stripNormal(meas->channelNumber()), true);
113  }
114  return toChamberTrans.linear() * stripLay->to3D(stripLay->design().stripNormal(), false);
115  }
116  else static_assert(std::false_type::value, "Unsupported measurement type.");
117  return Amg::Vector3D::Zero();
118 }
119 
120 template<class MeasType>
121 AmgSymMatrix(2) SpacePointMakerAlg::computeCov(const MeasType* primaryMeas,
122  const Amg::Vector3D& dir,
123  const Amg::Vector3D& nor) const {
124  AmgSymMatrix(2) Jac{AmgSymMatrix(2)::Identity()}, uvcov {AmgSymMatrix(2)::Identity()};
125 
126  if (primaryMeas->numDimensions() == 1) {
127  uvcov(0,0) = primaryMeas->template localCovariance<1>()[0];
128 
129  if constexpr (std::is_same_v<MeasType, xAOD::MdtDriftCircle>) {
130  uvcov(1,1) = 0.5* primaryMeas->readoutElement()->activeTubeLength(primaryMeas->measurementHash());
131  }
132  else if constexpr (std::is_same_v<MeasType, xAOD::RpcMeasurement>) {
133  if (primaryMeas->numDimensions() == 1) {
134  const xAOD::RpcStrip* strip = static_cast<const xAOD::RpcStrip*>(primaryMeas);
135  uvcov(1,1) = strip->measuresPhi() ? 0.5* strip->readoutElement()->stripPhiLength(): 0.5* strip->readoutElement()->stripEtaLength();
136  }
137  }
138  else if constexpr (std::is_same_v<MeasType, xAOD::TgcStrip>){
139  if (primaryMeas->measuresPhi()) {
140  uvcov(1,1) = 0.5 * primaryMeas->readoutElement()->stripLayout(primaryMeas->layerHash()).stripLength(primaryMeas->channelNumber());
141  } else {
142  uvcov(1,1) = 0.5 * primaryMeas->readoutElement()->wireGangLayout(primaryMeas->layerHash()).stripLength(primaryMeas->channelNumber());
143  }
144  }
145  else if constexpr (std::is_same_v<MeasType, xAOD::MMCluster>){
146  uvcov(1,1) = 0.5 * primaryMeas->readoutElement()->stripLayer(primaryMeas->measurementHash()).design().stripLength(primaryMeas->channelNumber());
147  }
148  else if constexpr (std::is_same_v<MeasType, xAOD::sTgcMeasurement>){
149  switch (primaryMeas->channelType()) {
150  case sTgcIdHelper::sTgcChannelTypes::Strip:
151  uvcov(1,1) = 0.5 * primaryMeas->readoutElement()->stripDesign(primaryMeas->measurementHash()).stripLength(primaryMeas->channelNumber());
152  break;
153  case sTgcIdHelper::sTgcChannelTypes::Wire:
154  uvcov(1,1) = 0.5 * primaryMeas->readoutElement()->wireDesign(primaryMeas->measurementHash()).stripLength(primaryMeas->channelNumber());
155  break;
157  case sTgcIdHelper::sTgcChannelTypes::Pad:
158  break;
159  }
160  }
161  else static_assert(std::false_type::value, "Unsupported measurement type.");
162 
163  uvcov(1,1) = std::pow(uvcov(1,1), 2);
164  }
165  else if (primaryMeas->numDimensions() == 2){
169  uvcov = xAOD::toEigen(primaryMeas->template localCovariance<2>());
170  }
171  else THROW_EXCEPTION("Unexpected numDimension for PRD: " << m_idHelperSvc->toString(primaryMeas->identify()));
172 
173  Jac.col(0) = nor.block<2,1>(0,0).unit();
174  Jac.col(1) = dir.block<2,1>(0,0).unit();
175 
176  return Jac * uvcov * Jac.inverse();
177 }
178 
179 AmgSymMatrix(2) SpacePointMakerAlg::computeCov(const xAOD::UncalibratedMeasurement* primaryMeas,
180  const xAOD::UncalibratedMeasurement* secondaryMeas,
181  const Amg::Vector3D& nor1,
182  const Amg::Vector3D& nor2) const {
183  AmgSymMatrix(2) Jac{AmgSymMatrix(2)::Identity()}, uvcov {AmgSymMatrix(2)::Identity()};
184 
185  if (primaryMeas->numDimensions() != 1) {
186  THROW_EXCEPTION("Unexpected numDimension");
187  }
188  uvcov(0,0) = primaryMeas->localCovariance<1>()[0];
189  uvcov(1,1) = secondaryMeas->localCovariance<1>()[0];
190  Jac.col(0) = nor1.block<2,1>(0,0).unit();
191  Jac.col(1) = nor2.block<2,1>(0,0).unit();
192  return Jac * uvcov * Jac.inverse();
193 }
194 
195 template<class MeasType>
196 void SpacePointMakerAlg::fillSpacePoint (std::vector<SpacePoint>& pointColl,
197  const MeasType* primaryMeas,
198  const Amg::Transform3D& toChamberTrans) const {
199  pointColl.emplace_back(primaryMeas);
200  SpacePoint& sp {pointColl.back()};
201 
202  sp.setDirection(channelDirInChamber(primaryMeas, toChamberTrans));
203  sp.setNormal(channelNormalInChamber(primaryMeas, toChamberTrans));
204  sp.setPosition(positionInChamber(primaryMeas, toChamberTrans));
205  sp.setCovariance(computeCov(primaryMeas,sp.directionInChamber(),sp.normalInChamber()));
206  ATH_MSG_VERBOSE("Space point 1D: "<<m_idHelperSvc->toString(primaryMeas->identify())<<", "<<Amg::toString(sp.positionInChamber())
207  <<", "<<Amg::toString(sp.directionInChamber())<<", "<<Amg::toString(sp.normalInChamber()));
208 }
209 
210 template<class MeasType>
211 void SpacePointMakerAlg::fillSpacePoint(std::vector<SpacePoint>& pointColl,
212  const MeasType* primaryMeas,
213  const MeasType* secondaryMeas,
214  const Amg::Transform3D& toChamberTrans_eta,
215  const Amg::Transform3D& toChamberTrans_phi) const{
216  pointColl.emplace_back(primaryMeas, secondaryMeas);
217  SpacePoint& sp {pointColl.back()};
218 
219  sp.setDirection(channelDirInChamber(primaryMeas, toChamberTrans_eta));
220  sp.setNormal(channelNormalInChamber(primaryMeas, toChamberTrans_eta));
221 
222  Amg::Vector3D pos1 {positionInChamber(primaryMeas, toChamberTrans_eta)};
223  Amg::Vector3D dir2 {channelDirInChamber(secondaryMeas, toChamberTrans_phi)};
224  Amg::Vector3D pos2 {positionInChamber(secondaryMeas, toChamberTrans_phi)};
225  sp.setPosition(pos1 + Amg::intersect<3>(pos2,dir2, pos1, sp.directionInChamber()).value_or(0) * sp.directionInChamber());
226  ATH_MSG_VERBOSE("Space point: "<<m_idHelperSvc->toString(primaryMeas->identify())<<", "<<Amg::toString(pos1)
227  <<", "<<Amg::toString(sp.directionInChamber())<<", "<<Amg::toString(dir2));
228  sp.setCovariance(computeCov(primaryMeas,
229  secondaryMeas,
230  sp.normalInChamber(),
231  channelNormalInChamber(secondaryMeas, toChamberTrans_phi))
232  );
233 
234 }
235 
237  if (techIdx != other.techIdx) {
238  return static_cast<int>(techIdx) < static_cast<int>(other.techIdx);
239  }
240  if (stIdx != other.stIdx) {
241  return static_cast<int>(stIdx) < static_cast<int>(other.stIdx);
242  }
243  return eta < other.eta;
244 }
246  return measEta + measPhi + measEtaPhi;
247 }
249  m_idHelperSvc{idHelperSvc}{}
250 
251 void SpacePointMakerAlg::SpacePointStatistics::addToStat(const std::vector<SpacePoint>& spacePoints){
252  std::lock_guard guard{m_mutex};
253  for (const SpacePoint& sp : spacePoints){
254  FieldKey key{};
255  key.stIdx = m_idHelperSvc->stationIndex(sp.identify());
256  key.techIdx = m_idHelperSvc->technologyIndex(sp.identify());
257  key.eta = m_idHelperSvc->stationEta(sp.identify());
258  StatField & stats = m_map[key];
259  if (sp.measuresEta() && sp.measuresPhi()) {
260  ++stats.measEtaPhi;
261  } else {
262  stats.measEta += sp.measuresEta();
263  stats.measPhi += sp.measuresPhi();
264  }
265  }
266 }
267 void SpacePointMakerAlg::SpacePointStatistics::dumpStatisics(MsgStream& msg) const {
268  using KeyVal = std::pair<FieldKey, StatField>;
269  std::vector<KeyVal> sortedstats{};
270  sortedstats.reserve(m_map.size());
272  for (const auto & [key, stats] : m_map){
273  sortedstats.emplace_back(std::make_pair(key, stats));
274  }
275  std::stable_sort(sortedstats.begin(), sortedstats.end(), [](const KeyVal& a, const KeyVal&b) {
276  return a.second.allHits() > b.second.allHits();
277  });
278  msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
279  for (const auto & [key, stats] : sortedstats) {
281  <<" "<<Muon::MuonStationIndex::stName(key.stIdx)
282  <<" "<<std::abs(key.eta)<<(key.eta < 0 ? "A" : "C")
283  <<" "<<std::setw(8)<<stats.measEtaPhi
284  <<" "<<std::setw(8)<<stats.measEta
285  <<" "<<std::setw(8)<<stats.measPhi<<endmsg;
286  }
287  msg<<MSG::ALWAYS<<"###########################################################################"<<endmsg;
288 
289 }
290 
291 
293  if (m_statCounter) {
294  m_statCounter->dumpStatisics(msgStream());
295  }
296  return StatusCode::SUCCESS;
297 }
299  ATH_CHECK(m_geoCtxKey.initialize());
300  ATH_CHECK(m_mdtKey.initialize(!m_mdtKey.empty()));
301  ATH_CHECK(m_rpcKey.initialize(!m_rpcKey.empty()));
302  ATH_CHECK(m_tgcKey.initialize(!m_tgcKey.empty()));
303  ATH_CHECK(m_mmKey.initialize(!m_mmKey.empty()));
304  ATH_CHECK(m_stgcKey.initialize(!m_stgcKey.empty()));
305  ATH_CHECK(m_idHelperSvc.retrieve());
306  ATH_CHECK(m_writeKey.initialize());
307  if (m_doStat) m_statCounter = std::make_unique<SpacePointStatistics>(m_idHelperSvc.get());
308  return StatusCode::SUCCESS;
309 }
310 
311 template <>
312  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::TgcStrip*>& etaHits,
313  const std::vector<const xAOD::TgcStrip*>& phiHits) const {
314  if (etaHits.empty() || phiHits.empty()) {
315  return false;
316  }
317  const MuonGMR4::TgcReadoutElement* re = etaHits[0]->readoutElement();
318  ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
319  return ((1.*etaHits.size()) / ((1.*re->numChannels(etaHits[0]->measurementHash())))) < m_maxOccTgcEta &&
320  ((1.*phiHits.size()) / ((1.*re->numChannels(phiHits[0]->measurementHash())))) < m_maxOccTgcPhi;
321  }
322 template <>
323  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::RpcMeasurement*>& etaHits,
324  const std::vector<const xAOD::RpcMeasurement*>& phiHits) const {
325  if (etaHits.empty() || phiHits.empty()) {
326  return false;
327  }
328  const MuonGMR4::RpcReadoutElement* re = etaHits[0]->readoutElement();
329  ATH_MSG_VERBOSE("Collected "<<etaHits.size()<<"/"<<phiHits.size()<<" hits in "<<m_idHelperSvc->toStringGasGap(etaHits[0]->identify()));
330  return ((1.*etaHits.size()) / (1.*re->nEtaStrips())) < m_maxOccRpcEta &&
331  ((1.*phiHits.size()) / (1.*re->nPhiStrips())) < m_maxOccRpcPhi;
332  }
333 
334 template <>
335  bool SpacePointMakerAlg::passOccupancy2D(const std::vector<const xAOD::sTgcMeasurement*>& etaHits,
336  const std::vector<const xAOD::sTgcMeasurement*>& phiHits) const {
337  if (etaHits.empty() || phiHits.empty()) {
338  return false;
339  }
340  const MuonGMR4::sTgcReadoutElement* re = etaHits[0]->readoutElement();
341  return ((1.*etaHits.size()) / (1.*re->numChannels(etaHits[0]->measurementHash()))) < m_maxOccStgcEta &&
342  ((1.*phiHits.size()) / (1.*re->numChannels(phiHits[0]->measurementHash()))) < m_maxOccStgcPhi;
343  }
344 
345 template <class ContType>
346  StatusCode SpacePointMakerAlg::loadContainerAndSort(const EventContext& ctx,
349  const ContType* measurementCont{nullptr};
350  ATH_CHECK(SG::get(measurementCont, key, ctx));
351  if (!measurementCont || measurementCont->empty()){
352  ATH_MSG_DEBUG("nothing to do");
353  return StatusCode::SUCCESS;
354  }
355  const ActsGeometryContext* gctx{nullptr};
356  ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
357 
358  using PrdType = typename ContType::const_value_type;
359  using PrdVec = std::vector<PrdType>;
360  xAOD::ChamberViewer viewer{*measurementCont};
361  do {
362 
363  SpacePointsPerChamber& pointsInChamb = fillContainer[viewer.at(0)->readoutElement()->msSector()];
364  const Amg::Transform3D& sectorTrans = viewer.at(0)->readoutElement()->msSector()->globalToLocalTrans(*gctx);
365  ATH_MSG_DEBUG("Fill space points for chamber "<<m_idHelperSvc->toStringDetEl(viewer.at(0)->identify()));
366  if constexpr( std::is_same_v<ContType, xAOD::MdtDriftCircleContainer> ||
367  std::is_same_v<ContType, xAOD::MMClusterContainer>) {
368 
369  pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.capacity() + viewer.size());
370  for (const PrdType prd: viewer) {
371  ATH_MSG_VERBOSE("Create space point from "<<m_idHelperSvc->toString(prd->identify())
372  <<", hash: "<<prd->identifierHash());
373 
374  Amg::Transform3D toChamberTrans{ toChamberTransform(*gctx, sectorTrans,prd)};
375  fillSpacePoint(pointsInChamb.etaHits, prd, toChamberTrans);
376  }
377  } else {
379  using EtaPhiHits = std::array<PrdVec, 2>;
380  std::vector<EtaPhiHits> hitsPerGasGap{};
381  for (const PrdType prd : viewer) {
382  ATH_MSG_VERBOSE("Create space point from "<<m_idHelperSvc->toString(prd->identify())<<", hash: "<<prd->identifierHash());
383 
384  unsigned int gapIdx = prd->gasGap() -1;
385  if constexpr (std::is_same_v<ContType, xAOD::RpcMeasurementContainer>) {
386  gapIdx = prd->readoutElement()->createHash(0, prd->gasGap(), prd->doubletPhi(), false);
387  }
388 
389  bool measPhi{false};
390  if constexpr(std::is_same_v<ContType, xAOD::sTgcMeasContainer>) {
392  if (prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
393  Amg::Transform3D toChamberTrans{ toChamberTransform(*gctx, sectorTrans, prd)};
394  fillSpacePoint(pointsInChamb.etaHits, prd, toChamberTrans);
395  continue;
396  }
398  measPhi = prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
399  } else {
401  measPhi = prd->measuresPhi();
402  }
403 
404  if (hitsPerGasGap.size() <= gapIdx) {
405  hitsPerGasGap.resize(gapIdx + 1);
406  }
408  PrdVec& toPush = hitsPerGasGap[gapIdx][measPhi];
409  if (toPush.capacity() == toPush.size()) {
410  toPush.reserve(toPush.size() + m_capacityBucket);
411  }
412  toPush.push_back(prd);
413  }
415  for (auto& [etaHits, phiHits] : hitsPerGasGap) {
416 
417  Amg::Transform3D toChamberTrans_eta {}, toChamberTrans_phi {};
418  if (!etaHits.empty()){
419  toChamberTrans_eta = toChamberTransform(*gctx, sectorTrans, etaHits.at(0));
420  }
421  if (!phiHits.empty()){
422  toChamberTrans_phi = toChamberTransform(*gctx, sectorTrans, phiHits.at(0));
423  }
424 
425  if (!passOccupancy2D(etaHits, phiHits)) {
426  ATH_MSG_VERBOSE("Occupancy cut not passed "<<etaHits.size()<<", "<<phiHits.size());
427  pointsInChamb.etaHits.reserve(pointsInChamb.etaHits.size() + etaHits.size());
428  pointsInChamb.phiHits.reserve(pointsInChamb.phiHits.size() + phiHits.size());
429  for (const PrdType etaPrd : etaHits) {
430 
431  fillSpacePoint(pointsInChamb.etaHits, etaPrd, toChamberTrans_eta);
432  ATH_MSG_VERBOSE("Add new eta hit "<<m_idHelperSvc->toString(pointsInChamb.etaHits.back().identify())
433  <<" "<<Amg::toString(pointsInChamb.etaHits.back().positionInChamber()));
434 
435  }
436  for (const PrdType phiPrd : phiHits) {
437  fillSpacePoint(pointsInChamb.phiHits, phiPrd, toChamberTrans_phi);
438  ATH_MSG_VERBOSE("Add new phi hit "<<m_idHelperSvc->toString(pointsInChamb.phiHits.back().identify())
439  <<" "<<Amg::toString(pointsInChamb.phiHits.back().positionInChamber()));
440  }
441  continue;
442  }
443  std::vector<std::shared_ptr<unsigned>> etaCounts{matchCountVec(etaHits.size())},
444  phiCounts{matchCountVec(phiHits.size())};
445  pointsInChamb.etaHits.reserve(etaHits.size()*phiHits.size());
447  for (unsigned int etaP = 0; etaP < etaHits.size(); ++etaP) {
449  for (unsigned int phiP = 0; phiP < phiHits.size(); ++ phiP) {
452  if (!(etaHits[etaP]->bcBitMap() & phiHits[phiP]->bcBitMap())){
453  continue;
454  }
455  }
456  fillSpacePoint(pointsInChamb.etaHits, etaHits[etaP], phiHits[phiP], toChamberTrans_eta, toChamberTrans_phi);
457 
458  SpacePoint& sp {pointsInChamb.etaHits.back()};
459  ATH_MSG_VERBOSE("Create new spacepoint from "<<m_idHelperSvc->toString(etaHits[etaP]->identify())
460  <<" & "<<m_idHelperSvc->toString(phiHits[phiP]->identify())<<" at "<<Amg::toString(sp.positionInChamber()));
461  sp.setInstanceCounts(etaCounts[etaP], phiCounts[phiP]);
462  }
463  if (!(*etaCounts[etaP])) {
464  fillSpacePoint(pointsInChamb.etaHits, etaHits[etaP], toChamberTrans_eta);
465  continue;
466  }
467  }
470  for (unsigned int phiP = 0; phiP < phiHits.size(); ++ phiP){
471  if (!(*phiCounts[phiP])) {
472  fillSpacePoint(pointsInChamb.phiHits, phiHits[phiP], toChamberTrans_phi);
473  }
474  }
475  }
476  }
477  } while (viewer.next());
478  return StatusCode::SUCCESS;
479 }
480 
481 
482 StatusCode SpacePointMakerAlg::execute(const EventContext& ctx) const {
483  PreSortedSpacePointMap preSortedContainer{};
484  ATH_CHECK(loadContainerAndSort(ctx, m_mdtKey, preSortedContainer));
485  ATH_CHECK(loadContainerAndSort(ctx, m_rpcKey, preSortedContainer));
486  ATH_CHECK(loadContainerAndSort(ctx, m_tgcKey, preSortedContainer));
487  ATH_CHECK(loadContainerAndSort(ctx, m_mmKey, preSortedContainer));
488  ATH_CHECK(loadContainerAndSort(ctx, m_stgcKey, preSortedContainer));
489  std::unique_ptr<SpacePointContainer> outContainer = std::make_unique<SpacePointContainer>();
490 
491  for (auto &[chamber, hitsPerChamber] : preSortedContainer){
492  ATH_MSG_DEBUG("Fill space points for chamber "<<chamber->identString());
493  distributePointsAndStore(std::move(hitsPerChamber), *outContainer);
494  }
495  SG::WriteHandle<SpacePointContainer> writeHandle{m_writeKey, ctx};
496  ATH_CHECK(writeHandle.record(std::move(outContainer)));
497  return StatusCode::SUCCESS;
498 }
499 
500 void SpacePointMakerAlg::distributePointsAndStore(SpacePointsPerChamber&& hitsPerChamber,
501  SpacePointContainer& finalContainer) const {
502  SpacePointBucketVec splittedHits{};
503  splittedHits.emplace_back();
504  if (m_statCounter){
505  m_statCounter->addToStat(hitsPerChamber.etaHits);
506  m_statCounter->addToStat(hitsPerChamber.phiHits);
507 
508  }
509  distributePrimaryPoints(std::move(hitsPerChamber.etaHits), splittedHits);
510  splittedHits.erase(std::remove_if(splittedHits.begin(), splittedHits.end(),
511  [](const SpacePointBucket& bucket) {
512  return bucket.size() <= 1;
513  }), splittedHits.end());
514  distributePhiPoints(std::move(hitsPerChamber.phiHits), splittedHits);
515 
516  for (SpacePointBucket& bucket : splittedHits) {
517 
518  std::ranges::sort(bucket, MuonR4::SpacePointPerLayerSorter{});
519 
520  if (msgLvl(MSG::VERBOSE)){
521  std::stringstream spStr{};
522  for (const std::shared_ptr<SpacePoint>& sp : bucket){
523  spStr<<"SpacePoint: PrimaryMeas: " << m_idHelperSvc->toString(sp->identify()) << " SecondaryMeas: "
524  <<(sp->secondaryMeasurement() ? m_idHelperSvc->toString(xAOD::identify(sp->secondaryMeasurement())) : " None ")
525  << " Pos: " << Amg::toString(sp->positionInChamber())<<std::endl;
526  }
527  ATH_MSG_VERBOSE("Created a bucket, printing all spacepoints..."<<std::endl<<spStr.str());
528  }
529 
530  bucket.populateChamberLocations();
531  finalContainer.push_back(std::make_unique<SpacePointBucket>(std::move(bucket)));
532  }
533 
534 }
535 void SpacePointMakerAlg::distributePhiPoints(std::vector<SpacePoint>&& spacePoints,
536  SpacePointBucketVec& splittedContainer) const{
537  for (SpacePoint& sp : spacePoints) {
538  auto phiPoint = std::make_shared<SpacePoint>(std::move(sp));
539  const double minY = phiPoint->positionInChamber().y() - phiPoint->uncertainty().y();
540  const double maxY = phiPoint->positionInChamber().y() + phiPoint->uncertainty().y();
541  for (SpacePointBucket& bucket : splittedContainer){
544  if (! (maxY < bucket.coveredMin() || bucket.coveredMax() < minY) ) {
545  bucket.emplace_back(phiPoint);
546  }
547  }
548  }
549 }
550 bool SpacePointMakerAlg::splitBucket(const SpacePoint& spacePoint,
551  const double firstSpPos,
552  const SpacePointBucketVec& sortedPoints) const {
554  const double spY = spacePoint.positionInChamber().y();
555  if (spY - firstSpPos > m_maxBucketLength){
556  return true;
557  }
558 
559  if (sortedPoints.empty() || sortedPoints.back().empty()) {
560  return false;
561  }
562  return spY - sortedPoints.back().back()->positionInChamber().y() > m_spacePointWindow;
563 }
564 void SpacePointMakerAlg::newBucket(const SpacePoint& refSpacePoint,
565  SpacePointBucketVec& sortedPoints) const {
566  SpacePointBucket& newContainer = sortedPoints.emplace_back();
567  newContainer.setBucketId(sortedPoints.size() -1);
568 
570  SpacePointBucket& overlap{sortedPoints[sortedPoints.size() - 2]};
571  overlap.setCoveredRange(overlap.front()->positionInChamber().y(),
572  overlap.back()->positionInChamber().y());
573 
574  const double refBound = refSpacePoint.positionInChamber().y();
575 
577  for (const std::shared_ptr<SpacePoint>& pointInBucket : overlap | std::views::reverse) {
578  const double overlapPos = pointInBucket->positionInChamber().y() + pointInBucket->uncertainty()[Amg::y];
579  if (refBound - overlapPos < m_spacePointOverlap) {
580  newContainer.insert(newContainer.begin(), pointInBucket);
581  } else {
582  break;
583  }
584  }
585 
586 }
587 
588 void SpacePointMakerAlg::distributePrimaryPoints(std::vector<SpacePoint>&& spacePoints,
589  SpacePointBucketVec& splittedHits) const {
590 
591  if (spacePoints.empty()) return;
592 
594  std::ranges::sort(spacePoints,
595  [] (const SpacePoint& a, const SpacePoint& b) {
596  return a.positionInChamber().y() < b.positionInChamber().y();
597  });
598 
599  double firstPointPos = spacePoints.front().positionInChamber().y();
600 
601  for (SpacePoint& toSort : spacePoints) {
602  ATH_MSG_VERBOSE("Add new primary space point "<<m_idHelperSvc->toString(toSort.identify())<<", "
603  <<" @ "<<Amg::toString(toSort.positionInChamber()));
604 
605  if (splitBucket(toSort, firstPointPos, splittedHits)){
606  newBucket(toSort, splittedHits);
607  firstPointPos = splittedHits.back().empty() ? toSort.positionInChamber().y() : splittedHits.back().front()->positionInChamber().y();
608  ATH_MSG_VERBOSE("New bucket: id " << splittedHits.back().bucketId() << " Coverage: " << firstPointPos);
609  }
610  std::shared_ptr<SpacePoint> spacePoint = std::make_shared<SpacePoint>(std::move(toSort));
611  splittedHits.back().emplace_back(spacePoint);
612  }
613  SpacePointBucket& lastBucket{splittedHits.back()};
614  lastBucket.setCoveredRange(lastBucket.front()->positionInChamber().y(),
615  lastBucket.back()->positionInChamber().y());
616 }
617 
618 }
UncalibratedMeasurement.h
xAOD::identify
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.
Definition: MuonSpectrometer/MuonPhaseII/Event/xAOD/xAODMuonPrepData/Root/UtilFunctions.cxx:82
MuonR4::SpacePointMakerAlg::PreSortedSpacePointMap
std::unordered_map< const MuonGMR4::SpectrometerSector *, SpacePointsPerChamber > PreSortedSpacePointMap
Container abrivation of the presorted space point container per MuonChambers.
Definition: SpacePointMakerAlg.h:153
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::operator<
bool operator<(const FieldKey &other) const
python.tests.PyTestsLib.finalize
def finalize(self)
_info( "content of StoreGate..." ) self.sg.dump()
Definition: PyTestsLib.py:50
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
initialize
void initialize()
Definition: run_EoverP.cxx:894
Muon::MuonStationIndex::stName
const std::string & stName(StIndex index)
convert StIndex into a string
Definition: MuonStationIndex.cxx:104
Amg::y
@ y
Definition: GeoPrimitives.h:35
xAOD::UncalibratedMeasurement
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
Definition: UncalibratedMeasurement.h:13
MuonR4::SpacePointBucket::populateChamberLocations
void populateChamberLocations()
populate the chamber location list.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePointContainer.cxx:23
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:138
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:148
athena.value
value
Definition: athena.py:124
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
MuonR4::SpacePointMakerAlg::SpacePointStatistics::StatField::allHits
unsigned int allHits() const
Helper method returning the sum of the three space point type counts.
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
SG::ReadHandleKey
Property holding a SG store/key/clid from which a ReadHandle is made.
Definition: StoreGate/StoreGate/ReadHandleKey.h:39
xAOD::RpcStrip_v1
Definition: RpcStrip_v1.h:11
trigbs_dumpHLTContentInBS.stats
stats
Definition: trigbs_dumpHLTContentInBS.py:91
MuonGMR4::RpcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:17
RpcStrip.h
SpacePoint
Definition: Trigger/TrigAccel/TrigCudaFitter/src/SpacePoint.h:7
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
LArG4FSStartPointFilterLegacy.execute
execute
Definition: LArG4FSStartPointFilterLegacy.py:20
GeoPrimitives.h
xAOD::ChamberViewer
Definition: ChamberViewer.h:59
WriteHandle.h
Handle class for recording to StoreGate.
MuonR4::SpacePointMakerAlg::SpacePointBucketVec
std::vector< SpacePointBucket > SpacePointBucketVec
Abrivation of a MuonSapcePoint bucket vector.
Definition: SpacePointMakerAlg.h:171
MuonR4::SpacePointMakerAlg::SpacePointsPerChamber
: Helper struct to collect the space point per muon chamber, which are later sorted into the space po...
Definition: SpacePointMakerAlg.h:145
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
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
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:729
MuonR4::SpacePointMakerAlg::SpacePointStatistics::StatField
Helper struct to count the space-points in each detector category.
Definition: SpacePointMakerAlg.h:117
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
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:150
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonR4::SpacePointMakerAlg::positionInChamber
Amg::Vector3D positionInChamber(const MeasType *meas, const Amg::Transform3D &toChamberTrans) const
Returns the position of the uncalibrated muon measurement in the sector frame.
Definition: SpacePointMakerAlg.cxx:48
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
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
beamspotman.dir
string dir
Definition: beamspotman.py:621
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:19
MuonR4::SpacePointMakerAlg::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: SpacePointMakerAlg.h:238
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
Amg
Definition of ATLAS Math & Geometry primitives (Amg)
Definition: AmgStringHelpers.h:19
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::techIdx
TechIdx_t techIdx
Definition: SpacePointMakerAlg.h:133
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::stIdx
StIdx_t stIdx
Definition: SpacePointMakerAlg.h:132
MuonR4::SpacePointMakerAlg::channelDirInChamber
Amg::Vector3D channelDirInChamber(const MeasType *meas, const Amg::Transform3D &toChamberTrans) const
Returns the direction of the measurement channel in the sector frame.
Definition: SpacePointMakerAlg.cxx:75
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
MuonR4::SpacePointMakerAlg::channelNormalInChamber
Amg::Vector3D channelNormalInChamber(const MeasType *meas, const Amg::Transform3D &toChamberTrans) const
Returns the direction, in the sector frame, of the precision axis of the measurement,...
Definition: SpacePointMakerAlg.cxx:98
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
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
MuonGMR4::sTgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/sTgcReadoutElement.h:20
MuonR4
This header ties the generic definitions in this package.
Definition: HoughEventData.h:16
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
MuonR4::SpacePoint::positionInChamber
const Amg::Vector3D & positionInChamber() const
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:59
MuonR4::SpacePointMakerAlg::SpacePointStatistics::SpacePointStatistics
SpacePointStatistics(const Muon::IMuonIdHelperSvc *idHelperSvc)
Standard constructor.
a
TList * a
Definition: liststreamerinfos.cxx:10
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
y
#define y
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
unit
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
Definition: AmgMatrixBasePlugin.h:21
re
const boost::regex re(r_e)
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
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
ReadHandle.h
Handle class for reading from StoreGate.
SpacePointMakerAlg.h
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
MuonR4::SpacePointMakerAlg::fillSpacePoint
void fillSpacePoint(std::vector< SpacePoint > &pointColl, const MeasType *primaryMeas, const MeasType *secondaryMeas, const Amg::Transform3D &toChamberTrans_eta, const Amg::Transform3D &toChamberTrans_phi) const
Helper function that creates the spacepoint and populates it, when having two measurement.
MuonGMR4::RadialStripDesign
Definition: RadialStripDesign.h:23
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey::eta
int eta
Definition: SpacePointMakerAlg.h:134
MuonR4::AmgSymMatrix
const AmgSymMatrix(2) &SpacePoint
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:90
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
SpacePointPerLayerSorter.h
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:19
MuonR4::SpacePointMakerAlg::toChamberTransform
Amg::Transform3D toChamberTransform(const ActsGeometryContext &gctx, const Amg::Transform3D &sectorTrans, const MeasType *meas) const
Returns the transform from the attached Muon chamber frame to the sector frame.
Definition: SpacePointMakerAlg.cxx:34
MuonR4::SpacePointMakerAlg::SpacePointStatistics::FieldKey
Helper struct to define the counting categories.
Definition: SpacePointMakerAlg.h:129
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
MuonR4::SpacePointMakerAlg
Definition: SpacePointMakerAlg.h:27
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37