ATLAS Offline Software
MuonPhiHoughTransformAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
9 
11 
12 using namespace MuonR4;
13 
15  ISvcLocator* pSvcLocator)
16  : AthReentrantAlgorithm(name, pSvcLocator) {}
17 
22 
23  return StatusCode::SUCCESS;
24 }
25 
26 template <class ContainerType>
28  const EventContext& ctx, const SG::ReadHandleKey<ContainerType>& key,
29  const ContainerType*& contToPush) const {
30  contToPush = nullptr;
31  if (key.empty()) {
32  ATH_MSG_VERBOSE("No key has been parsed for object "
33  << typeid(ContainerType).name());
34  return StatusCode::SUCCESS;
35  }
36  SG::ReadHandle<ContainerType> readHandle{key, ctx};
37  ATH_CHECK(readHandle.isPresent());
38  contToPush = readHandle.cptr();
39  return StatusCode::SUCCESS;
40 }
41 
43  MuonHoughEventData& data) const {
44  HoughPlaneConfig cfg;
45  cfg.nBinsX = m_nBinsTanPhi;
46  cfg.nBinsY = m_nBinsIntercept;
47  // configure the peak finder for the phi-extension.
48  // Expect "shallow" maxima with 2-3 hits.
49  ActsPeakFinderForMuonCfg peakFinderCfg;
50  peakFinderCfg.fractionCutoff = 0.4;
51  peakFinderCfg.threshold = 2; // 2D spacepoints receive a weight of 2
52  peakFinderCfg.minSpacingBetweenPeaks = {0., 30.};
53  data.houghPlane = std::make_unique<HoughPlane>(cfg);
54  data.peakFinder = std::make_unique<ActsPeakFinderForMuon>(peakFinderCfg);
55 
56  return StatusCode::SUCCESS;
57 }
58 
60  const MuonR4::ActsPeakFinderForMuon::Maximum& phiMaximum,
61  const MuonR4::HoughMaximum& etaMaximum) const {
62  std::unordered_map<const xAOD::UncalibratedMeasurement*, bool> foundEtas;
63  // loop over the original eta maximum and check all hits measuring the eta-coordinate
64  for (auto& hit : etaMaximum.getHitsInMax()) {
65  if (hit->measuresEta() && hit->measuresPhi()) {
66  auto [iter, added] =
67  foundEtas.emplace(hit->primaryMeasurement(), false);
68  // test if the PRD for the eta-measurement appears on at least
69  // one space point of this phi extension.
70  // This will be done for all space points containing the eta-PRD
71  iter->second |= phiMaximum.hitIdentifiers.count(hit);
72  }
73  }
74  // count the number of eta PRD not compatible with this extension.
75  return std::count_if(
76  foundEtas.begin(), foundEtas.end(),
77  [](const std::pair<const xAOD::UncalibratedMeasurement*, bool>& p) {
78  return !p.second;
79  });
80 }
82  const HoughMaximum & etaMax,
83  const MuonR4::ActsPeakFinderForMuon::Maximum & phiMax) const {
84  // book a new hit list
85  std::vector<MuonR4::HoughHitType> hitsOnMax;
86  // copy the pure eta hits onto the hit list
87  std::copy_if(etaMax.getHitsInMax().begin(), etaMax.getHitsInMax().end(), std::back_inserter(hitsOnMax), [](const HoughHitType &hit){
88  return (hit->measuresEta() && !hit->measuresPhi());
89  });
90  // and then add all hits (2D and pure phi) from the phi-extension to it
91  hitsOnMax.insert(hitsOnMax.end(), phiMax.hitIdentifiers.begin(), phiMax.hitIdentifiers.end());
92  // use this to construct the segment seed
93  return HoughSegmentSeed( etaMax.tanTheta(), etaMax.interceptY(), phiMax.x, phiMax.y, hitsOnMax.size(), std::move(hitsOnMax));
94 }
95 
97  // reset the event data
98  eventData.phiHitsOnMax = 0;
99  eventData.searchSpaceTanAngle = std::make_pair(1e10, -1e10);
100  eventData.searchSpaceIntercept = std::make_pair(1e10, -1e10);
101  // loop over the measurements on the maximum
102  for (auto hit : maximum.getHitsInMax()) {
103  // reject the pure eta measurements - not relevant here
104  if (!hit->measuresPhi())
105  continue;
106  // find the direction of the IP viewed from the chamber frame
107  Amg::Vector3D extrapDir = (hit->positionInChamber() - hit->muonChamber()->globalToLocalTrans(eventData.gctx).translation()).unit();
108  // express the x location of our phi hits on the chamber plane (z = 0) when projecting from the beam spot
109  std::optional<double> dummyIntercept = Amg::intersect<3>(hit->positionInChamber(),extrapDir,Amg::Vector3D::UnitZ(),0);
110  double x0 = (hit->positionInChamber() + dummyIntercept.value_or(0) * extrapDir).x();
111  // now we can obtain the most likely tan(phi) via the pointing vector from the origin to our hit
112  double tanPhi = extrapDir.x()/extrapDir.z();
113  // update our search space with this info
116  // and increment the hit counter
117  ++ eventData.phiHitsOnMax;
118  }
119  // now use the results from the individual hits to define an axis range adapted to the binning we desire
120  double chamberCenter = (eventData.searchSpaceIntercept.second + eventData.searchSpaceIntercept.first) * 0.5;
121  double searchStart = chamberCenter - 0.5 * eventData.houghPlane->nBinsY() * m_targetResoIntercept;
122  double searchEnd = chamberCenter + 0.5 * eventData.houghPlane->nBinsY() * m_targetResoIntercept;
123  // Protection for very wide buckets - if the search space does not cover all of the bucket, widen the bin size
124  // so that we cover everything
125  searchStart = std::min(searchStart, eventData.searchSpaceIntercept.first- m_minSigmasSearchIntercept * m_targetResoIntercept);
126  searchEnd = std::max(searchEnd, eventData.searchSpaceIntercept.second + m_minSigmasSearchIntercept * m_targetResoIntercept);
127  // also treat tan(phi)
128  double tanPhiMean = 0.5 * (eventData.searchSpaceTanAngle.first + eventData.searchSpaceTanAngle.second);
129  double searchStartTanPhi = tanPhiMean - 0.5 * eventData.houghPlane->nBinsX() * m_targetResoTanPhi;
130  double searchEndTanPhi = tanPhiMean + 0.5* eventData.houghPlane->nBinsX() * m_targetResoTanPhi;
131  searchStartTanPhi = std::min(searchStartTanPhi, eventData.searchSpaceTanAngle.first- m_minSigmasSearchTanPhi * m_targetResoTanPhi);
132  searchEndTanPhi = std::max(searchEndTanPhi, eventData.searchSpaceTanAngle.second + m_minSigmasSearchTanPhi * m_targetResoTanPhi);
133 
134  // and update the axis ranges for the search space according to our results
135  eventData.currAxisRanges =
136  Acts::HoughTransformUtils::HoughAxisRanges{searchStartTanPhi, searchEndTanPhi, searchStart, searchEnd};
137 
138  return StatusCode::SUCCESS;
139 }
140 
141 std::vector<MuonR4::ActsPeakFinderForMuon::Maximum> MuonPhiHoughTransformAlg::findRankedSegmentSeeds (MuonHoughEventData & eventData, const MuonR4::HoughMaximum & maximum) const{
142  std::map<int, std::vector<MuonR4::ActsPeakFinderForMuon::Maximum>> rankedSeeds;
143  // reset the accumulator
144  eventData.houghPlane->reset();
145  // fill the accumulator with the phi measurements
146  for (auto hit : maximum.getHitsInMax()){
147  if (!hit->measuresPhi())
148  continue;
149  eventData.houghPlane->fill<HoughHitType>(
150  hit, eventData.currAxisRanges,
153  // up-weigh 2D spacepoints w.r.t 1D phi hits to prevent
154  // discarding measurements known to be compatible in eta
155  (hit->measuresEta() ? 2.0 : 1.0)
156  );
157  }
158  // run the peak finder
159  auto foundMaxPhi = eventData.peakFinder->findPeaks(
160  *(eventData.houghPlane), eventData.currAxisRanges);
161  // now rank the found peaks by the number of eta-compatible PRDs they would discard.
162  for (auto solution : foundMaxPhi) {
163  // for each solution, count how many eta PRDs would not be compatible with this phi extension.
164  // rank by the lowest number of such "holes".
165  rankedSeeds[countIncompatibleEtaHits(solution, maximum)].push_back(solution);
166  }
167  // return only the best solution(s)
168  auto best = rankedSeeds.begin();
169  // and apply the maximum hole cut.
170  if (best != rankedSeeds.end() && best->first <= m_maxEtaHolesOnMax){
171  return best->second;
172  }
173  return {};
174 }
176  // recovers cases of a single phi hit assuming a straight
177  // line extrapolation from the beam line to the phi measurement
178  return HoughSegmentSeed(maximum.tanTheta(), maximum.interceptY(),
179  data.searchSpaceTanAngle.first,
180  data.searchSpaceIntercept.first,
181  maximum.getCounts(),
182  std::vector<HoughHitType>(maximum.getHitsInMax()));
183 
184 }
185 
186 
187 StatusCode MuonPhiHoughTransformAlg::execute(const EventContext& ctx) const {
188 
189  // read the inputs
190  const StationHoughMaxContainer* maxima{nullptr};
191  ATH_CHECK(retrieveContainer(ctx, m_maxima, maxima));
192 
193  const ActsGeometryContext* gctx{nullptr};
195 
196  // book the event data object
197  MuonHoughEventData eventData(*gctx);
198 
199  // prepare the accumulator
200  ATH_CHECK(prepareHoughPlane(eventData));
201 
202  // prepare our output collection
204  m_segmentSeeds, ctx);
205  ATH_CHECK(writeMaxima.record(
206  std::make_unique<StationHoughSegmentSeedContainer>()));
207 
208  // loop over the previously found eta-maxima for each station
209  for (auto& stationAndMax : *maxima) {
210  std::vector<MuonR4::HoughSegmentSeed> segmentSeedsInStation;
211  for (auto& max : stationAndMax.getMaxima()) {
212  // for each maximum, pre-process
213  ATH_CHECK(preProcessMaximum(eventData,max));
214  bool foundSolution=false;
215  // if we have enough hits, run a phi transform
216  if (eventData.phiHitsOnMax > 1){
217  std::vector<MuonR4::ActsPeakFinderForMuon::Maximum> rankedSeeds = findRankedSegmentSeeds(eventData, max);
218  for (auto & phiSolution : rankedSeeds){
219  foundSolution = true;
220  segmentSeedsInStation.push_back(buildSegmentSeed(max, phiSolution));
221  }
222  }
223  // if we do not have at least two phi-hits for a proper transform:
224  if (!foundSolution){
225  // if we have a single phi hit, we can approximate the phi
226  // solution using the beam spot (as the IP is far).
227  // This is steered by a flag, and not appropriate for splashes
228  // or cosmics.
229  if (m_recoverSinglePhiWithBS && eventData.phiHitsOnMax == 1){
230  segmentSeedsInStation.push_back(recoverSinglePhiMax(eventData,max));
231  }
232  // otherwise we have no phi-solution, and we fall back to writing a 1D eta-maximum
233  else{
234  segmentSeedsInStation.push_back(HoughSegmentSeed(max));
235  }
236  }
237  }
238  // add the maxima for this station to the output
239  writeMaxima->emplace(StationHoughSegmentSeeds(stationAndMax.chamber(),
240  segmentSeedsInStation));
241 
242  }
243  return StatusCode::SUCCESS;
244 }
MuonR4::MuonPhiHoughTransformAlg::findRankedSegmentSeeds
std::vector< MuonR4::ActsPeakFinderForMuon::Maximum > findRankedSegmentSeeds(MuonHoughEventData &data, const MuonR4::HoughMaximum &maximum) const
perform a hough search for the most promising phi extension of an eta-maximum Performs a local hough ...
Definition: MuonPhiHoughTransformAlg.cxx:141
MuonR4::MuonPhiHoughTransformAlg::preProcessMaximum
StatusCode preProcessMaximum(MuonHoughEventData &data, const MuonR4::HoughMaximum &maximum) const
pre-processing for a given input eta-maximum Counts potential phi-hits and defines the search space
Definition: MuonPhiHoughTransformAlg.cxx:96
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
MuonR4::MuonPhiHoughTransformAlg::m_targetResoIntercept
DoubleProperty m_targetResoIntercept
Definition: MuonPhiHoughTransformAlg.h:104
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
max
#define max(a, b)
Definition: cfImp.cxx:41
MuonPhiHoughTransformAlg.h
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
MuonR4::HoughHitType
std::shared_ptr< MuonR4::MuonSpacePoint > HoughHitType
Definition: MuonHoughDefs.h:20
MuonR4::StationHoughMaxContainer
std::set< StationHoughMaxima > StationHoughMaxContainer
Definition: StationHoughMaxContainer.h:12
MuonR4::HoughMaximum_impl::tanTheta
double tanTheta() const
getter
Definition: HoughMaximum.h:31
MuonR4::HoughMaximum_impl::interceptY
double interceptY() const
getter
Definition: HoughMaximum.h:35
MuonR4::MuonPhiHoughTransformAlg::m_nBinsIntercept
IntegerProperty m_nBinsIntercept
Definition: MuonPhiHoughTransformAlg.h:116
MuonR4::HoughSegmentSeed
HoughSegmentSeed_impl< HoughHitType > HoughSegmentSeed
Definition: MuonHoughDefs.h:24
HoughHelperFunctions.h
MuonR4::MuonPhiHoughTransformAlg::buildSegmentSeed
MuonR4::HoughSegmentSeed buildSegmentSeed(const HoughMaximum &etaMax, const MuonR4::ActsPeakFinderForMuon::Maximum &phiMax) const
constructs a segment seed from an eta maximum and a phi-extension.
Definition: MuonPhiHoughTransformAlg.cxx:81
xAOD::etaMax
etaMax
Definition: HIEventShape_v2.cxx:46
MuonR4::HoughHelpers::Phi::houghParamStrip
double houghParamStrip(double tanPhi, const MuonR4::HoughHitType &dc)
straight line parametrisation for strip detector measurements, in the x-direction
Definition: HoughHelperFunctions.cxx:31
MuonR4::MuonPhiHoughTransformAlg::m_segmentSeeds
SG::WriteHandleKey< StationHoughSegmentSeedContainer > m_segmentSeeds
Definition: MuonPhiHoughTransformAlg.h:96
MuonR4::MuonHoughEventData_impl::currAxisRanges
Acts::HoughTransformUtils::HoughAxisRanges currAxisRanges
Definition: MuonHoughEventData.h:66
MuonR4::ActsPeakFinderForMuonCfg
Acts::HoughTransformUtils::PeakFinders::IslandsAroundMaxConfig ActsPeakFinderForMuonCfg
Definition: MuonHoughDefs.h:33
MuonR4::StationHoughSegmentSeeds
StationHoughResults< HoughSegmentSeed > StationHoughSegmentSeeds
Definition: StationHoughMaxima.h:56
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::ReadHandleKey< ContainerType >
x
#define x
MuonR4::MuonPhiHoughTransformAlg::m_recoverSinglePhiWithBS
BooleanProperty m_recoverSinglePhiWithBS
Definition: MuonPhiHoughTransformAlg.h:122
ReadCondHandle.h
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
MuonR4::updateSearchWindow
void updateSearchWindow(std::pair< double, double > &searchWindow, double value)
Updates a search space window to account for a value.
Definition: MuonHoughEventData.h:23
MuonR4::MuonPhiHoughTransformAlg::m_geoCtxKey
SG::ReadHandleKey< ActsGeometryContext > m_geoCtxKey
Definition: MuonPhiHoughTransformAlg.h:99
MuonR4::MuonPhiHoughTransformAlg::initialize
virtual StatusCode initialize() override
Definition: MuonPhiHoughTransformAlg.cxx:18
MuonR4::MuonHoughEventData_impl::peakFinder
std::unique_ptr< peakFinder_t > peakFinder
Definition: MuonHoughEventData.h:42
MuonR4::MuonPhiHoughTransformAlg::m_minSigmasSearchTanPhi
DoubleProperty m_minSigmasSearchTanPhi
Definition: MuonPhiHoughTransformAlg.h:107
MuonR4::MuonHoughEventData_impl::searchSpaceTanAngle
std::pair< double, double > searchSpaceTanAngle
Definition: MuonHoughEventData.h:70
MuonR4::MuonHoughEventData_impl
Templated event data class for the phase-2 muon hough transform.
Definition: MuonHoughEventData.h:34
MuonR4::MuonPhiHoughTransformAlg::retrieveContainer
StatusCode retrieveContainer(const EventContext &ctx, const SG::ReadHandleKey< ContainerType > &key, const ContainerType *&contToPush) const
Helper method to fetch data from StoreGate.
Definition: MuonPhiHoughTransformAlg.cxx:27
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
MuonR4::MuonHoughEventData_impl::searchSpaceIntercept
std::pair< double, double > searchSpaceIntercept
Definition: MuonHoughEventData.h:68
MuonChamber.h
python.utils.best
def best(iterable, priorities=[3, 2, 1, -1, 0])
Definition: DataQuality/DQUtils/python/utils.py:50
AnalysisUtils::copy_if
Out copy_if(In first, const In &last, Out res, const Pred &p)
Definition: IFilterUtils.h:30
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
MuonR4::MuonHoughEventData_impl::houghPlane
std::unique_ptr< houghPlane_t > houghPlane
Definition: MuonHoughEventData.h:40
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
min
#define min(a, b)
Definition: cfImp.cxx:40
MuonR4::MuonHoughEventData_impl::gctx
const ActsGeometryContext & gctx
Definition: MuonHoughEventData.h:38
MuonR4::HoughMaximum_impl::getCounts
double getCounts() const
getter
Definition: HoughMaximum.h:38
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
WriteCaloSwCorrections.cfg
cfg
Definition: WriteCaloSwCorrections.py:23
MuonR4::MuonPhiHoughTransformAlg::recoverSinglePhiMax
HoughSegmentSeed recoverSinglePhiMax(MuonHoughEventData &data, const MuonR4::HoughMaximum &maximum) const
extend an eta maximum with just a single attached phi measurement.
Definition: MuonPhiHoughTransformAlg.cxx:175
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonR4::MuonPhiHoughTransformAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override
Definition: MuonPhiHoughTransformAlg.cxx:187
MuonR4::MuonPhiHoughTransformAlg::prepareHoughPlane
StatusCode prepareHoughPlane(MuonHoughEventData &data) const
prepare the hough plane once per event.
Definition: MuonPhiHoughTransformAlg.cxx:42
MuonR4::HoughHelpers::Phi::houghWidthStrip
double houghWidthStrip(double tanPhi, const MuonR4::HoughHitType &dc)
Uncertainty parametrisation for strip measurements.
Definition: HoughHelperFunctions.cxx:34
MuonR4
The CsvMuonSimHitDumper reads a Simulation Hit container for muons and dumps information to csv files...
Definition: MuonSpacePoint.h:11
MuonR4::MuonPhiHoughTransformAlg::m_minSigmasSearchIntercept
DoubleProperty m_minSigmasSearchIntercept
Definition: MuonPhiHoughTransformAlg.h:110
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
MuonR4::HoughMaximum_impl
Data class to represent an eta maximum in hough space.
Definition: HoughMaximum.h:16
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
MuonR4::MuonPhiHoughTransformAlg::m_nBinsTanPhi
IntegerProperty m_nBinsTanPhi
Definition: MuonPhiHoughTransformAlg.h:114
unit
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
Definition: AmgMatrixBasePlugin.h:20
MuonR4::MuonPhiHoughTransformAlg::m_targetResoTanPhi
DoubleProperty m_targetResoTanPhi
Definition: MuonPhiHoughTransformAlg.h:102
MuonR4::MuonPhiHoughTransformAlg::MuonPhiHoughTransformAlg
MuonPhiHoughTransformAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: MuonPhiHoughTransformAlg.cxx:14
MuonR4::HoughMaximum_impl::getHitsInMax
const std::vector< HitType > & getHitsInMax() const
getter
Definition: HoughMaximum.h:41
MuonR4::MuonPhiHoughTransformAlg::m_maxima
SG::ReadHandleKey< StationHoughMaxContainer > m_maxima
Definition: MuonPhiHoughTransformAlg.h:94
MuonR4::HoughSegmentSeed_impl
Representation of a segment seed (a fully processed hough maximum) produced by the hough transform.
Definition: HoughSegmentSeed.h:13
MuonR4::MuonPhiHoughTransformAlg::countIncompatibleEtaHits
int countIncompatibleEtaHits(const MuonR4::ActsPeakFinderForMuon::Maximum &phiMaximum, const MuonR4::HoughMaximum &etaMaximum) const
helper to count the number of eta measurements that would be discarded for a given phi extension cand...
Definition: MuonPhiHoughTransformAlg.cxx:59
MuonR4::MuonPhiHoughTransformAlg::m_maxEtaHolesOnMax
IntegerProperty m_maxEtaHolesOnMax
Definition: MuonPhiHoughTransformAlg.h:119
MuonR4::MuonHoughEventData_impl::phiHitsOnMax
size_t phiHitsOnMax
Definition: MuonHoughEventData.h:72
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37