ATLAS Offline Software
Loading...
Searching...
No Matches
MuPatHitTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "MuPatHitTool.h"
6
21#include "TrkTrack/Track.h"
23
24namespace Muon {
25
26 MuPatHitTool::MuPatHitTool(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t, n, p) {
27 declareInterface<MuPatHitTool>(this);
28 }
29
31
33 ATH_CHECK(m_idHelperSvc.retrieve());
34 ATH_CHECK(m_mdtRotCreator.retrieve());
35 ATH_CHECK(m_cscRotCreator.retrieve(DisableTool{m_cscRotCreator.empty()}));
36 ATH_CHECK(m_edmHelperSvc.retrieve());
37 ATH_CHECK(m_printer.retrieve());
38 ATH_CHECK(m_pullCalculator.retrieve());
39 ATH_CHECK(m_propagator.retrieve());
40
41 return StatusCode::SUCCESS;
42 }
43
44 bool MuPatHitTool::create(const EventContext& ctx, const MuonSegment& seg, MuPatHitList& hitList) const {
45 ATH_MSG_DEBUG(" creating hit list from segment " << std::endl << m_printer->print(seg));
46
47 // create parameters with very large momentum and no charge
48 double momentum{1.e8}, charge{0.};
49 std::unique_ptr<const Trk::TrackParameters> pars{m_edmHelperSvc->createTrackParameters(seg, momentum, charge)};
50 if (!pars) {
51 ATH_MSG_WARNING(" could not create track parameters for segment ");
52 return false;
53 }
54
55 return create(ctx, *pars, seg.containedMeasurements(), hitList);
56 }
57
58 bool MuPatHitTool::create(const EventContext& ctx, const Trk::TrackParameters& pars,
59 const std::vector<const Trk::MeasurementBase*>& measVec, MuPatHitList& hitList) const {
60 // loop over hits
61 for (const Trk::MeasurementBase* meas : measVec) {
62 // create hit info
63 MuPatHit::Info hitInfo = getHitInfo(*meas);
64
65 const Identifier& id = hitInfo.id;
66 if (hitInfo.type == MuPatHit::UnknownType) {
67 ATH_MSG_WARNING(" unknown hit type " << m_idHelperSvc->toString(id));
68 continue;
69 }
70
71 // create broad measurement
72 std::unique_ptr<const Trk::MeasurementBase> broadMeas = createBroadMeasurement(*meas, hitInfo);
73 if (!broadMeas) {
74 ATH_MSG_WARNING(" could not create broad measurement " << m_idHelperSvc->toString(id));
75 continue;
76 }
77 // extrapolate
78 std::unique_ptr<const Trk::TrackParameters> exPars;
79 if (pars.associatedSurface() == broadMeas->associatedSurface()) {
80 exPars = pars.uniqueClone();
81 ATH_MSG_VERBOSE(" start parameters and measurement expressed at same surface, cloning parameters ");
82 } else {
83 exPars = m_propagator->propagate(ctx, pars, broadMeas->associatedSurface(), Trk::anyDirection, false, m_magFieldProperties);
84 if (!exPars) { continue; } // !exPars
85 }
86
87 // create hit and insert it into list
88 ATH_MSG_VERBOSE(" inserting hit " << m_idHelperSvc->toString(id) << " " << m_printer->print(*exPars));
89 std::unique_ptr<MuPatHit> hit = std::make_unique<MuPatHit>(std::move(exPars), meas->uniqueClone(), std::move(broadMeas), hitInfo);
90 hitList.push_back(std::move(hit));
91 }
92
93 const SortByDirectionMuPatHits isLargerCal{pars};
94 std::stable_sort(hitList.begin(), hitList.end(), isLargerCal);
95 return true;
96 }
97
98 bool MuPatHitTool::create(const Trk::Track& track, MuPatHitList& hitList) const {
99 // loop over hits
100 for (const Trk::TrackStateOnSurface* tsit : *track.trackStateOnSurfaces()) {
101 // do not take into account scatteres and holes for now
102 if (tsit->type(Trk::TrackStateOnSurface::Scatterer) ||
103 tsit->type(Trk::TrackStateOnSurface::Hole)) continue;
104
105 const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
106 if (!meas) continue;
107
108 const Trk::TrackParameters* pars = tsit->trackParameters();
109 if (!pars) continue;
110
111 // create hit info
112 MuPatHit::Info hitInfo = getHitInfo(*meas);
113
115
116 const Identifier& id = hitInfo.id;
117
118 if (!m_idHelperSvc->isMuon(id)) continue;
119
120 if (hitInfo.type == MuPatHit::UnknownType) {
121 ATH_MSG_WARNING(" unknown hit type " << m_idHelperSvc->toString(id));
122 continue;
123 }
124
125 // create broad measurement
126 std::unique_ptr<const Trk::MeasurementBase> broadMeas = createBroadMeasurement(*meas, hitInfo);
127 if (!broadMeas) {
128 ATH_MSG_WARNING(" could not create broad measurement " << m_idHelperSvc->toString(id));
129 continue;
130 }
131
132 // create hit and insert it into list
133 std::unique_ptr<MuPatHit> hit = std::make_unique<MuPatHit>(pars->uniqueClone(), meas->uniqueClone(), std::move(broadMeas), hitInfo);
134 ATH_MSG_VERBOSE(" inserting hit " << m_printer->print(*meas) << (hitInfo.status == MuPatHit::Outlier ? " Outlier" : ""));
135 double residual{0.}, pull{0.};
136 calculateResiduals(tsit, Trk::ResidualPull::Unbiased, residual, pull);
137 hit->setResidual(residual,pull);
138 hitList.push_back(std::move(hit));
139 }
140
141 const Trk::TrackParameters* pars = track.perigeeParameters();
142 const SortByDirectionMuPatHits isLargerCal{*pars};
143 std::stable_sort(hitList.begin(), hitList.end(), isLargerCal);
144
145 return true;
146 }
147
148 MuPatHitList MuPatHitTool::merge(const MuPatHitList& hitList1, const MuPatHitList& hitList2) {
149 // copy first list into outList
150 MuPatHitList tmpList{};
151 tmpList.reserve(hitList1.size() + hitList2.size());
152
153 if (!hitList1.empty()) {
154 const Trk::TrackParameters& pars{hitList1.front()->parameters()};
155 const SortByDirectionMuPatHits isLargerCal{pars};
156 std::merge(hitList1.begin(), hitList1.end(), hitList2.begin(), hitList2.end(),
157 std::back_inserter(tmpList), isLargerCal);
158 } else {
159 return hitList2;
160 }
161 MuPatHitList outList{};
162 outList.reserve(tmpList.size());
163 std::set<Identifier> used_hits{};
165 std::copy_if(std::make_move_iterator(tmpList.begin()), std::make_move_iterator(tmpList.end()), std::back_inserter(outList),
166 [&used_hits](const MuPatHitPtr& pathit) { return used_hits.insert(pathit->info().id).second; });
167
168 return outList;
169 }
170
171 bool MuPatHitTool::extract(const MuPatHitList& hitList, std::vector<const Trk::MeasurementBase*>& measVec, bool usePreciseHits,
172 bool /*getReducedTrack*/) {
173 // make sure the vector is sufficiently large
174 measVec.reserve(hitList.size());
175
176 // loop over hit list
177 for (const MuPatHitPtr& hit : hitList) {
178 if (hit->info().status != MuPatHit::OnTrack) { continue; }
179 const Trk::MeasurementBase* meas = usePreciseHits ? &hit->preciseMeasurement() : &hit->broadMeasurement();
180 measVec.push_back(meas);
181 }
182 return true;
183 }
184
185 bool MuPatHitTool::remove(const Identifier& id, MuPatHitList& hitList) {
186 // loop over hit list
187 MuPatHitIt lit = hitList.begin(), lit_end = hitList.end();
188 for (; lit != lit_end; ++lit) {
189 const MuPatHit& hit = **lit;
190 if (hit.info().id == id) {
191 hitList.erase(lit);
192 return true;
193 }
194 }
195 // if we get here the hit was not found
196 return false;
197 }
198
199 bool MuPatHitTool::remove(const Trk::MeasurementBase& meas, MuPatHitList& hitList) const {
200 // loop over hit list
201 const Identifier meas_id = m_edmHelperSvc->getIdentifier(meas);
202 MuPatHitIt lit = hitList.begin(), lit_end = hitList.end();
203 for (; lit != lit_end; ++lit) {
204 const MuPatHit& hit = **lit;
205 if (m_edmHelperSvc->getIdentifier(hit.preciseMeasurement()) == meas_id ||
206 m_edmHelperSvc->getIdentifier(hit.broadMeasurement()) == meas_id) {
207 hitList.erase(lit);
208 return true;
209 }
210 }
211 // if we get here the hit was not found
212 return false;
213 }
214
216 if (m_idHelperSvc->isMdt(id))
217 return MuPatHit::MDT;
218 else if (m_idHelperSvc->isTgc(id))
219 return MuPatHit::TGC;
220 else if (m_idHelperSvc->isCsc(id))
221 return MuPatHit::CSC;
222 else if (m_idHelperSvc->isRpc(id))
223 return MuPatHit::RPC;
224 else if (m_idHelperSvc->isMM(id))
225 return MuPatHit::MM;
226 else if (m_idHelperSvc->issTgc(id))
227 return MuPatHit::sTGC;
228 else if (m_idHelperSvc->isMuon(id))
229 return MuPatHit::PREC;
231 }
232
234 MuPatHit::Info hitInfo{};
235 hitInfo.id = m_edmHelperSvc->getIdentifier(meas);
236 // for clusters store layer id instead of channel id
237 hitInfo.measuresPhi = true; // assume that all PseudoMeasurements measure phi!!
238 hitInfo.type = MuPatHit::Pseudo;
239 hitInfo.status = MuPatHit::OnTrack;
240 if (hitInfo.id.is_valid() && m_idHelperSvc->isMuon(hitInfo.id)) {
241 hitInfo.type = getHitType(hitInfo.id);
242 hitInfo.measuresPhi = m_idHelperSvc->measuresPhi(hitInfo.id);
243 hitInfo.isSmall = m_idHelperSvc->isSmallChamber(hitInfo.id);
244 hitInfo.stIdx = m_idHelperSvc->stationIndex(hitInfo.id);
245 hitInfo.isEndcap = m_idHelperSvc->isEndcap(hitInfo.id);
246 if (hitInfo.type != MuPatHit::MDT && hitInfo.type != MuPatHit::MM) hitInfo.id = m_idHelperSvc->layerId(hitInfo.id);
247 }
248 return hitInfo;
249 }
250
251 std::unique_ptr<const Trk::MeasurementBase> MuPatHitTool::createBroadMeasurement(const Trk::MeasurementBase& meas,
252 const MuPatHit::Info& hitInfo) const {
253 // don't change errors for Pseudo measurements
254 if (hitInfo.type == MuPatHit::MDT) {
255 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(&meas);
256 if (!mdt) {
257 ATH_MSG_WARNING(" found hit with a MDT Identifier that is not a MdtDriftCircleOnTrack "
258 << m_idHelperSvc->toString(hitInfo.id));
259 return nullptr;
260 }
261 ATH_MSG_DEBUG(" creating broad MdtDriftCircleOnTrack ");
262
263 return std::unique_ptr<const Trk::MeasurementBase>(m_mdtRotCreator->updateError(*mdt));
264
265 } else if (hitInfo.type == MuPatHit::CSC && !hitInfo.measuresPhi) {
266 if (m_cscRotCreator.empty()) {
267 // Configured to not use CSC's
268 return nullptr;
269 }
270 const CscClusterOnTrack* csc = dynamic_cast<const CscClusterOnTrack*>(&meas);
271 if (!csc) {
272 ATH_MSG_WARNING(" found hit with CSC identifier that is not a CscClusterOnTrack " << m_idHelperSvc->toString(hitInfo.id));
273 return nullptr;
274 }
275 ATH_MSG_DEBUG(" creating broad CscClusterOnTrack ");
276
277 return std::unique_ptr<const Trk::MeasurementBase>(
278 m_cscRotCreator->createRIO_OnTrack(*csc->prepRawData(), csc->globalPosition()));
279 }
280
281 // don't change errors for CSC phi hits, TGC, RPC and Pseudo measurements
282 return meas.uniqueClone();
283 }
284
285 bool MuPatHitTool::update(const Trk::Track& track, MuPatHitList& hitList) const {
286 const DataVector<const Trk::MeasurementBase>* measurements = track.measurementsOnTrack();
287 if (!measurements) return false;
288
289 std::set<Identifier> ids;
290
293 for (; mit != mit_end; ++mit) {
294 Identifier id = m_edmHelperSvc->getIdentifier(**mit);
295 if (!id.is_valid()) continue;
296
297 if (!m_idHelperSvc->isMdt(id)) id = m_idHelperSvc->layerId(id);
298
299 ids.insert(id);
300 }
301
302 // loop over hit list
303 MuPatHitIt lit = hitList.begin(), lit_end = hitList.end();
304 for (; lit != lit_end; ++lit) {
305 MuPatHit& hit = **lit;
306 if (!ids.count(hit.info().id)) {
308 continue;
309 }
310 }
311 return true;
312 }
313
314 std::string MuPatHitTool::print(const MuPatHitList& hitList, bool printPos, bool printDir, bool printMom) const {
315 std::ostringstream sout;
316 DistanceAlongParameters distCal{};
317
318 // for nicely aligned printout, get max width of Id printout
319 std::vector<std::string> idStrings;
320 std::vector<std::string> dataStrings;
321 idStrings.reserve(hitList.size());
322 unsigned int idWidth = 0;
323 std::string result = "first ";
324 bool isLarger = true;
325 double distance = 0;
326 MuPatHitCit it = hitList.begin();
327 MuPatHitCit it_end = hitList.end();
328 MuPatHitCit itNext = hitList.begin();
329
330 const Trk::TrackParameters& pars{hitList.front()->parameters()};
331 const SortByDirectionMuPatHits isLargerCal{pars};
332
333 if (itNext != it_end) ++itNext;
334 for (; it != it_end; ++it, ++itNext) {
335
336 Identifier id = m_edmHelperSvc->getIdentifier((*it)->measurement());
337 std::string idStr = id.is_valid() ? m_idHelperSvc->toString(id) : "pseudo-measurement";
338 idStrings.push_back(idStr);
339 if (idStr.length() > idWidth) idWidth = idStr.length();
340 const Trk::TrackParameters& pars = (*it)->parameters();
341 std::ostringstream dataOss;
342 if (printPos) {
343 dataOss << "r " << std::fixed << std::setprecision(0) << std::setw(5) << pars.position().perp() << " z " << std::fixed
344 << std::setprecision(0) << std::setw(6) << pars.position().z();
345 }
346 if (printDir) {
347 dataOss << " theta " << std::fixed << std::setprecision(5) << std::setw(7) << pars.momentum().theta() << " phi "
348 << std::fixed << std::setprecision(3) << std::setw(6) << pars.momentum().phi();
349 }
350 if (printMom) {
351 dataOss << " q*p(GeV) " << std::scientific << std::setprecision(3) << std::setw(10)
352 << pars.momentum().mag() * pars.charge() / 1000.;
353 }
354
355
356 dataOss << " " << result << " dist " << distance;
357 dataStrings.push_back(dataOss.str());
358 if (itNext != it_end) {
359 isLarger = isLargerCal(*it, *itNext);
360
361 distance = distCal(*it, *itNext);
362 result = isLarger ? "larger " : "smaller";
363
364 if (isLarger == isLargerCal(*itNext, *it)) {
365 result = "duplicate";
366 } else if (!isLarger) {
367 result += " sorting problem ";
368 }
369 }
370 }
371
372 // second loop to print out aligned strings
373 unsigned int n = idStrings.size();
374 for (unsigned int i = 0; i < n; ++i) {
375 sout << " " << std::left << std::setw(idWidth) << idStrings[i] << std::right << " " << dataStrings[i];
376 if (i != n - 1) sout << std::endl;
377 }
378
379 return sout.str();
380 }
382 MuPatHitCit it = hitList.begin();
383 MuPatHitCit it_end = hitList.end();
384 MuPatHitCit itNext = it;
385 if (itNext != it_end) ++itNext;
386 bool isLarger = true;
387 const Trk::TrackParameters& pars{hitList.front()->parameters()};
388 const SortByDirectionMuPatHits isLargerCal{pars};
389 for (; itNext != it_end; ++it, ++itNext) {
390 isLarger = isLargerCal(*it, *itNext);
391 bool sameSurface = (isLarger == isLargerCal(*it, *itNext)); // same surface
392 if (!isLarger && !sameSurface) return false;
393 if (sameSurface) return false;
394 }
395 return true;
396 }
398 double& residualPull) const {
399 std::optional<Trk::ResidualPull> resPull(
400 m_pullCalculator->residualPull(tsos->measurementOnTrack(), tsos->trackParameters(), type));
401 if (resPull) {
402 residual = resPull->residual().front();
403 residualPull = resPull->pull().front();
404 } else {
405 residual = residualPull = -999;
406 }
407 }
408} // namespace Muon
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Standard const_iterator.
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
bool is_valid() const
Check if id is in a valid state.
Class to represent the calibrated clusters created from CSC strips.
virtual const CscPrepData * prepRawData() const override final
Returns the CscPrepData - is a CscPrepData in this scope.
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
PublicToolHandle< MuonEDMPrinterTool > m_printer
MuPatHit::Type getHitType(const Identifier &id) const
get hit type
void calculateResiduals(const Trk::TrackStateOnSurface *tsos, Trk::ResidualPull::ResidualType type, double &residual, double &residualPull) const
calculate the residuals
ToolHandle< Trk::IResidualPullCalculator > m_pullCalculator
static bool remove(const Identifier &id, MuPatHitList &hitList)
remove hit with a give Identifier
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
static MuPatHitList merge(const MuPatHitList &hitList1, const MuPatHitList &hitList2)
merge two MuPatHitLists into a new one
ToolHandle< IMuonClusterOnTrackCreator > m_cscRotCreator
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Trk::MagneticFieldProperties m_magFieldProperties
magnetic field properties
ToolHandle< Trk::IPropagator > m_propagator
StatusCode initialize() override
initialize method, method taken from bass-class AlgTool
static bool extract(const MuPatHitList &hitList, std::vector< const Trk::MeasurementBase * > &measVec, bool usePreciseHits=true, bool getReducedTrack=false)
merge two MuPatHitLists into a new one.
MuPatHit::Info getHitInfo(const Trk::MeasurementBase &meas) const
get hit info
bool update(const Trk::Track &track, MuPatHitList &hitList) const
update hit list for a give track
~MuPatHitTool()
destructor
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
std::unique_ptr< const Trk::MeasurementBase > createBroadMeasurement(const Trk::MeasurementBase &preciseMeas, const MuPatHit::Info &hitInfo) const
calculate broad measurement for a give precise measurement
MuPatHitTool(const std::string &, const std::string &, const IInterface *)
default AlgTool constructor
std::string print(const MuPatHitList &hitList, bool printPos=true, bool printDir=true, bool printMom=true) const
print the list of hits, with optional parts of the printout (position,direction,momentum)
static bool isSorted(const MuPatHitList &hitList)
check whether the list is correctly sorted
bool create(const EventContext &ctx, const MuonSegment &seg, MuPatHitList &hitList) const
create a MCTBList from a MuonSegment
const Trk::MeasurementBase & broadMeasurement() const
returns broad measurement
Definition MuPatHit.cxx:50
const Trk::MeasurementBase & preciseMeasurement() const
returns precise measurement
Definition MuPatHit.cxx:49
const Info & info() const
returns a reference to the hit info
Definition MuPatHit.cxx:51
virtual const Amg::Vector3D & globalPosition() const override
Returns global position.
This is the common class for 3D segments used in the muon spectrometer.
Default for both collision and cosmic parameter sorting.
This class is the pure abstract base class for all fittable tracking measurements.
std::unique_ptr< MeasurementBase > uniqueClone() const
NVI Clone giving up unique pointer.
@ Unbiased
RP with track state that has measurement not included.
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
represents the track state (measurement, material, fit parameters and quality) at a surface.
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
@ Hole
A hole on the track - this is defined in the following way.
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
std::vector< MuPatHitPtr > MuPatHitList
Definition MuPatHit.h:26
std::shared_ptr< MuPatHit > MuPatHitPtr
Definition MuPatHit.h:25
MuPatHitList::iterator MuPatHitIt
Definition MuPatHit.h:28
MuPatHitList::const_iterator MuPatHitCit
Definition MuPatHit.h:27
@ anyDirection
ParametersBase< TrackParametersDim, Charged > TrackParameters
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
Identifier id
Identifier of the measurement. Is invalid in cases of pseudo measurements.
Definition MuPatHit.h:39
bool isEndcap
Hit in the endcap?
Definition MuPatHit.h:54
MuonStationIndex::StIndex stIdx
Station index of the Identifier BI.
Definition MuPatHit.h:48
bool measuresPhi
Does the hit constrain phi?
Definition MuPatHit.h:56
Type type
Measurement type as defined above.
Definition MuPatHit.h:42
Status status
Flag whether the hit is on Tack or not.
Definition MuPatHit.h:46
bool isSmall
Small or large sector?
Definition MuPatHit.h:52