ATLAS Offline Software
DCMathSegmentMaker.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "DCMathSegmentMaker.h"
6 
7 #include <cassert>
8 #include <functional>
9 #include <iostream>
10 
11 #include "AthenaKernel/Timeout.h"
42 #include "TrkRoad/TrackRoad.h"
45 #include "TrkTrack/Track.h"
46 
47 namespace {
48 
49  double cot(double x) {
51  constexpr double dX = std::numeric_limits<float>::epsilon();
52  if (std::abs(x) < dX || std::abs(x - M_PI) < dX) return std::numeric_limits<float>::max();
54  return std::tan(M_PI_2 - x);
55  }
56  template <typename T> constexpr T absmax(const T& a, const T& b) {
57  return std::abs(a) > std::abs(b) ? a : b;}
58 
59 } // namespace
60 namespace Muon {
61 
62  DCMathSegmentMaker::DCMathSegmentMaker(const std::string& t, const std::string& n, const IInterface* p) :
63  base_class(t, n, p) {}
64 
66  ATH_CHECK(m_mdtKey.initialize(m_removeDeltas && !m_mdtKey.empty()));
67  // retrieve MuonDetectorManager
69  ATH_CHECK(m_mdtCreator.retrieve());
70  ATH_CHECK(m_mdtCreatorT0.retrieve(DisableTool{m_mdtCreatorT0.empty()}));
71  ATH_CHECK(m_clusterCreator.retrieve());
72  ATH_CHECK(m_compClusterCreator.retrieve());
73  ATH_CHECK(m_idHelperSvc.retrieve());
74  ATH_CHECK(m_printer.retrieve());
75  ATH_CHECK(m_edmHelperSvc.retrieve());
76  ATH_CHECK(m_segmentFinder.retrieve());
78  ATH_CHECK(m_segmentFitter.retrieve(DisableTool{!m_refitParameters}));
79  ATH_CHECK(m_dcslFitProvider.retrieve(DisableTool{m_dcslFitProvider.empty()}));
80 
81  // initialise for data handles
83  return StatusCode::SUCCESS;
84  }
85 
86  void DCMathSegmentMaker::find(const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir,
87  const std::vector<const MdtDriftCircleOnTrack*>& mdts,
88  const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements,
89  Trk::SegmentCollection* segColl, double momentum, double sinAngleCut) const {
90  const EventContext& ctx = Gaudi::Hive::currentContext();
91  if (m_doTimeOutChecks && Athena::Timeout::instance().reached()) {
92  ATH_MSG_DEBUG("Timeout reached. Aborting sequence.");
93  return;
94  }
95 
96  ATH_MSG_DEBUG("In find, passed " << mdts.size() << " MDTs & "<<clusters.size()<<" clusters");
97 
98  if (mdts.size() < 3) return;
99 
101 
102  if (!firstRot) { return; }
103 
104  const MuonGM::MdtReadoutElement* detEl = firstRot->detectorElement();
105 
106  if (!detEl) {
107  ATH_MSG_WARNING(" no MdtReadoutElement found, returning 0 ");
108  return;
109  }
110 
111  // identifier
112  Identifier chid = firstRot->identify();
113 
114  // endcap or barrel
115  bool isEndcap = m_idHelperSvc->mdtIdHelper().isEndcap(chid);
116 
117  // global to local transformation for chamber
118  Amg::Transform3D gToStation = detEl->GlobalToAmdbLRSTransform();
119 
120  // define axis of chamber in global coordinates
121  Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform();
122 
123  // transform nominal pointing chamber position into surface frame
124  Amg::Vector3D globalDirCh{detEl->center()};
125  Amg::Vector3D dirCh(gToStation.linear() * globalDirCh);
126  double chamber_angleYZ = std::atan2(dirCh.z(), dirCh.y());
127 
128  Amg::Vector3D roaddir2 = roaddir;
129  double dotprod = globalDirCh.perp() * std::sin(roaddir2.theta()) + globalDirCh.z() * std::cos(roaddir2.theta());
130  if (dotprod < 0) roaddir2 = -roaddir2;
131 
132  // transform the global direction into the surface frame
133  Amg::Vector3D d(gToStation.linear() * roaddir2);
134  // calculate the local road angles in the surface frame
135  double road_angleXZ = std::atan2(d.z(), d.x());
136  double road_angleYZ = std::atan2(d.z(), d.y());
137 
138  if (!hasPhiMeasurements) road_angleXZ = M_PI; // if no phi, take phi perpendicular to plane
139  ATH_MSG_VERBOSE("global road pos "<<Amg::toString(roadpos)<<", global road dir " << Amg::toString(roaddir2) << " XZ " << road_angleXZ << " YZ " << road_angleYZ << " isEndcap "
140  << isEndcap << " central phi " << detEl->center().phi() << " r " << detEl->center().perp()
141  << " z " << detEl->center().z());
142 
143  // rescale errors for low momentum
144  double errorScale = errorScaleFactor(chid, momentum, hasPhiMeasurements);
145 
146  /* ***** create cluster hits ******** */
147  ATH_MSG_DEBUG(" adding clusters " << clusters.size());
148  ClusterVecPair spVecs;
149  if (m_doSpacePoints)
150  spVecs = create2DClusters(clusters);
151  else
152  spVecs = create1DClusters(clusters);
153  TrkDriftCircleMath::CLVec cls = createClusterVec(chid, spVecs.first, gToStation);
154 
155  /* ***** create MDT hits ************ */
156  if (msgLvl(MSG::VERBOSE)) {
157  std::stringstream sstr{};
158  for (const MdtDriftCircleOnTrack* mdt : mdts)
159  sstr<<m_printer->print(*mdt)<<std::endl;
160  ATH_MSG_VERBOSE(" adding mdts " << mdts.size()<<std::endl<<sstr.str());
161  }
162 
163  // set to get Identifiers of chambers with hits
164  std::set<Identifier> chamberSet;
165  double phimin{-9999}, phimax{9999};
166  TrkDriftCircleMath::DCStatistics dcStatistics; // statistics on chamber occupancy
167  TrkDriftCircleMath::DCVec dcs = createDCVec(mdts, errorScale, chamberSet, phimin, phimax, dcStatistics, gToStation, amdbToGlobal);
168 
169  // create geometry
170  std::shared_ptr<const TrkDriftCircleMath::ChamberGeometry> multiGeo;
171  if (m_doGeometry) {
172  ATH_MSG_VERBOSE(" using chamber geometry with #chambers " << chamberSet.size());
173  // vector to store chamber geometries
174  std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos{};
175 
176  // loop over chambers
177  geos.reserve(chamberSet.size());
178  for (const Identifier& id : chamberSet) {
179  ATH_MSG_VERBOSE("Chamber: "<<m_idHelperSvc->toStringChamber(id));
180  geos.push_back(createChamberGeometry(id, gToStation));
181  }
182  // create new geometry
183  multiGeo = std::make_unique<TrkDriftCircleMath::MdtMultiChamberGeometry>(geos);
184 
185 
186  }
187 
188  double angle = m_sinAngleCut;
189  if (sinAngleCut > 0) angle = sinAngleCut;
190  TrkDriftCircleMath::Road road(TrkDriftCircleMath::LocVec2D{0.,0.}, road_angleYZ, chamber_angleYZ, angle);
191 
192  // call segment finder
193  TrkDriftCircleMath::SegVec segs = m_segmentFinder->findSegments(dcs, cls, road, dcStatistics, multiGeo.get());
194 
195  if (msgLvl(MSG::VERBOSE)) {
196  std::stringstream sstr{};
197  unsigned int seg_n{0};
198  for (const TrkDriftCircleMath::Segment& seg: segs) {
199  constexpr double toDeg = 1./Gaudi::Units::degree;
200  sstr<<"Segment number "<<seg_n<<" is at ("<<seg.line().x0()<<","<<seg.line().y0()<<") pointing to "<<seg.line().phi()*toDeg<<" chi2: "<<
201  (seg.chi2()/seg.ndof())<<"("<<seg.ndof()<<")"<<std::endl;
202  sstr<<"Mdt measurements: "<<seg.dcs().size()<<std::endl;
203  for (const TrkDriftCircleMath::DCOnTrack & mdt_meas : seg.dcs()){
204  sstr<<" **** "<<m_printer->print(*mdt_meas.rot());
205  sstr<<" ("<<mdt_meas.state()<<")"<<std::endl;
206  }
207  sstr<<"Cluster measurements "<<seg.clusters().size()<<std::endl;
208  for (const TrkDriftCircleMath::Cluster& clus: seg.clusters()) {
209  sstr<<" ---- "<<m_printer->print(*clus.rot())<<std::endl;
210  }
211  sstr<<std::endl;
212  ++seg_n;
213  }
214  ATH_MSG_VERBOSE("Found " << segs.size() << " segments "<<std::endl<<sstr.str());
215  }
216 
217  // return
218  if (segs.empty()) { return; }
219 
220  // loop over segments
221  segmentCreationInfo sInfo(spVecs, multiGeo.get(), gToStation, amdbToGlobal, phimin, phimax);
222  for (TrkDriftCircleMath::Segment& seg : segs) {
223  std::unique_ptr<MuonSegment> segment = createSegment(ctx, seg, chid, roadpos, roaddir2, mdts, hasPhiMeasurements, sInfo);
224  if (segment) segColl->push_back(segment.release());
225  }
226  ATH_MSG_DEBUG(" Done ");
227  }
228 
229  std::unique_ptr<MuonSegment> DCMathSegmentMaker::createSegment(const EventContext& ctx, TrkDriftCircleMath::Segment& segment, const Identifier& chid,
230  const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir2,
231  const std::vector<const MdtDriftCircleOnTrack*>& mdts, bool hasPhiMeasurements,
232  segmentCreationInfo& sInfo) const {
233  bool isEndcap = m_idHelperSvc->isEndcap(chid);
234  // find all curved segments
235  MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chid);
236 
237  static constexpr std::array<Muon::MuonStationIndex::ChIndex ,4> statWithField{MuonStationIndex::BIL, MuonStationIndex::BML,
239  const bool isCurvedSegment = segment.hasCurvatureParameters() &&
240  std::find(statWithField.begin(), statWithField.end(), chIndex) != statWithField.end();
241 
242  // remove segments with too few hits
243  if (segment.hitsOnTrack() < 3) return nullptr;
244 
245  // convert segment parameters + x position from road
246  const TrkDriftCircleMath::Line& line = segment.line();
247 
248  ATH_MSG_DEBUG("New segment: chi2 " << segment.chi2() << " ndof " << segment.ndof() << " line " << line.position().x() << ","
249  << line.position().y() << " phi " << line.phi() << " associated clusters "
250  << segment.clusters().size());
251 
252  // local position along x from road
253  Amg::Vector3D lroadpos = sInfo.globalTrans * roadpos;
254  Amg::Vector3D lroaddir = sInfo.globalTrans.linear() * roaddir2;
255 
256  // local x position of first tube used if no phi measurement is present
257  double lxroad = 0.;
258 
259  if (hasPhiMeasurements) {
260  // calculate local position of segment along tube using the road
261  // calculate intersect pattern measurement plane
262  double sphi = 0.;
263  double cphi = lroaddir.x();
264  // swap local y and z in the endcaps
265  if (isEndcap) {
266  sphi = lroaddir.y();
267  lxroad = lroadpos.x() + (-lroadpos.y() + line.position().x()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
268  } else {
269  sphi = lroaddir.z();
270  lxroad = lroadpos.x() + (-lroadpos.z() + line.position().y()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
271  }
272 
273  double shortestTubeLen = 1e9;
274  // loop over hits and get the shortest tube on the segment
275  for (const TrkDriftCircleMath::DCOnTrack& driftCircle : segment.dcs()) {
276  if (driftCircle.state() != TrkDriftCircleMath::DCOnTrack::OnTrack) continue;
277 
278  const MdtDriftCircleOnTrack* riodc{driftCircle.rot()};
279  int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(riodc->identify());
280  int tube = m_idHelperSvc->mdtIdHelper().tube(riodc->identify());
281  double tubelen = 0.5 * riodc->prepRawData()->detectorElement()->getActiveTubeLength(lay, tube);
282  if (tubelen < shortestTubeLen) shortestTubeLen = tubelen;
283  }
284  // if the predicted position lies outside the chamber move it back inside
285  if (std::abs(lxroad) > shortestTubeLen) {
286  ATH_MSG_DEBUG("coordinates far outside chamber! using global position of first hit ");
287  if (lxroad < 0.) shortestTubeLen *= -1.;
288  lxroad = shortestTubeLen;
289  }
290  } else {
291  lxroad = (sInfo.globalTrans * mdts[0]->prepRawData()->detectorElement()->surface(mdts[0]->identify()).center()).x();
292  }
293 
294  // calculate local direction vector
295  Amg::Vector3D lpos(lxroad, line.position().x(), line.position().y());
296 
297  // global position segment
298  Amg::Vector3D gpos = sInfo.amdbTrans * lpos;
299 
300  // create new surface
301  Amg::Transform3D surfaceTransform(sInfo.amdbTrans.rotation());
302  surfaceTransform.pretranslate(gpos);
303  double surfDim = 500.;
304  std::unique_ptr<Trk::PlaneSurface> surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
305 
306  // measurements
307  Amg::Vector2D segLocPos{Amg::Vector2D::Zero()};
308  double linephi = line.phi();
309 
310  // now update the global direction using the local precision angle of the segment and the global phi angle of the
311  // road.
312  Amg::Vector3D gdir = updateDirection(linephi, *surf, roaddir2, isCurvedSegment);
313 
314  // extract RIO_OnTracks
315  std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> > rioDistVec; // vector to store the distance of a ROT to the segment
316 
317  // associate MDT hits to segment
318  std::set<Identifier> deltaVec;
319  std::set<Identifier> outoftimeVec;
320 
321  associateMDTsToSegment(gdir, segment, sInfo.geom, sInfo.globalTrans, sInfo.amdbTrans, deltaVec, outoftimeVec, rioDistVec);
322  std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>> garbage_collector;
323 
325 
326  if (m_redo2DFit && !isCurvedSegment) {
327  // refit segment after recalibration
328  TrkDriftCircleMath::DCSLFitter defaultFitter;
330  bool goodFit = defaultFitter.fit(result, line, segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs()));
331  if (goodFit) {
332  if (std::abs(xAOD::P4Helpers::deltaPhi(segment.line().phi(), result.line().phi())) > 0.01 ||
333  std::abs(segment.line().x0() - result.line().x0()) > 0.01 ||
334  std::abs(segment.line().y0() - result.line().y0()) > 0.01) {
335  // update local position and global
336  linephi = result.line().phi();
337  lpos[1] = result.line().position().x();
338  lpos[2] = result.line().position().y();
339  gpos = sInfo.amdbTrans * lpos;
340 
341  // recreate surface
342  surfaceTransform = Amg::Transform3D(sInfo.amdbTrans.rotation());
343  surfaceTransform.pretranslate(gpos);
344  surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
345 
346  // finally update global direction
347  gdir = updateDirection(linephi, *surf, roaddir2, isCurvedSegment);
348  }
349  }
350  }
351 
352  // create local segment direction
353  Trk::LocalDirection segLocDir;
354  surf->globalToLocalDirection(gdir, segLocDir);
355  if (segLocDir.angleYZ() == 0 && segLocDir.angleXZ() == 0) {
356  ATH_MSG_DEBUG("invalid local direction");
357  return nullptr;
358  }
359 
360  // sanity checks
361  const double diff_phi = xAOD::P4Helpers::deltaPhi(roaddir2.phi(), gdir.phi());
362  const double diff_prec = xAOD::P4Helpers::deltaPhi(linephi, segLocDir.angleYZ());
364  if (std::min(std::abs(diff_phi), std::abs( std::abs(diff_phi) - M_PI)) > 1.e-3 ||
365  std::min(std::abs(diff_prec), std::abs(std::abs(diff_prec) - M_PI)) > 1.e-3) {
366  ATH_MSG_WARNING(" ALARM updated angles wrong: diff phi " << diff_phi << " prec " << diff_prec << " phi rdir " << roaddir2.phi()
367  << " gdir " << gdir.phi() << " lphi " << linephi << " seg "
368  << segLocDir.angleYZ());
369  }
370 
371  // associate Clusters to segment, uses spVecs to get clusters
372  std::pair<std::pair<int, int>, bool> netaPhiHits =
373  associateClustersToSegment(segment, chid, sInfo.globalTrans, sInfo.clusters, sInfo.phimin, sInfo.phimax, rioDistVec);
374 
375  if (rioDistVec.empty()){
376  ATH_MSG_VERBOSE("No measurements were collected.");
377  return nullptr;
378 
379  }
381  auto meas_for_fit = [&rioDistVec] () {
382  std::vector<const Trk::MeasurementBase*> out{};
383  out.reserve(rioDistVec.size());
384  std::sort(rioDistVec.begin(), rioDistVec.end(), SortByDistanceToSegment());
385  for (const std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& ele : rioDistVec) out.push_back(ele.second.get());
386  return out;
387  };
388 
389 
390  double dlocx{1000.}, dangleXZ{1000.}, qoverp{-99999.}, dqoverp{-99999.};
391  bool hasMeasuredCoordinate = false;
392  if (m_refitParameters && netaPhiHits.second) {
393  ATH_MSG_DEBUG(" distance between first and last phi hit sufficient to perform 4D fit: phi " << gdir.phi() << " theta "
394  << gdir.theta());
395 
396  std::unique_ptr<Trk::Track> track{m_segmentFitter->fit(gpos, gdir, *surf, meas_for_fit())};
397 
398  if (track) {
399  if (isCurvedSegment && track->perigeeParameters() && track->perigeeParameters()->covariance()) {
400  qoverp = track->perigeeParameters()->parameters()[Trk::qOverP];
401  dqoverp = Amg::error(*track->perigeeParameters()->covariance(), Trk::qOverP);
402  }
403  hasMeasuredCoordinate = true;
404  // hack to update the second coordinate errors
405  Amg::MatrixX updatedCov(5, 5);
406  updatedCov.setZero();
407  m_segmentFitter->updateSegmentParameters(*track, *surf, segLocPos, segLocDir, updatedCov);
408  if (Amg::error(updatedCov, Trk::locX) > 0 && Amg::error(updatedCov, Trk::phi) > 0.) {
409  dlocx = Amg::error(updatedCov, Trk::locX);
410  dangleXZ = Amg::error(updatedCov, Trk::phi); // hack (2): phi not always angleXZ
411  } else {
412  ATH_MSG_WARNING(" Corrupt error matrix returned from fitter " << Amg::toString(updatedCov));
413  }
414 
416  surf->localToGlobal(segLocPos, gdir, gpos);
417  surf->localToGlobalDirection(segLocDir, gdir);
418 
419  if (track->measurementsOnTrack() && rioDistVec.size() != track->measurementsOnTrack()->size()) {
420  if (track->measurementsOnTrack()->empty()) {
421  ATH_MSG_DEBUG("No measurements survived");
422  return nullptr;
423  }
424  ATH_MSG_DEBUG(" ROT vector size changed after fit, updating ");
425  garbage_collector = std::move(rioDistVec);
426  rioDistVec.reserve(track->measurementsOnTrack()->size());
427  const Trk::TrackParameters* firstPars = nullptr;
428  for (const Trk::TrackStateOnSurface* tsit : *track->trackStateOnSurfaces()) {
429  const Trk::TrackParameters* pars = tsit->trackParameters();
430  if (!pars) continue;
431  if (!firstPars) firstPars = pars;
432 
433  // check whether state is a measurement, skip outliers if they are not MDT
434  const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
435  if (!meas) continue;
436  if (tsit->type(Trk::TrackStateOnSurface::Outlier) && !dynamic_cast<const MdtDriftCircleOnTrack*>(meas)) continue;
437  double dist = (pars->position() - firstPars->position()).dot(firstPars->momentum().unit());
438  rioDistVec.emplace_back(dist, meas->uniqueClone());
439  }
440  }
441  } else {
442  ATH_MSG_DEBUG(" refit of segment failed!! ");
443  netaPhiHits.second = false;
444  }
445  }
446 
447  // optional update of phi position and direction, only performed if the segment was not refitted and there are phi
448  // hits
449  if (m_updatePhiUsingPhiHits && !netaPhiHits.second) {
450  if (updateSegmentPhi(gpos, gdir, segLocPos, segLocDir, *surf, meas_for_fit(), sInfo.phimin, sInfo.phimax)) {
451  surf->localToGlobal(segLocPos, gpos, gpos);
452  surf->localToGlobalDirection(segLocDir, gdir);
453  hasMeasuredCoordinate = true;
454  dlocx = 100.;
455  dangleXZ = 0.1;
456  }
457  }
458 
459  if (msgLvl(MSG::DEBUG)) {
460  std::vector<const Trk::MeasurementBase*> debug_meas = meas_for_fit();
461  ATH_MSG_DEBUG(" number of hits " << debug_meas.size() << " of which trigger " << netaPhiHits.first.first << " eta and "
462  << netaPhiHits.first.second << " phi ");
463  for (const Trk::MeasurementBase* mit : debug_meas) {
464  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(mit);
465  if (rot) {
466  ATH_MSG_DEBUG(m_idHelperSvc->toString(rot->identify()));
467  const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rot);
468  if (mdt)
469  ATH_MSG_DEBUG(std::setprecision(4)
470  << " radius " << std::setw(6) << mdt->driftRadius() << " time " << std::setw(6) << mdt->driftTime());
471  continue;
472  }
473  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(mit);
474  if (crot) {
475  ATH_MSG_DEBUG(m_idHelperSvc->toString(crot->rioOnTrack(0).identify())
476  << " comp rot with hits " << crot->containedROTs().size());
477  continue;
478  }
479  ATH_MSG_WARNING("failed to dynamic_cast to ROT ");
480  }
481  }
482  // recalculate holes
483  std::vector<Identifier> holeVec = calculateHoles(ctx, chid, gpos, gdir, hasMeasuredCoordinate, deltaVec, outoftimeVec, rioDistVec);
484 
485  // currently not taking into account masked channels
486  if (!outoftimeVec.empty()) holeVec.insert(holeVec.end(), std::make_move_iterator(outoftimeVec.begin()),
487  std::make_move_iterator(outoftimeVec.end()));
488  MuonSegmentQuality* quality = new MuonSegmentQuality(segment.chi2(), segment.ndof(), holeVec);
489 
490  const TrkDriftCircleMath::DCSLFitter* dcslFitter = m_dcslFitProvider->getFitter();
492  if (dcslFitter && !segment.hasT0Shift() && m_outputFittedT0) {
493  if (!dcslFitter->fit(result, segment.line(), segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs()))) {
494  ATH_MSG_DEBUG(" T0 refit failed ");
495  } else {
496  ATH_MSG_DEBUG(" Fitted T0 " << result.t0Shift()<<" is valid "<<result.hasT0Shift());
497  }
498  }
499  bool hasFittedT0 = false;
500  double fittedT0{0}, errorFittedT0{1.};
501  if (m_outputFittedT0 && (segment.hasT0Shift() || (dcslFitter && result.hasT0Shift()))) {
502  hasFittedT0 = true;
503  if (segment.hasT0Shift()) {
504  fittedT0 = segment.t0Shift();
505  errorFittedT0 = segment.t0Error();
506  } else if (dcslFitter && result.hasT0Shift()) {
507  fittedT0 = result.t0Shift();
508  errorFittedT0 = result.t0Error();
509  } else {
510  ATH_MSG_WARNING(" Failed to access fitted t0 ");
511  hasFittedT0 = false;
512  }
513  }
514  // create new segment
515  std::unique_ptr<MuonSegment> msegment;
516  if (isCurvedSegment) { // curved segments
517  if (qoverp == -99999.) {
518  double charge = gpos.z() * std::tan(gdir.theta());
519  charge = charge / std::abs(charge);
520  // if the curved segment was not refit, then use a momentum estimate
521  constexpr double BILALPHA(28.4366), BMLALPHA(62.8267), BMSALPHA(53.1259), BOLALPHA(29.7554);
522  if (chIndex == MuonStationIndex::BIL) {
523  qoverp = (charge * segment.deltaAlpha()) / BILALPHA;
524  dqoverp = M_SQRT2 * segment.dtheta() / BILALPHA;
525  } else if (chIndex == MuonStationIndex::BML) {
526  qoverp = (charge * segment.deltaAlpha()) / BMLALPHA;
527  dqoverp = M_SQRT2 * segment.dtheta() / BMLALPHA;
528  } else if (chIndex == MuonStationIndex::BMS) {
529  qoverp = (charge * segment.deltaAlpha()) / BMSALPHA;
530  dqoverp = M_SQRT2 * segment.dtheta() / BMSALPHA;
531  } else if (chIndex == MuonStationIndex::BOL) {
532  qoverp = (charge * segment.deltaAlpha()) / BOLALPHA;
533  dqoverp = M_SQRT2 * segment.dtheta() / BOLALPHA;
534  }
535  }
536  Amg::MatrixX covMatrix(5, 5);
537  covMatrix.setIdentity();
538  covMatrix(0, 0) = dlocx * dlocx;
539  covMatrix(1, 1) = segment.dy0() * segment.dy0();
540  covMatrix(2, 2) = dangleXZ * dangleXZ;
541  covMatrix(3, 3) = segment.dtheta() * segment.dtheta();
542  covMatrix(4, 4) = dqoverp * dqoverp;
543 
544  std::vector<Trk::DefinedParameter> defPars;
545  defPars.emplace_back(segLocPos[Trk::loc1], Trk::loc1);
546  defPars.emplace_back(segLocPos[Trk::loc2], Trk::loc2);
547  defPars.emplace_back(gdir.phi(), Trk::phi);
548  defPars.emplace_back(gdir.theta(), Trk::theta);
549  defPars.emplace_back(qoverp, Trk::qOverP);
550  Trk::LocalParameters segLocPar(defPars);
551  msegment = std::make_unique<MuonSegment>(
552  std::move(segLocPar),
553  std::move(covMatrix),
554  surf.release(),
555  createROTVec(rioDistVec),
556  quality,
558  } else { // straight segments
559  // errors (for now no correlations)
560  Amg::MatrixX covMatrix(4, 4);
561  covMatrix.setIdentity();
562  covMatrix(0, 0) = dlocx * dlocx;
563  covMatrix(1, 1) = segment.dy0() * segment.dy0();
564  covMatrix(2, 2) = dangleXZ * dangleXZ;
565  covMatrix(3, 3) = segment.dtheta() * segment.dtheta();
566  msegment =
567  std::make_unique<MuonSegment>(segLocPos,
568  segLocDir,
569  std::move(covMatrix),
570  surf.release(),
571  createROTVec(rioDistVec),
572  quality,
574  }
575 
576  if (hasFittedT0) msegment->setT0Error(fittedT0, errorFittedT0);
577 
578  // check whether segment satisfies minimum quality criteria
579  int segmentQuality = m_segmentSelectionTool->quality(*msegment);
580 
581  if (msgLvl(MSG::DEBUG)) {
582  ATH_MSG_DEBUG(m_printer->print(*msegment) << " quality " << segmentQuality);
583  if (segmentQuality < 0) ATH_MSG_DEBUG(" BAD segment ");
584  if (hasFittedT0) ATH_MSG_DEBUG(" T0 " << fittedT0);
585  if (isCurvedSegment) ATH_MSG_DEBUG(" Curved " << fittedT0);
586  }
587  if (segmentQuality < 0) { return nullptr; }
588  return msegment;
589  }
590 
591  void DCMathSegmentMaker::find(const std::vector<const Trk::RIO_OnTrack*>& rios, Trk::SegmentCollection* segColl) const {
592  std::vector<const MdtDriftCircleOnTrack*> mdts;
593  std::vector<const MuonClusterOnTrack*> clusters;
594 
595  for (const Trk::RIO_OnTrack* it : rios) {
596  Identifier id = it->identify();
597  if (m_idHelperSvc->isMdt(id)) {
598  const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(it);
599  if (!mdt) { ATH_MSG_WARNING("failed dynamic_cast, not a MDT but hit has MDT id!!!"); }
600  mdts.push_back(mdt);
601  } else if (m_idHelperSvc->isTrigger(id)) {
602  const MuonClusterOnTrack* clus = dynamic_cast<const MuonClusterOnTrack*>(it);
603  if (!clus) { ATH_MSG_WARNING("failed dynamic_cast, not a cluster but hit has RPC/TGC id!!!"); }
604  clusters.push_back(clus);
605  }
606  }
607  find(mdts, clusters, segColl);
608  }
609 
610  void DCMathSegmentMaker::find(const std::vector<const MdtDriftCircleOnTrack*>& mdts,
611  const std::vector<const MuonClusterOnTrack*>& clusters, Trk::SegmentCollection* segColl) const {
612  if (mdts.empty()) return;
613 
614  const MdtDriftCircleOnTrack* mdt = mdts.front();
615  if (!mdt) return;
616 
617  bool hasPhiMeasurements = false;
618  Amg::Vector3D gpos = mdt->globalPosition();
619  Amg::Vector3D gdir = gpos.unit();
620  find(gpos, gdir, mdts, clusters, hasPhiMeasurements, segColl);
621  }
622 
623  void DCMathSegmentMaker::find(const std::vector<const Trk::RIO_OnTrack*>& rios1,
624  const std::vector<const Trk::RIO_OnTrack*>& rios2) const {
625  std::vector<const Trk::RIO_OnTrack*> rios = rios1;
626  rios.insert(rios.end(), rios2.begin(), rios2.end());
627  find(rios);
628  }
629 
630  void DCMathSegmentMaker::find(const Trk::TrackRoad& road, const std::vector<std::vector<const MdtDriftCircleOnTrack*> >& mdts,
631  const std::vector<std::vector<const MuonClusterOnTrack*> >& clusters, Trk::SegmentCollection* segColl,
632  bool hasPhiMeasurements, double momentum) const {
633  // copy all mdt hits into one vector
634  std::vector<const MdtDriftCircleOnTrack*> all_mdts;
635  for (const std::vector<const MdtDriftCircleOnTrack*>& circle_vec : mdts) { std::copy(circle_vec.begin(), circle_vec.end(), std::back_inserter(all_mdts)); }
636 
637  // copy all clusters into one vector
638  std::vector<const MuonClusterOnTrack*> all_clus;
639  for ( const std::vector<const MuonClusterOnTrack*>& clus_vec : clusters) { std::copy(clus_vec.begin(), clus_vec.end(), std::back_inserter(all_clus)); }
640 
641  const Amg::Vector3D& gpos = road.globalPosition();
642  const Amg::Vector3D& gdir = road.globalDirection();
643  find(gpos, gdir, all_mdts, all_clus, hasPhiMeasurements, segColl, momentum, road.deltaEta());
644  }
645 
646  double DCMathSegmentMaker::errorScaleFactor(const Identifier& id, double curvature, bool hasPhiMeasurements) const {
647  double scale = 1.;
648  if (!m_curvedErrorScaling) return scale;
649 
650  if (!errorScalingRegion(id)) return scale;
651 
652  double scaleMax = 5.;
653  if (m_curvedErrorScaling && curvature > 2) {
654  scale = std::min(scaleMax, 1. + curvature / 10000);
655  ATH_MSG_DEBUG(" rescaled errors " << scale << " curvature " << curvature);
656  }
657  scale *= 2;
658 
659  // rescale errors is no phi measurement was found
660  if (!hasPhiMeasurements) {
661  double phiScale = 1.;
662  // rescale errors
663  int stRegion = m_idHelperSvc->mdtIdHelper().stationRegion(id);
664  if (stRegion == 0)
665  phiScale = 2.; // inner
666  else if (stRegion == 1)
667  phiScale = 2.5; // extended
668  else if (stRegion == 2)
669  phiScale = 2.5; // middle
670  else
671  phiScale = 3.; // outer
672  scale = std::sqrt(scale*scale + phiScale*phiScale);
673  ATH_MSG_DEBUG(" rescaled error for missing phi road " << scale);
674  }
675 
676  return scale;
677  }
678 
680 
681  {
682  // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus
683  // inner/middle/outer seperation
684 
685  bool isEndcap = m_idHelperSvc->isEndcap(id);
686 
687  if (isEndcap) {
688  std::string stName = m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(id));
689  if (stName[1] == 'I') return true;
690 
691  } else {
692  return true;
693  }
694  return false;
695  }
696 
697  DCMathSegmentMaker::ClusterVecPair DCMathSegmentMaker::create1DClusters(const std::vector<const MuonClusterOnTrack*>& clusters) const {
698  // if empty return
699  if (clusters.empty()) return {};
700  // some useful typedefs...
701 
702  // create a vector to hold the clusters
703  ClusterVec clVec;
704  ClusterVec phiVec;
705  clVec.reserve(clusters.size());
706 
707  for (const MuonClusterOnTrack* clust : clusters) {
708  const Identifier id = clust->identify();
709  const Identifier gasGapId = m_idHelperSvc->gasGapId(id);
710 
711  if (m_idHelperSvc->measuresPhi(id)) {
712  phiVec.push_back(createSpacePoint(gasGapId, nullptr, clust));
713  if (phiVec.back().corrupt()) phiVec.pop_back();
714  } else {
715  clVec.push_back(createSpacePoint(gasGapId, clust, nullptr));
716  if (clVec.back().corrupt()) clVec.pop_back();
717  }
718  }
719 
720  return ClusterVecPair(clVec, phiVec);
721  }
722 
723  DCMathSegmentMaker::ClusterVecPair DCMathSegmentMaker::create2DClusters(const std::vector<const MuonClusterOnTrack*>& clusters) const {
724  // if empty return
725  if (clusters.empty()) return {};
726 
727  ChIdHitMap gasGapHitMap;
728  for (const MuonClusterOnTrack* clus: clusters) {
729  const Identifier id = clus->identify();
730  ATH_MSG_VERBOSE(" new trigger hit " << m_idHelperSvc->toString(id));
731 
732  const Identifier chId = m_idHelperSvc->chamberId(id);
733  const Identifier gasGapId = m_idHelperSvc->gasGapId(id);
734  // eta hits first than phi hits
735  if (!m_idHelperSvc->measuresPhi(id))
736  gasGapHitMap[chId][gasGapId].first.push_back(clus);
737  else
738  gasGapHitMap[chId][gasGapId].second.push_back(clus);
739  }
740 
741  return createSpacePoints(gasGapHitMap);
742  }
743 
745  // vector to store output
746  ClusterVec spacePoints{}, phiVec{};
747  spacePoints.reserve(20);
748  phiVec.reserve(20);
749  // loop over chambers
750  for ( const auto& [id, gasGapHits] : chIdHitMap) {
751  // create clusters per chamber and copy them in to result vector
752  ClusterVecPair cls = createSpacePoints(gasGapHits);
753  std::copy(std::make_move_iterator(cls.first.begin()),
754  std::make_move_iterator(cls.first.end()), std::back_inserter(spacePoints));
755  std::copy(std::make_move_iterator(cls.second.begin()),
756  std::make_move_iterator(cls.second.end()), std::back_inserter(phiVec));
757  }
758 
759  return std::make_pair(std::move(spacePoints), std::move(phiVec));
760  }
761 
763  ClusterVec spacePoints{}, phiVec{};
764  bool isEndcap = m_idHelperSvc->isEndcap((*(gasGapHitMap.begin())).first);
765 
766  ATH_MSG_VERBOSE(" creating Space points for " << gasGapHitMap.size() << " gas gaps ");
767 
768  for (const auto& [gasGapId, etaPhiHits] : gasGapHitMap) {
769  // flag whether phi hits are matched with a eta hit
770  std::vector<bool> flagPhihit(etaPhiHits.second.size(), 0);
771 
772  // store Identifier of previous hit to remove duplicates
773  Identifier prevEtaId;
774 
775  ATH_MSG_VERBOSE(" New gasgap " << m_idHelperSvc->toString(gasGapId) << " neta " << etaPhiHits.first.size() << " nphi "
776  << etaPhiHits.second.size());
777 
778  for (const MuonClusterOnTrack* etaHit : etaPhiHits.first) {
779  // check whether we are not dealing with a duplicate hit
780  if (etaHit->identify() == prevEtaId) continue;
781  prevEtaId = etaHit->identify();
782 
783  ATH_MSG_VERBOSE(" Eta hit " << m_idHelperSvc->toString(etaHit->identify()));
784 
785  if (isEndcap) {
786  // check whether match with phi hits was found
787  bool foundSP = false;
788  Identifier prevPhiId;
789  int phi_idx{-1};
790  for (const MuonClusterOnTrack* phiHit : etaPhiHits.second) {
791  // check for duplicate phi hits
792  ++phi_idx;
793  if (phiHit->identify() == prevPhiId) continue;
794  prevPhiId = phiHit->identify();
795 
796  ATH_MSG_VERBOSE(" Phi hit " << m_idHelperSvc->toString(phiHit->identify()));
797 
798  Cluster2D sp = createTgcSpacePoint(gasGapId, etaHit, phiHit);
799  if (sp.corrupt()) continue;
800  spacePoints.push_back(std::move(sp));
801  // mark as used
802  foundSP = true;
803  flagPhihit[phi_idx] = true;
804  }
805 
806  // add single eta hit if not matching phi hit was found
807  if (!foundSP) {
808  Cluster2D sp = createSpacePoint(gasGapId, etaHit, nullptr);
809  if (sp.corrupt()) continue;
810  spacePoints.push_back(std::move(sp));
811  }
812  } else {
813  Cluster2D sp = createRpcSpacePoint(gasGapId, etaHit, etaPhiHits.second);
814  if (sp.corrupt()) continue;
815  // flag all phi hits, not very elegant, but works
816  flagPhihit = std::vector<bool>(etaPhiHits.second.size(), 1);
817  spacePoints.push_back(std::move(sp));
818  }
819  }
820  if (isEndcap) {
821  // loop over flag vector and add unmatched phi hits to phiVec;
822  Identifier prevPhiId;
823  for (unsigned int i = 0; i < flagPhihit.size(); ++i) {
824  if (flagPhihit[i]) continue;
825 
826  // check for duplicate phi hits
827  if (etaPhiHits.second[i]->identify() == prevPhiId) continue;
828  prevPhiId = etaPhiHits.second[i]->identify();
829 
830  Cluster2D sp = createTgcSpacePoint(gasGapId, nullptr, etaPhiHits.second[i]);
831  if (sp.corrupt()) continue;
832  phiVec.push_back(std::move(sp));
833  }
834  } else if (etaPhiHits.first.empty() && !etaPhiHits.second.empty()) {
835  // if there were no eta hits create one phi spacePoint of all phi hits in gasgap
836  Cluster2D sp = createRpcSpacePoint(gasGapId, nullptr, etaPhiHits.second);
837  if (sp.corrupt()) continue;
838  phiVec.push_back(std::move(sp));
839  }
840  }
841 
842  ATH_MSG_VERBOSE(" Creating space points, number of gas-gaps " << gasGapHitMap.size() << " space points " << spacePoints.size());
843 
844  return std::make_pair(std::move(spacePoints), std::move(phiVec));
845  }
846 
848  const MuonClusterOnTrack* phiHit) const {
849  bool isEndcap = m_idHelperSvc->isEndcap(gasGapId);
850  double error{1.}, lpx{0.}, lpy{0.};
851  // case one hit missing. Take position and error of the available hit
852  if (!etaHit) {
853  if (!phiHit) {
854  ATH_MSG_WARNING("Both eta and phi hits missing");
855  error = 0;
856  } else {
857  lpx = phiHit->localParameters()[Trk::locX];
859  }
860  } else if (!phiHit) {
861  lpx = etaHit->localParameters()[Trk::locX];
863  } else if (etaHit && phiHit) {
864  if (isEndcap) {
865  return createTgcSpacePoint(gasGapId, etaHit, phiHit);
866  } else {
867  std::vector<const MuonClusterOnTrack*> phiVec{phiHit};
868  return createRpcSpacePoint(gasGapId, etaHit, phiVec);
869  }
870  }
871  Identifier detElId = m_idHelperSvc->detElId(gasGapId);
872  if (std::abs(error) < 0.001) {
873  ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId));
874  error = 0.;
875  }
876  return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit);
877  }
878 
880  const MuonClusterOnTrack* etaHit,
881  const MuonClusterOnTrack* phiHit) const {
882  double error{1.}, lpx{0.}, lpy{0.};
883  Identifier detElId = m_idHelperSvc->detElId(gasGapId);
884  // case one hit missing. Take position and error of the available hit
885  if (!etaHit) {
886  lpx = phiHit->localParameters()[Trk::locX];
888  } else if (!phiHit) {
889  lpx = etaHit->localParameters()[Trk::locX];
891  } else if (etaHit && phiHit) {
892  // get orientation angle of strip to rotate back from local frame to strip
893  // copy code from ROT creator
894  const MuonGM::TgcReadoutElement* detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(etaHit->detectorElement());
895  const Amg::Vector3D lSpacePoint = Amg::getRotateZ3D(-90 * Gaudi::Units::deg) * detEl->localSpacePoint(phiHit->identify(),
896  etaHit->globalPosition(),
897  phiHit->globalPosition());
898 
899 
900  lpx = lSpacePoint.x();
901  lpy = lSpacePoint.y();
903  if (error <= std::numeric_limits<double>::epsilon()) {
904  ATH_MSG_WARNING(" Unphysical error assigned for " << m_idHelperSvc->toString(etaHit->identify()));
905  if (etaHit->prepRawData())
906  ATH_MSG_WARNING(" PRD error " << Amg::error(etaHit->prepRawData()->localCovariance(), Trk::locX));
907  }
908  ATH_MSG_DEBUG(" TGC space point: error " << error << " stripWith " << error * M_SQRT2 << std::endl
909  << " " << m_idHelperSvc->toString(etaHit->identify()) << std::endl
910  << " " << m_idHelperSvc->toString(phiHit->identify()));
911  }
912  if (std::abs(error) < 0.001) {
913  ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId));
914  error = 1.;
915  }
916  ATH_MSG_VERBOSE("New space point for "<<m_idHelperSvc->toStringGasGap(gasGapId)<<" at ("<<lpx<<","<<lpy<<")");
917  return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit);
918  }
919 
921  const std::vector<const MuonClusterOnTrack*>& phiHits) const {
922  // create vector to store phi hits after removal of duplicate hits
923  std::vector<const MuonClusterOnTrack*> cleanPhihits;
924  cleanPhihits.reserve(phiHits.size());
925 
926  double error{1.}, lpx{0.}, lpy{0.};
927  // case one hit missing. Take position and error of the available hit
928  if (!etaHit) {
929  lpx = phiHits.front()->localParameters()[Trk::locX];
930  error = Amg::error(phiHits.front()->localCovariance(), Trk::locX);
931  // loop over phi hits, remove duplicate phi hits
932  Identifier prevId;
933  for (const MuonClusterOnTrack* clus : phiHits) {
934  // remove duplicate phi hits
935  if (clus->identify() == prevId) continue;
936  prevId = clus->identify();
937  cleanPhihits.push_back(clus);
938  }
939  } else if (phiHits.empty()) {
940  lpx = etaHit->localParameters()[Trk::locX];
942  } else if (etaHit && !phiHits.empty()) {
943  lpx = etaHit->localParameters()[Trk::locX];
945 
946  ATH_MSG_DEBUG(" RPC space point: error " << error << " stripWith " << error * M_SQRT2 << std::endl
947  << " " << m_idHelperSvc->toString(etaHit->identify()));
948 
949  double minPos{1e9}, maxPos{-1e9};
950  Identifier prevId;
951 
952  // loop over phi hits, calculate average position + cluster width, remove duplicate phi hits
953  for (const MuonClusterOnTrack* phiHit : phiHits) {
954  // remove duplicate phi hits
955  if (phiHit->identify() == prevId) continue;
956  prevId = phiHit->identify();
957 
958  // calculate phi hit position in local eta hit reference frame
959  Amg::Vector2D phiLocPos{Amg::Vector2D::Zero()};
960  if (etaHit->associatedSurface().globalToLocal(phiHit->globalPosition(), phiHit->globalPosition(), phiLocPos)) {
961  lpy = phiLocPos[Trk::locY];
962  minPos = std::min(minPos, lpy);
963  maxPos = std::max(maxPos, lpy);
964  ATH_MSG_DEBUG(" " << m_idHelperSvc->toString(phiHit->identify()));
965  cleanPhihits.push_back(phiHit);
966  }
967  }
968  if (cleanPhihits.size() > 1)
969  ATH_MSG_DEBUG(" multiple phi hits: nhits " << cleanPhihits.size() << " cl width " << maxPos - minPos);
970  } else {
971  ATH_MSG_DEBUG(" ARRRGGG got two empty pointers!!! ");
972  }
973  Identifier detElId = m_idHelperSvc->detElId(gasGapId);
974  if (std::abs(error) < 0.001) {
975  ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId));
976  error = 1.;
977  }
978  return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, !cleanPhihits.empty() ? cleanPhihits : phiHits);
979  }
980 
982  const Amg::Transform3D& gToStation) const {
984 
985  const int chPhi = m_idHelperSvc->mdtIdHelper().stationPhi(chid);
986 
987  // loop over clusters
988  int index{-1};
989  cls.reserve(spVec.size());
990  for (const Cluster2D& clust : spVec) {
991  ++index;
992  const MuonClusterOnTrack* meas = clust.etaHit ? clust.etaHit : clust.phiHit;
993  // construct cluster id
994  const Identifier id = meas->identify();
995  const int measuresPhi = m_idHelperSvc->measuresPhi(id);
996  const int eta = m_idHelperSvc->stationEta(id);
997  const int phi = m_idHelperSvc->stationPhi(id);
998  const int isTgc = m_idHelperSvc->isTgc(id);
999  const int name = isTgc ? m_idHelperSvc->tgcIdHelper().stationName(id) : m_idHelperSvc->rpcIdHelper().stationName(id);
1000  if (!isTgc) {
1001  if (chPhi != phi) {
1002  ATH_MSG_VERBOSE(" Discarding cluster, wrong station phi " << m_idHelperSvc->toString(id));
1003  continue;
1004  }
1005  }
1006  TrkDriftCircleMath::ClusterId clid{name, eta, phi, isTgc, measuresPhi};
1007 
1008  // calculate local cluster position
1009  Amg::Vector3D locPos = gToStation * clust.globalPos;
1010  TrkDriftCircleMath::LocVec2D lp(locPos.y(), locPos.z());
1011 
1012  if (std::abs(lp.y()) > m_maxAssociateClusterDistance) {
1013  ATH_MSG_VERBOSE(" Discarding cluster with large distance from chamber " << m_idHelperSvc->toString(id));
1014  continue;
1015  }
1016  ATH_MSG_VERBOSE(" " << m_idHelperSvc->toString(id) << " clid: " << clid.id() << " central phi "
1017  << meas->detectorElement()->center().phi() << " index " << index);
1018  cls.emplace_back(lp, clust.error, clid, meas, index);
1019  }
1020  return cls;
1021  }
1022 
1023  TrkDriftCircleMath::DCVec DCMathSegmentMaker::createDCVec(const std::vector<const MdtDriftCircleOnTrack*>& mdts, double errorScale,
1024  std::set<Identifier>& chamberSet, double& phimin, double& phimax,
1025  TrkDriftCircleMath::DCStatistics& dcStatistics, const Amg::Transform3D& gToStation,
1026  const Amg::Transform3D& amdbToGlobal) const {
1028  dcs.reserve(mdts.size());
1029  /* ******** Mdt hits ******** */
1030  bool firstMdt = true;
1031 
1032  for (const MdtDriftCircleOnTrack* rot : mdts) {
1033 
1034  Identifier id = rot->identify();
1035  Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id);
1036 
1037  // calculate local AMDB position
1038  Amg::Vector3D locPos = gToStation * rot->prepRawData()->globalPosition();
1039  TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1040 
1041  double r = rot->localParameters()[Trk::locR];
1042  double dr = Amg::error(rot->localCovariance(), Trk::locR) * errorScale;
1043 
1044  // create identifier
1045  TrkDriftCircleMath::MdtId mdtid(m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1,
1046  m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1);
1047 
1048  //
1049  double preciseError = dr;
1050  if (m_usePreciseError) { preciseError = m_preciseErrorScale * (0.23 * std::exp(-std::abs(r) / 6.06) + 0.0362); }
1051  // create new DriftCircle
1052  TrkDriftCircleMath::DriftCircle dc(lpos, r, dr, preciseError, TrkDriftCircleMath::DriftCircle::InTime, mdtid, rot);
1053 
1054  TubeEnds tubeEnds = localTubeEnds(*rot, gToStation, amdbToGlobal);
1055  if (firstMdt) {
1056  phimin = tubeEnds.phimin;
1057  phimax = tubeEnds.phimax;
1058  firstMdt = false;
1059  } else {
1060  updatePhiRanges(tubeEnds.phimin, tubeEnds.phimax, phimin, phimax);
1061  }
1062 
1063  ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id) << " x " << lpos.x() << " y " << lpos.y() << " time "
1064  << rot->driftTime() << " r " << r << " dr " << dr << " phi range " << tubeEnds.phimin << " "
1065  << tubeEnds.phimax<<" precise error "<<preciseError);
1066  dcs.push_back(std::move(dc));
1067 
1068  chamberSet.insert(elId);
1069 
1070  ++dcStatistics[rot->prepRawData()->detectorElement()];
1071  }
1072 
1073  return dcs;
1074  }
1075 
1077  const Amg::Transform3D& gToStation) const {
1078  /* calculate chamber geometry
1079  it takes as input:
1080  distance between the first and second tube in the chamber within a layer along the tube layer (tube distance)
1081  distance between the first tube in the first layer and the first tube in the second layer along the tube layer
1082  (tube stagering) distance between the first and second layer perpendicular to the tube layers (layer distance)
1083  position of the first hit in ml 0 and ml 1 (2D in plane)
1084  total number of multilayers
1085  total number of layers
1086  total number of tubes per layer for each multilayer
1087  an identifier uniquely identifying the chamber
1088  */
1089 
1090  Amg::Vector3D firstTubeMl0{Amg::Vector3D::Zero()};
1091  Amg::Vector3D firstTubeMl1{Amg::Vector3D::Zero()};
1092 
1093  // get id
1094  int eta = m_idHelperSvc->mdtIdHelper().stationEta(chid);
1095  int phi = m_idHelperSvc->mdtIdHelper().stationPhi(chid);
1096  int name = m_idHelperSvc->mdtIdHelper().stationName(chid);
1097 
1099  const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle};
1100  if (!MuonDetMgr) {
1101  ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
1102  return {};
1103  }
1104 
1105  // get detEL for first ml (always there)
1106  const MuonGM::MdtReadoutElement* detEl1 =
1107  MuonDetMgr->getMdtReadoutElement(m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1));
1108  const MuonGM::MdtReadoutElement* detEl2 = nullptr;
1109  int ntube2 = 0;
1110  // number of multilayers in chamber
1111  int nml = detEl1->nMDTinStation();
1112 
1113  // treament of chambers with two ml
1114  if (nml == 2) {
1115  Identifier firstIdml1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 2, 1, 1);
1116  detEl2 = MuonDetMgr->getMdtReadoutElement(firstIdml1);
1117  firstTubeMl1 = gToStation * (detEl2->surface(firstIdml1).center());
1118  ntube2 = detEl2->getNtubesperlayer();
1119  }
1120 
1121  // number of layers and tubes
1122  int nlay = detEl1->getNLayers();
1123  int ntube1 = detEl1->getNtubesperlayer();
1124 
1125  // position first tube in ml 0
1126  Identifier firstIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1);
1127  firstTubeMl0 = gToStation * (detEl1->surface(firstIdml0).center());
1128 
1129  // position second tube in ml 0
1130  Identifier secondIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 2);
1131  Amg::Vector3D secondTubeMl0 = gToStation * (detEl1->surface(secondIdml0).center());
1132 
1133  TrkDriftCircleMath::LocVec2D firstTube0(firstTubeMl0.y(), firstTubeMl0.z());
1134  TrkDriftCircleMath::LocVec2D firstTube1(firstTubeMl1.y(), firstTubeMl1.z());
1135 
1136  // position first tube ml 0 and 1
1137  Identifier firstIdml0lay1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 2, 1);
1138  Amg::Vector3D firstTubeMl0lay1 = gToStation * (detEl1->surface(firstIdml0lay1).center());
1139 
1140  double tubeDist = (secondTubeMl0 - firstTubeMl0).y(); // distance between tube in a given layer
1141  double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).y(); // tube stagering distance
1142  double layDist = (firstTubeMl0lay1 - firstTubeMl0).z(); // distance between layers
1143 
1144  TrkDriftCircleMath::MdtChamberGeometry mdtgeo(chid, m_idHelperSvc.get(), nml, nlay, ntube1, ntube2, firstTube0, firstTube1, tubeDist, tubeStage,
1145  layDist, detEl1->surface().center().theta());
1146 
1147  if (msgLvl(MSG::VERBOSE)) mdtgeo.print(msgStream());
1148 
1149  return mdtgeo;
1150  }
1151 
1154  const TrkDriftCircleMath::ChamberGeometry* multiGeo, const Amg::Transform3D& gToStation, const Amg::Transform3D& amdbToGlobal,
1155  std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec,
1156  std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec) const {
1157  // clear result vectors
1158 
1159  // convert segment parameters + x position from road
1160  const TrkDriftCircleMath::Line& line = segment.line();
1163  if (segment.hasCurvatureParameters()) {
1164  // ml2 segment direction
1165  double ml2phi = line.phi() - segment.deltaAlpha();
1166  TrkDriftCircleMath::LocVec2D ml2dir(std::cos(ml2phi), std::sin(ml2phi));
1167  // ml2 segment position
1168  const TrkDriftCircleMath::LocVec2D ml1LocPos = multiGeo->tubePosition(0, multiGeo->nlay(), 0);
1169  const TrkDriftCircleMath::LocVec2D ml2LocPos = multiGeo->tubePosition(1, 1, 0);
1170  double chamberMidPtY = (ml1LocPos.y() + ml2LocPos.y()) / 2.0;
1171  TrkDriftCircleMath::LocVec2D ml2pos(segment.deltab(), chamberMidPtY);
1172  // construct the new ml2 segment line & transform
1173  const TrkDriftCircleMath::Line ml2line(ml2pos, ml2dir);
1174  TrkDriftCircleMath::TransformToLine tmptoLine(ml2line);
1175  // set the ml2 line
1176  toLineml2 = tmptoLine;
1177  }
1178 
1179  for (TrkDriftCircleMath::DCOnTrack& dcit : segment.dcs()) {
1180  if (dcit.state() == TrkDriftCircleMath::DCOnTrack::Delta) { deltaVec.insert(dcit.rot()->identify()); }
1181 
1182  if (dcit.state() == TrkDriftCircleMath::DCOnTrack::OutOfTime) { outoftimeVec.insert(dcit.rot()->identify()); }
1183 
1184  if (dcit.state() != TrkDriftCircleMath::DCOnTrack::OnTrack) continue;
1185 
1186  const MdtDriftCircleOnTrack* riodc{dcit.rot()};
1187 
1188  // choose which line to use (ml1 or ml2)
1189  TrkDriftCircleMath::TransformToLine toLine = toLineml1;
1190  if (m_idHelperSvc->mdtIdHelper().multilayer(riodc->identify()) == 2) toLine = toLineml2;
1191  // calculate position of hit in line frame
1192  TrkDriftCircleMath::LocVec2D pointOnHit = toLine.toLine(dcit.position());
1193 
1194  // calculate position of hit on line in line frame
1195  TrkDriftCircleMath::LocVec2D pointOnLine(pointOnHit.x(), 0.);
1196 
1197  // transform back to local AMDB coordinates
1198  TrkDriftCircleMath::LocVec2D pointOnLineAMDB = toLine.toLocal(pointOnLine);
1199 
1200  // get position along wire from ROT
1201  Amg::Vector3D posAlong = gToStation * riodc->globalPosition();
1202 
1203  // set yz components
1204  posAlong[1] = pointOnLineAMDB.x();
1205  posAlong[2] = pointOnLineAMDB.y();
1206 
1207  // back to global
1208  Amg::Vector3D mdtGP = amdbToGlobal * posAlong;
1209 
1210  const Trk::StraightLineSurface* surf = dynamic_cast<const Trk::StraightLineSurface*>(&riodc->associatedSurface());
1211  if (!surf) {
1212  ATH_MSG_WARNING(" dynamic cast to StraightLineSurface failed for mdt!!! ");
1213  continue;
1214  }
1215 
1216  // calculate Amg::Vector2D using surf to obtain sign
1218  if (!surf->globalToLocal(mdtGP, gdir, locPos)) ATH_MSG_WARNING(" globalToLocal failed ");
1219 
1220  // calculate side
1222 
1223  std::unique_ptr<MdtDriftCircleOnTrack> nonconstDC;
1224  bool hasT0 = segment.hasT0Shift();
1225  if (!hasT0 || m_mdtCreatorT0.empty()) {
1226  // ATH_MSG_VERBOSE(" recalibrate MDT hit");
1227  nonconstDC.reset(m_mdtCreator->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir));
1228  if (hasT0) ATH_MSG_WARNING("Attempted to change t0 without a properly configured MDT creator tool. ");
1229  } else {
1230  ATH_MSG_VERBOSE(" recalibrate MDT hit with shift " << segment.t0Shift()<<" "<<m_printer->print(*riodc));
1231  nonconstDC.reset(m_mdtCreatorT0->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir, segment.t0Shift()));
1232  }
1233 
1234  if (!nonconstDC) {
1236  continue;
1237  }
1238  ATH_MSG_VERBOSE("Post calibrated hit "<<m_printer->print(*nonconstDC));
1239 
1240  // update the drift radius after recalibration, keep error
1241  TrkDriftCircleMath::DriftCircle new_dc(dcit.position(), std::abs(nonconstDC->driftRadius()), dcit.dr(), dcit.drPrecise(),
1242  dcit.driftState(), dcit.id(),
1243  nonconstDC.get());
1244  TrkDriftCircleMath::DCOnTrack new_dc_on_track(new_dc, dcit.residual(), dcit.errorTrack());
1245  dcit = std::move(new_dc_on_track);
1246 
1247  if (hasT0) {
1248  if (msgLvl(MSG::VERBOSE)) {
1249  double shift = riodc->driftTime() - nonconstDC->driftTime();
1250  ATH_MSG_VERBOSE(" t0 shift " << segment.t0Shift() << " from hit " << shift << " recal " << nonconstDC->driftRadius()
1251  << " t " << nonconstDC->driftTime() << " from fit " << dcit.r() << " old "
1252  << riodc->driftRadius() << " t " << riodc->driftTime());
1253  if (std::abs(std::abs(nonconstDC->driftRadius()) - std::abs(dcit.r())) > 0.1 && nonconstDC->driftRadius() < 19. &&
1254  nonconstDC->driftRadius() > 1.) {
1255  ATH_MSG_WARNING("Detected invalid recalibration after T0 shift");
1256  }
1257  }
1258  }
1259  m_mdtCreator->updateSign(*nonconstDC, side);
1260  double dist = pointOnHit.x();
1261  rioDistVec.emplace_back(dist, std::move(nonconstDC));
1262  }
1263  }
1264 
1265  template <class T> struct IdDataVec {
1266  using Entry = T;
1267  using EntryVec = std::vector<Entry>;
1268 
1269  IdDataVec() = default;
1270  explicit IdDataVec(const Identifier& i) : id(i) {}
1271 
1272  Identifier id{0};
1274  };
1275 
1276  template <class T> struct SortIdDataVec {
1277  bool operator()(const IdDataVec<T>& d1, const IdDataVec<T>& d2) { return d1.id < d2.id; }
1278  };
1279 
1280  struct SortClByPull {
1281  bool operator()(const std::pair<double, DCMathSegmentMaker::Cluster2D>& d1,
1282  const std::pair<double, DCMathSegmentMaker::Cluster2D>& d2) {
1283  return std::abs(d1.first) < std::abs(d2.first);
1284  }
1285  };
1286 
1287  std::pair<std::pair<int, int>, bool> DCMathSegmentMaker::associateClustersToSegment(
1288  const TrkDriftCircleMath::Segment& segment, const Identifier& chid, const Amg::Transform3D& gToStation, ClusterVecPair& spVecs,
1289  double phimin, double phimax, std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec) const {
1291  typedef IdDataVec<GasGapData> ChamberData;
1292  typedef std::vector<ChamberData> ChamberDataVec;
1293  ChamberDataVec chamberDataVec;
1294  bool isEndcap = m_idHelperSvc->isEndcap(chid);
1295 
1296  // keep track of the number of eta/phi hits on the segment
1297  bool refit = false;
1298  std::pair<std::pair<int, int>, bool> netaPhiHits(std::make_pair(0, 0), false);
1299  if (segment.clusters().empty()) return netaPhiHits;
1300 
1301  std::vector<const Trk::MeasurementBase*> phiHits;
1302 
1303  // only refit if there are sufficient phi hits and no multiple phi hits per surface
1304  refit = true;
1305 
1306  // keep track of detector elements which space points added to the track
1307  std::set<Identifier> detElOnSegments;
1308  std::set<MuonStationIndex::PhiIndex> phiIndices;
1309 
1310  ATH_MSG_DEBUG(" Associating clusters: " << segment.clusters().size() << " number of space points " << spVecs.first.size());
1311 
1312  // associate space points and sort them per detector element and gas gap
1313  for (const TrkDriftCircleMath::Cluster& clust : segment.clusters()) {
1314  ATH_MSG_VERBOSE(" accessing cluster: " << clust.index());
1315  const Cluster2D& spacePoint = spVecs.first[clust.index()];
1316 
1317  // skip corrupt space points
1318  if (spacePoint.corrupt()) {
1319  ATH_MSG_DEBUG(" Found corrupt space point: index " << clust.index());
1320  continue;
1321  }
1322  // reject TGC clusters that are not 2D
1323  if (m_reject1DTgcSpacePoints && !spacePoint.is2D() && m_idHelperSvc->isTgc(spacePoint.identify())) {
1324  ATH_MSG_DEBUG(" Rejecting 1D tgc space point " << m_idHelperSvc->toString(spacePoint.identify()));
1325  continue;
1326  }
1327  if (m_assumePointingPhi && spacePoint.is2D() && !checkPhiConsistency(spacePoint.globalPos.phi(), phimin, phimax)) {
1328  ATH_MSG_DEBUG(" Inconsistent phi angle, dropping space point: phi " << spacePoint.globalPos.phi() << " range " << phimin
1329  << " " << phimax);
1330  continue;
1331  }
1332 
1333  std::pair<double, double> resPull = residualAndPullWithSegment(segment, spacePoint, gToStation);
1334 
1335  // if empty or new chamber, add chamber
1336  if (chamberDataVec.empty() || chamberDataVec.back().id != spacePoint.detElId) {
1337  detElOnSegments.insert(spacePoint.detElId);
1338  chamberDataVec.emplace_back(spacePoint.detElId);
1339  MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(spacePoint.detElId);
1340  phiIndices.insert(phiIndex);
1341  }
1342 
1343  // reference to current chamber data
1344  ChamberData& chamber = chamberDataVec.back();
1345 
1346  // if same detector element
1347  if (spacePoint.detElId == chamber.id) {
1348  // if chamber empty or new gas gap, add gasp gap
1349  if (chamber.data.empty() || chamber.data.back().id != spacePoint.gasGapId) {
1350  chamber.data.emplace_back(spacePoint.gasGapId);
1351  }
1352  }
1353 
1354  // reference to current gas gap data
1355  GasGapData& gasGap = chamber.data.back();
1356  gasGap.data.emplace_back(resPull.second, spacePoint);
1357  }
1358 
1359  // calculate the distance between the first and last station, use r in barrel and z in endcaps
1360  double posFirstPhiStation{FLT_MAX}, posLastPhiStation{0.};
1361 
1362  // loop over chambers and create competing ROTs per chamber
1363  for (ChamberData& chamb : chamberDataVec) {
1364  // select best clusters per gas gap in chamber
1365  std::list<const Trk::PrepRawData*> etaClusterVec{}, phiClusterVec{};
1366  std::set<Identifier> etaIds;
1367  // loop over gas gaps
1368  for (GasGapData& gasGap : chamb.data) {
1369  // sort space points by their pull with the segment
1370  std::sort(gasGap.data.begin(), gasGap.data.end(), SortClByPull());
1371 
1372  // select all space points with a pull that is within 1 of the best pull
1373  double bestPull = std::abs(gasGap.data.front().first);
1374 
1375  // count number of associated clusters in gas gap
1376  unsigned int nassociatedSp = 0;
1377  GasGapData::EntryVec::const_iterator cl_it = gasGap.data.begin();
1378  while (cl_it != gasGap.data.end() && std::abs(cl_it->first) - bestPull < 1.) {
1379  const Cluster2D& sp = cl_it->second;
1381  double dist = distanceToSegment(segment, sp.globalPos, gToStation);
1382  ATH_MSG_VERBOSE(" selected space point: " << m_idHelperSvc->toString(sp.identify()) << " pull "
1383  << std::abs(cl_it->first) << " distance to segment " << dist << " phi "
1384  << sp.globalPos.phi());
1385 
1386  // here keep open the option not to create CompetingMuonClustersOnTrack
1387  if (sp.etaHit) {
1388  if (!etaIds.count(sp.etaHit->identify())) {
1389  etaIds.insert(sp.etaHit->identify());
1390 
1392  etaClusterVec.push_back(sp.etaHit->prepRawData());
1393  else {
1394  rioDistVec.emplace_back(dist, sp.etaHit->uniqueClone());
1395  ++netaPhiHits.first.first;
1396  }
1397  }
1398  }
1399  if (!sp.phiHits.empty()) {
1401  // can have multiple phi hits per cluster, loop over phi hits and add them
1402  std::transform(sp.phiHits.begin(), sp.phiHits.end(), std::back_inserter(phiClusterVec),
1403  [](const Muon::MuonClusterOnTrack* clus){
1404  return clus->prepRawData();
1405  });
1406  } else {
1407  // can have multiple phi hits per cluster, loop over phi hits and add them
1408  for (const MuonClusterOnTrack* phi_hit : sp.phiHits) {
1409  rioDistVec.emplace_back(dist, phi_hit->uniqueClone());
1410  ++netaPhiHits.first.second;
1411  phiHits.push_back(phi_hit);
1412 
1413  // calculate position
1414  double phiPos = isEndcap ? std::abs(phi_hit->globalPosition().z()) : phi_hit->globalPosition().perp();
1415  posFirstPhiStation = std::min(phiPos, posFirstPhiStation);
1416  posLastPhiStation = std::max(phiPos, posLastPhiStation);
1417  }
1418  if (sp.phiHits.size() > 1) refit = false;
1419  }
1420  }
1421  ++nassociatedSp;
1422  ++cl_it;
1423  }
1424  // multiple clusters in same gas gap, don't refit
1425  if (!m_createCompetingROTsPhi && nassociatedSp > 1) refit = false;
1426  }
1427 
1429  // create competing ROT for eta hits
1430  if (!etaClusterVec.empty()) {
1431  std::unique_ptr<const CompetingMuonClustersOnTrack> etaCompCluster = m_compClusterCreator->createBroadCluster(etaClusterVec, 0.);
1432  if (!etaCompCluster) {
1433  ATH_MSG_DEBUG(" failed to create competing ETA ROT " << etaClusterVec.size());
1434  } else {
1435  double dist = distanceToSegment(segment, etaCompCluster->globalPosition(), gToStation);
1436  ++netaPhiHits.first.first;
1437  if (msgLvl(MSG::VERBOSE)) {
1438  ATH_MSG_VERBOSE(" selected cluster: " << m_idHelperSvc->toString(etaClusterVec.front()->identify()));
1439  for (unsigned int i = 0; i < etaCompCluster->containedROTs().size(); ++i) {
1441  " content: " << m_idHelperSvc->toString(etaCompCluster->containedROTs()[i]->identify()));
1442  }
1443  }
1444  rioDistVec.emplace_back(dist, std::move(etaCompCluster));
1445  }
1446  }
1447  }
1448 
1450  // create competing ROT for phi hits
1451  if (!phiClusterVec.empty()) {
1452  std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster = m_compClusterCreator->createBroadCluster(phiClusterVec, 0.);
1453  if (!phiCompCluster) {
1454  ATH_MSG_DEBUG(" failed to create competing PHI ROT " << phiClusterVec.size());
1455  } else {
1456  double dist = distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1457  phiHits.push_back(phiCompCluster.get());
1458 
1459  ++netaPhiHits.first.second;
1460 
1461  if (msgLvl(MSG::VERBOSE)) {
1462  ATH_MSG_VERBOSE(" selected cluster: " << m_idHelperSvc->toString(phiClusterVec.front()->identify()));
1463  for (unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) {
1465  " content: " << m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1466  }
1467  }
1468 
1469 
1470  // calculate position
1471  double phiPos = isEndcap ? std::abs(phiCompCluster->globalPosition().z()) :
1472  phiCompCluster->globalPosition().perp();
1473  posFirstPhiStation = std::min(phiPos,posFirstPhiStation);
1474  posLastPhiStation = std::max(phiPos,posLastPhiStation);
1475  rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1476 
1477  }
1478  }
1479  }
1480  }
1481 
1482  // add phi hits that were not associated with an eta hit (only in barrel)
1483  if ((!spVecs.second.empty() || m_recoverBadRpcCabling) && m_addUnassociatedPhiHits && !isEndcap) {
1485 
1486  std::map<Identifier, std::list<const Trk::PrepRawData*> > phiClusterMap;
1487 
1488  std::set<const MuonClusterOnTrack*> selectedClusters;
1489  std::vector<const Cluster2D*> phiClusters;
1490  phiClusters.reserve(spVecs.second.size());
1491 
1492  // create lists of PrepRawData per detector element
1493  for (const Cluster2D& phi_clus :spVecs.second) {
1494  if (!phi_clus.phiHit || phi_clus.corrupt()) {
1495  ATH_MSG_WARNING(" phi clusters without phi hit!!");
1496  continue;
1497  }
1498  phiClusters.push_back(&phi_clus);
1499  selectedClusters.insert(phi_clus.phiHit);
1500  }
1501 
1502  unsigned int recoveredUnassociatedPhiHits(0);
1503  if (m_recoverBadRpcCabling) {
1504  // now loop over 2D space points and add the phi hits to the list if the detEl is not yet added to the
1505  // segment
1506  for (const Cluster2D& rpc_clust : spVecs.first) {
1507  // skip clusters without phi hit
1508  if (!rpc_clust.phiHit || rpc_clust.corrupt()) continue;
1509 
1510  // skip clusters in detector elements that are already associated (ok as this is only done for RPC)
1511  if (detElOnSegments.count(rpc_clust.detElId)) continue;
1512 
1514  // skip clusters in detector layer
1515  if (phiIndices.count(phiIndex)) continue;
1516 
1517  bool wasFound = false;
1518  for (const MuonClusterOnTrack* phi_hit : rpc_clust.phiHits) {
1519  // now to avoid duplicate also skip if the given ROT is already in the list
1520  if (!selectedClusters.insert(phi_hit).second) {
1521  // flag as found
1522  wasFound = true;
1523 
1524  // just because I'm paranoid, remove the hits from this cluster that were already inserted up to
1525  // here
1526  for (const MuonClusterOnTrack* erase_me : rpc_clust.phiHits) {
1527  if (erase_me == phi_hit) break;
1528  selectedClusters.erase(erase_me);
1529  }
1530  break;
1531  }
1532  }
1533  if (wasFound) continue;
1534 
1535  // if we get here we should add the hit
1536  phiClusters.push_back(&rpc_clust);
1537  ++recoveredUnassociatedPhiHits;
1538  }
1539  }
1540 
1541  unsigned int addedPhiHits(0);
1542  for (const Cluster2D* phi_clus : phiClusters) {
1543  const Identifier& detElId = phi_clus->detElId;
1544 
1545  // check that detector element is not already added to segment
1546  if (detElOnSegments.count(detElId)) continue;
1547 
1548  MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(detElId);
1549  // skip clusters in detector layer
1550  if (phiIndices.count(phiIndex)) continue;
1551 
1552  // calculate local cluster position
1553  Amg::Vector3D locPos = gToStation * phi_clus->globalPos;
1554 
1555  // calculate intersect of segment with cluster
1556  TrkDriftCircleMath::Cluster cl(TrkDriftCircleMath::LocVec2D(locPos.y(), locPos.z()), 1.);
1557  double residual = resWithSegment.residual(cl);
1558  double segError = std::sqrt(resWithSegment.trackError2(cl));
1559  const MuonGM::RpcReadoutElement* detEl = dynamic_cast<const MuonGM::RpcReadoutElement*>(phi_clus->phiHit->detectorElement());
1560  if (!detEl) {
1561  ATH_MSG_WARNING("found RPC prd without RpcReadoutElement");
1562  continue;
1563  }
1564 
1565  // perform bound check
1566  double stripLength = detEl->StripLength(1);
1567  bool inBounds = std::abs(residual) < 0.5 * stripLength + 2. + segError;
1568  if (msgLvl(MSG::DEBUG)) {
1569  ATH_MSG_DEBUG(" Unassociated " << m_idHelperSvc->toString(phi_clus->phiHit->identify()) << " pos x " << cl.position().x()
1570  << " pos y " << cl.position().y() << " : residual " << residual << " strip half length "
1571  << 0.5 * stripLength << " segment error " << segError);
1572  if (inBounds)
1573  ATH_MSG_DEBUG(" inBounds");
1574  else
1575  ATH_MSG_DEBUG(" outBounds");
1576  }
1577  if (inBounds) {
1578  // can have multiple phi hits per cluster, loop over phi hits and add them
1579  std::list<const Trk::PrepRawData*>& cham_hits{phiClusterMap[detElId]};
1580  std::transform(phi_clus->phiHits.begin(), phi_clus->phiHits.end(), std::back_inserter(cham_hits),
1581  [](const MuonClusterOnTrack* clus){
1582  return clus->prepRawData();
1583  });
1584  }
1585  }
1586 
1587  // loop over detector elements and created competing ROTs
1588  for (const auto& [phi_id, prds] : phiClusterMap) {
1589  if (prds.empty()) {
1590  ATH_MSG_WARNING(" chamber without phi hits " << m_idHelperSvc->toString(phi_id));
1591  continue;
1592  }
1593 
1594  std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster = m_compClusterCreator->createBroadCluster(prds, 0.);
1595  if (!phiCompCluster) {
1596  ATH_MSG_DEBUG(" failed to create competing PHI ROT " << prds.size());
1597  } else {
1598  double dist = distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1599 
1600  if (std::abs(dist) > m_maxAssociateClusterDistance) {
1601 
1602  ATH_MSG_VERBOSE(" rejected unassociated cluster: " << m_idHelperSvc->toString(prds.front()->identify())
1603  << " distance to segment " << dist);
1604  continue;
1605  }
1606  phiHits.push_back(phiCompCluster.get());
1607  ++netaPhiHits.first.second;
1608  ++addedPhiHits;
1609  if (msgLvl(MSG::VERBOSE)) {
1610  ATH_MSG_VERBOSE(" selected unassociated cluster: " << m_idHelperSvc->toString(prds.front()->identify())
1611  << " distance to segment " << dist);
1612  for (unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) {
1614  " content: " << m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1615  }
1616  }
1617  rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1618  }
1619  }
1620  ATH_MSG_VERBOSE("Added " << addedPhiHits << " unass phi hits out of " << spVecs.second.size()
1621  << " phi hits without eta hit and " << recoveredUnassociatedPhiHits << " with unassociated eta hit ");
1622  }
1623 
1624  // calculate distance between first and last phi trigger hit, refit if there is a good constraint on phi
1625  double phiDistanceMax = posLastPhiStation - posFirstPhiStation;
1626  if (isEndcap && phiDistanceMax < 1000.)
1627  refit = false;
1628  else if (phiDistanceMax < 400.)
1629  refit = false;
1630 
1631  netaPhiHits.second = refit;
1632  return netaPhiHits;
1633  }
1634 
1636  const Amg::Transform3D& gToStation) {
1637  const TrkDriftCircleMath::Line& line = segment.line();
1639  double cos_sinLine = cot(line.phi());
1640 
1641  // calculate local AMDB position
1642  Amg::Vector3D locPos = gToStation * hitPos;
1643 
1644  TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1645 
1646  // calculate distance of segment to measurement surface
1647  double delta_y = lpos.y() - line.position().y();
1648 
1649  // calculate position of hit in line frame
1650  TrkDriftCircleMath::LocVec2D lineSurfaceIntersect(delta_y * cos_sinLine + line.position().x(), lpos.y());
1651 
1652  // calculate position of hit in line frame
1653  TrkDriftCircleMath::LocVec2D pointOnHit = toLine.toLine(lineSurfaceIntersect);
1654 
1655  return pointOnHit.x();
1656  }
1657 
1659  std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec) {
1660  // sort hits according to they distance to the segment position
1661  std::sort(rioDistVec.begin(), rioDistVec.end(), SortByDistanceToSegment());
1662 
1664  rioVec.reserve(rioDistVec.size());
1665  for (std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) { rioVec.push_back(std::move(rdit.second)); }
1666  rioDistVec.clear();
1667  return rioVec;
1668  }
1669 
1671  const Cluster2D& spacePoint,
1672  const Amg::Transform3D& gToStation) {
1673  const TrkDriftCircleMath::Line& line = segment.line();
1674  double cos_sinLine = cot(line.phi());
1675 
1676  // calculate sp postion in AMDB reference frame
1677  Amg::Vector3D locPos = gToStation * spacePoint.globalPos;
1678  TrkDriftCircleMath::LocVec2D lpos(locPos.y(), locPos.z());
1679 
1680  // calculate distance of segment to measurement surface
1681  double delta_y = lpos.y() - line.position().y();
1682 
1683  // calculate position of hit in line frame
1684  TrkDriftCircleMath::LocVec2D lineSurfaceIntersect(delta_y * cos_sinLine + line.position().x(), lpos.y());
1685 
1686  // calculate position of hit in line frame
1687  double residual = lpos.x() - lineSurfaceIntersect.x();
1688  double pull = residual / spacePoint.error;
1689  return std::make_pair(residual, pull);
1690  }
1691 
1692  std::vector<Identifier> DCMathSegmentMaker::calculateHoles(const EventContext& ctx,
1693  Identifier chid, const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, bool hasMeasuredCoordinate, std::set<Identifier>& deltaVec,
1694  std::set<Identifier>& outoftimeVec, const std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec) const {
1695  // calculate crossed tubes
1697  if (!InterSectSvc.isValid()) {
1698  ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
1699  return {};
1700  }
1701  const MuonStationIntersect intersect = InterSectSvc->tubesCrossedByTrack(chid, gpos, gdir);
1702  const MuonGM::MuonDetectorManager* MuonDetMgr = InterSectSvc->detMgr();
1703 
1704  // set to identify the hit on the segment
1705  std::set<Identifier> hitsOnSegment, chambersOnSegment;
1706  int firstLayer{-1}, lastLayer{-1};
1707  for (const std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) {
1708  const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rdit.second.get());
1709  if (!mdt) continue;
1710  const Identifier id = mdt->identify();
1711  int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1);
1712  if (firstLayer == -1)
1713  firstLayer = layer;
1714  else
1715  lastLayer = layer;
1716 
1717  hitsOnSegment.insert(id);
1718  chambersOnSegment.insert(m_idHelperSvc->chamberId(id));
1719  }
1720 
1721  // cross check for cosmic case
1722  if (firstLayer > lastLayer) { std::swap(firstLayer, lastLayer); }
1723  ATH_MSG_VERBOSE(" Tube layer ranges: " << firstLayer << " -- " << lastLayer << " crossed tubes "
1724  << intersect.tubeIntersects().size());
1725  // clear hole vector
1726  std::vector<Identifier> holeVec;
1727  for (const MuonTubeIntersect& tint : intersect.tubeIntersects()) {
1728  if (!chambersOnSegment.count(m_idHelperSvc->chamberId(tint.tubeId))) {
1729  ATH_MSG_VERBOSE(" chamber not on segment, not counting tube " << tint.rIntersect << " l " << tint.xIntersect << " "
1730  << m_idHelperSvc->toString(tint.tubeId));
1731  continue;
1732  }
1733 
1734  const Identifier& id = tint.tubeId;
1735  int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1);
1736 
1737  bool notBetweenHits = layer < firstLayer || layer > lastLayer;
1738  double distanceCut = hasMeasuredCoordinate ? -20 : -200.;
1739  double innerRadius = MuonDetMgr->getMdtReadoutElement(id)->innerTubeRadius();
1740  if (notBetweenHits && (std::abs(tint.rIntersect) > innerRadius || (!m_allMdtHoles && tint.xIntersect > distanceCut))) {
1741  ATH_MSG_VERBOSE(" not counting tube: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1742  << " " << m_idHelperSvc->toString(tint.tubeId));
1743  continue;
1744  }
1745  // check whether there is a hit in this tube
1746  if (hitsOnSegment.count(tint.tubeId)) {
1747  ATH_MSG_VERBOSE(" tube on segment: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1748  << " " << m_idHelperSvc->toString(tint.tubeId));
1749  continue;
1750  }
1751  // check whether there is a delta electron in this tube
1752  if (m_removeDeltas) {
1753  if (deltaVec.count(tint.tubeId)) {
1754  ATH_MSG_VERBOSE(" removing delta, distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect
1755  << " " << m_idHelperSvc->toString(tint.tubeId));
1756  continue;
1757  }
1758 
1759  const MdtPrepData* prd = findMdt(ctx, id);
1760  if (prd && std::abs(prd->localPosition()[Trk::locR]) < std::abs(tint.rIntersect)) {
1761  ATH_MSG_VERBOSE(" found and removed delta, distance to wire " << tint.rIntersect << " dist to tube end "
1762  << tint.xIntersect << " "
1763  << m_idHelperSvc->toString(tint.tubeId));
1764  continue;
1765  }
1766  }
1767  ATH_MSG_VERBOSE((outoftimeVec.count(tint.tubeId) ? "Out-of-time" : "hole") << " distance to wire "
1768  << tint.rIntersect << " dist to tube end " << tint.xIntersect << " "
1769  << m_idHelperSvc->toString(tint.tubeId)<<(notBetweenHits ? "outside hits" : "between hits"));
1770 
1771  holeVec.push_back(tint.tubeId);
1772  }
1773  return holeVec;
1774  }
1775 
1776  const MdtPrepData* DCMathSegmentMaker::findMdt(const EventContext& ctx, const Identifier& id) const {
1777  IdentifierHash colHash;
1778  if (m_idHelperSvc->mdtIdHelper().get_module_hash(m_idHelperSvc->chamberId(id), colHash)){
1779  ATH_MSG_VERBOSE("Invalid Mdt identifier "<<m_idHelperSvc->toString(id));
1780  return nullptr;
1781  }
1783  if (!MdtCont.isValid()) {
1784  ATH_MSG_WARNING("Cannot retrieve MdtPrepDataContainer ");
1785  return nullptr;
1786  }
1787  const MdtPrepDataCollection* collptr = MdtCont->indexFindPtr(colHash);
1788  if (!collptr) return nullptr;
1789  for (const MdtPrepData* prd : *collptr) {
1790  if (prd->identify() == id) return prd;
1791  }
1792  return nullptr;
1793  }
1794 
1796  const std::vector<const MdtDriftCircleOnTrack*>& mdts) const {
1797  int hitsInChamberWithMostHits = 0;
1798  std::map<Identifier, int> hitsPerChamber;
1799  int currentSector = -1;
1800  const MdtDriftCircleOnTrack* rotInChamberWithMostHits = nullptr;
1801 
1802  // loop over all MDTs and count number of MDTs per chamber
1803  for (const MdtDriftCircleOnTrack* rot : mdts) {
1804  if (!rot) {
1805  ATH_MSG_WARNING(" rot not a MdtDriftCircleOnTrack ");
1806  continue;
1807  }
1808  Identifier chId = m_idHelperSvc->chamberId(rot->identify());
1809  int sector = m_idHelperSvc->sector(chId);
1810  if (currentSector == -1) {
1811  currentSector = sector;
1812  } else if (sector != currentSector) {
1813  return nullptr;
1814  }
1815  int& hitsInCh = hitsPerChamber[chId];
1816  ++hitsInCh;
1817  if (hitsInCh > hitsInChamberWithMostHits) {
1818  hitsInChamberWithMostHits = hitsInCh;
1819  rotInChamberWithMostHits = rot;
1820  }
1821  }
1822  return rotInChamberWithMostHits;
1823  }
1824 
1825  bool DCMathSegmentMaker::checkBoundsInXZ(double xline, double zline, double dXdZ,
1826  const std::vector<DCMathSegmentMaker::HitInXZ>& hits) const {
1827  bool ok = true;
1828 
1829  // look over hits and check whether all are in bounds
1830  for (const HitInXZ& hit : hits) {
1831  bool outBounds = false;
1832  double locExX = xline + dXdZ * (hit.z - zline);
1833  if (hit.isMdt && (locExX < hit.xmin - 1. || locExX > hit.xmax + 1.)) {
1834  ok = false;
1835  outBounds = true;
1836  if (!msgLvl(MSG::DEBUG)) break;
1837  }
1838 
1839  if (outBounds && msgLvl(MSG::DEBUG)) {
1840  ATH_MSG_DEBUG(" " << std::setw(65) << m_idHelperSvc->toString(hit.id) << " pos (" << std::setw(6) << (int)hit.x << ","
1841  << std::setw(6) << (int)hit.z << ") ex pos " << std::setw(6) << (int)locExX << " min " << std::setw(6)
1842  << (int)hit.xmin << " max " << std::setw(6) << (int)hit.xmax << " phimin " << std::setw(6)
1843  << hit.phimin << " phimax " << std::setw(6) << hit.phimax << " outBounds, cross-check");
1844  }
1845  }
1846  return ok;
1847  }
1848 
1850  Trk::LocalDirection& segLocDir, Trk::PlaneSurface& surf,
1851  const std::vector<const Trk::MeasurementBase*>& rots, double seg_phimin,
1852  double seg_phimax) const {
1853  bool hasUpdated = false;
1854 
1855  const Amg::Transform3D& segmentToGlobal = surf.transform();
1856  Amg::Transform3D gToSegment = surf.transform().inverse();
1857  Amg::Vector3D ldir = gToSegment * gdir;
1858 
1859  // ensure that we can extrapolate
1860  if (ldir.z() < 0.0001) return false;
1861 
1862  double dXdZ = ldir.x() / ldir.z();
1863  Amg::Vector3D lsegPos = gToSegment * gpos;
1864  double xline = lsegPos.x();
1865  double zline = lsegPos.z();
1866  ATH_MSG_VERBOSE(" Associated hits " << rots.size() << " angleXZ " << 90. * segLocDir.angleXZ() / (M_PI_2) << " dXdZ " << dXdZ
1867  << " seg Pos (" << xline << " " << zline << ") " << segLocPos);
1868 
1869  std::vector<HitInXZ> hits;
1870  hits.reserve(rots.size());
1871 
1872  unsigned int nphiHits(0);
1873  const HitInXZ* firstPhiHit{nullptr}, *lastPhiHit{nullptr};
1874 
1875  for (const Trk::MeasurementBase* meas : rots) {
1876  Identifier id = m_edmHelperSvc->getIdentifier(*meas);
1877  if (!id.is_valid()) continue;
1879  double lxmin{0}, lxmax{0}, phimin{0}, phimax{0};
1880  bool isMdt = m_idHelperSvc->isMdt(id);
1881  bool measuresPhi = m_idHelperSvc->measuresPhi(id);
1882  if (isMdt) {
1883  lpos.setZero();
1884  const MdtDriftCircleOnTrack* mdt = static_cast<const MdtDriftCircleOnTrack*>(meas);
1885  TubeEnds tubeEnds = localTubeEnds(*mdt, gToSegment, segmentToGlobal);
1886 
1887  lxmin = tubeEnds.lxmin;
1888  lxmax = tubeEnds.lxmax;
1889  phimin = tubeEnds.phimin;
1890  phimax = tubeEnds.phimax;
1891  } else {
1892  lpos = gToSegment * meas->globalPosition();
1893  lxmin = lpos.x() - 5 * Amg::error(meas->localCovariance(), Trk::locX);
1894  lxmax = lpos.x() + 5 * Amg::error(meas->localCovariance(), Trk::locX);
1895 
1896  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1897  if (!measuresPhi) {
1898  if (crot) {
1899  const MuonGM::RpcReadoutElement* detEl =
1900  dynamic_cast<const MuonGM::RpcReadoutElement*>(crot->containedROTs().front()->prepRawData()->detectorElement());
1901  if (detEl) {
1902  // perform bound check
1903  double stripLength = detEl->StripLength(0);
1904  lxmin = lpos.x() - 0.5 * stripLength;
1905  lxmax = lpos.x() + 0.5 * stripLength;
1906  }
1907  }
1908  Amg::Vector3D locPosition = lpos;
1909  locPosition[0] = lxmin;
1910  Amg::Vector3D globalPos = segmentToGlobal * locPosition;
1911  double phi1 = globalPos.phi();
1912 
1913  locPosition[0] = lxmax;
1914  globalPos = segmentToGlobal * locPosition;
1915  double phi2 = globalPos.phi();
1916  phimin = std::min(phi1, phi2);
1917  phimax = std::max(phi1, phi2);
1918 
1919  } else {
1920  if (m_idHelperSvc->isTgc(id)) {
1921  // need some special tricks for TGC phi hits as their reference plane can be rotated
1922  // with respect to the MDT frame
1923 
1924  // get orientation angle of strip to rotate back from local frame to strip
1925  // copy code from ROT creator
1926  int stripNo = m_idHelperSvc->tgcIdHelper().channel(id);
1927  int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id);
1928  if (!crot) {
1929  ATH_MSG_WARNING("dynamic cast failed for CompetingMuonClustersOnTrack");
1930  continue;
1931  }
1932  auto detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(crot->containedROTs().front()->prepRawData()->detectorElement());
1933 
1934  // transform the two points inth
1935  const Amg::Vector3D segFrame_StripDir = gToSegment.linear()* detEl->stripDir(gasGap, stripNo);
1936  const Amg::Vector3D segFrame_stripPos = gToSegment * detEl->channelPos(id);
1937 
1938  lpos = segFrame_stripPos +
1939  Amg::intersect<3>(lsegPos, ldir, segFrame_stripPos, segFrame_StripDir).value_or(0) * segFrame_StripDir;
1940 
1941  ATH_MSG_VERBOSE(" In seg frame: phi pos " << Amg::toString(lsegPos)
1942  << " shifted pos " << Amg::toString(segFrame_StripDir)
1943  << " intersect with segment " << Amg::toString(lpos));
1944  }
1945  Amg::Vector3D globalPos = segmentToGlobal * lpos;
1946  phimin = globalPos.phi();
1947  phimax = phimin;
1948 
1949  // check whether phi is consistent with segment phi range
1950  bool phiOk = checkPhiConsistency(phimin, seg_phimin, seg_phimax);
1951  if (!phiOk) {
1952  ATH_MSG_DEBUG(" Inconsistent phi " << phimin << " range " << seg_phimin << " " << seg_phimax);
1953  }
1954  }
1955  }
1956 
1957  hits.emplace_back(id, isMdt, measuresPhi, lpos.x(), lpos.z(), lxmin, lxmax, phimin, phimax);
1958  if (measuresPhi) {
1959  ++nphiHits;
1960  if (!firstPhiHit)
1961  firstPhiHit = &hits.back();
1962  else {
1963  double distPhiHits = std::abs(firstPhiHit->z - hits.back().z);
1964  if (distPhiHits > 500.) {
1965  lastPhiHit = &hits.back();
1966  } else {
1967  // not count this phi hit
1968  --nphiHits;
1969  ATH_MSG_DEBUG(" close phi hits, distance " << distPhiHits);
1970  }
1971  }
1972  }
1973  if (msgLvl(MSG::VERBOSE)) {
1974  double locExX = xline + dXdZ * (lpos.z() - zline);
1975  ATH_MSG_VERBOSE(" " << std::setw(65) << m_idHelperSvc->toString(id) << " pos (" << std::setw(6) << (int)lpos.x() << ","
1976  << std::setw(6) << (int)lpos.z() << ") ex pos " << std::setw(6) << (int)locExX << " min "
1977  << std::setw(6) << (int)lxmin << " max " << std::setw(6) << (int)lxmax << " phimin " << std::setw(6)
1978  << phimin << " phimax " << std::setw(6) << phimax);
1979  if (lpos.x() < lxmin || lpos.x() > lxmax) ATH_MSG_VERBOSE(" outBounds");
1980  }
1981  }
1982 
1983  if (nphiHits == 1) {
1984  if (!firstPhiHit) {
1985  ATH_MSG_WARNING(" Pointer to first phi hit not set, this should not happen! ");
1986  } else {
1987  if (xline != firstPhiHit->x) {
1988  hasUpdated = true;
1989 
1990  // use phi position of the phi hit
1991  xline = firstPhiHit->x;
1992  zline = firstPhiHit->z;
1993 
1994  if (m_assumePointingPhi) {
1995  Amg::Vector3D ipLocPos = gToSegment.translation();
1996  ATH_MSG_VERBOSE(" IP position in local frame " << ipLocPos);
1997 
1998  double dz = ipLocPos.z() - zline;
1999  if (std::abs(dz) > 0.001) {
2000  ATH_MSG_VERBOSE(" hit (" << xline << "," << zline << ") IP (" << ipLocPos.x() << "," << ipLocPos.z()
2001  << ") dXdZ " << (ipLocPos.x() - xline) / dz << " old " << dXdZ);
2002  dXdZ = (ipLocPos.x() - xline) / dz;
2003  }
2004  }
2005  }
2006  }
2007  } else if (nphiHits == 2) {
2008  if (!firstPhiHit || !lastPhiHit) {
2009  ATH_MSG_WARNING(" Pointer to one of the two phi hit not set, this should not happen! ");
2010  } else {
2011  double dz = lastPhiHit->z - firstPhiHit->z;
2012  // use phi position of the first hit
2013  xline = firstPhiHit->x;
2014  zline = firstPhiHit->z;
2015  if (std::abs(dz) > 300.) {
2016  double dx = lastPhiHit->x - firstPhiHit->x;
2017  hasUpdated = true;
2018 
2019  // if the two hits are far enough apart, also use the direction of the line connecting the two hits.
2020  dXdZ = dx / dz;
2021  }
2022  }
2023  } else {
2024  // in all other cases just rotate until the MDTs are ok
2025  }
2026 
2027  if (hasUpdated) {
2028  // move segment to position of phi hit
2029  double segX = xline - dXdZ * zline;
2030 
2031  // finally check whether now everything is in bounds
2032  bool ok = checkBoundsInXZ(segX, 0., dXdZ, hits);
2033  if (!ok) {
2034  // give WARNING and give up for now
2035  ATH_MSG_DEBUG("still several out of bounds hits after rotation: posx(" << segX << ") dXdZ " << dXdZ
2036  << " keeping old result ");
2037  }
2038 
2039  // update segment parameters
2040  double alphaYZ = segLocDir.angleYZ();
2041  double alphaXZ = std::atan2(1, dXdZ);
2042 
2043  segLocPos[Trk::locX] = segX;
2044  segLocDir = Trk::LocalDirection(alphaXZ, alphaYZ);
2045  }
2046  return hasUpdated;
2047  }
2048 
2050  const Amg::Transform3D& segmentToG) const {
2051  TubeEnds tubeEnds;
2052  const Identifier& id = mdt.identify();
2053  Amg::Vector3D lpos = gToSegment * mdt.prepRawData()->globalPosition();
2054 
2055  // use readout and hv side as the surface frame is not that of the chamber
2056  Amg::Vector3D lropos = gToSegment * mdt.prepRawData()->detectorElement()->ROPos(id);
2057  Amg::Vector3D lhvpos = lpos + (lpos - lropos);
2058 
2059  // rescale to correctly take into account active tube length
2060  double tubeLen = (lropos - lhvpos).mag();
2061  double activeTubeLen =
2062  mdt.detectorElement()->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id), m_idHelperSvc->mdtIdHelper().tube(id));
2063  double scaleFactor = activeTubeLen / tubeLen;
2064  lropos[0] = scaleFactor * lropos.x();
2065  lhvpos[0] = scaleFactor * lhvpos.x();
2066 
2067  tubeEnds.lxmin = std::min(lropos.x(), lhvpos.x());
2068  tubeEnds.lxmax = std::max(lropos.x(), lhvpos.x());
2069 
2070  Amg::Vector3D ropos = segmentToG * lropos;
2071  Amg::Vector3D hvpos = segmentToG * lhvpos;
2072  const double phiRO = ropos.phi();
2073  const double phiHV = hvpos.phi();
2074  tubeEnds.phimin = std::min(phiRO, phiHV);
2075  tubeEnds.phimax = std::max(phiRO, phiHV);
2076  return tubeEnds;
2077  }
2078 
2079  void DCMathSegmentMaker::updatePhiRanges(double phiminNew, double phimaxNew, double& phiminRef, double& phimaxRef) {
2080  // check whether we are at the boundary where phi changes sign
2081  if (phiminRef * phimaxRef < 0.) {
2082  if (phiminRef < -1.1) {
2083  if (phiminRef > phiminNew) phiminRef = phiminNew;
2084  if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2085  } else {
2086  if (phiminRef < phiminNew) phiminRef = phiminNew;
2087  if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2088  }
2089  } else {
2090  // if not life is 'easy'
2091  if (phiminRef < 0.) {
2092  if (phiminRef < phiminNew) phiminRef = phiminNew;
2093  if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2094  } else {
2095  if (phiminRef > phiminNew) phiminRef = phiminNew;
2096  if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2097  }
2098  }
2099  }
2100 
2101  bool DCMathSegmentMaker::checkPhiConsistency(double phi, double phimin, double phimax) const {
2102  // only if assuming pointing phi
2103  if (!m_assumePointingPhi) return true;
2104 
2105  bool phiOk = true;
2106  double offset = 0.05;
2107  if (phimin * phimax < 0.) {
2108  if (phi < 0.) {
2109  if (phi > -1.1) {
2110  if (phi < phimin - offset) phiOk = false;
2111  } else {
2112  if (phi > phimin + offset) phiOk = false;
2113  }
2114  } else {
2115  if (phi > 1.1) {
2116  if (phi < phimax - offset) phiOk = false;
2117  } else {
2118  if (phi > phimax + offset) phiOk = false;
2119  }
2120  }
2121  } else {
2122  if (phi < phimin - offset || phi > phimax + offset) phiOk = false;
2123  }
2124  return phiOk;
2125  }
2126 
2128  bool isCurvedSegment) const {
2129  // Local direction along precision measurement (0, dy, dz)
2130  Trk::LocalDirection segLocDirs(M_PI_2, linephi);
2131  Amg::Vector3D gdirs;
2132  surf.localToGlobalDirection(segLocDirs, gdirs);
2133  // Local direction in plane (1,0,0)
2134  Trk::LocalDirection segLocDiro(0., M_PI_2);
2135  Amg::Vector3D gdiro;
2136  surf.localToGlobalDirection(segLocDiro, gdiro);
2137 
2138  // recalculate the value of the local XZ angle for the give YZ angle of the segment such that the global phi
2139  // direction remains unchanged
2140  double dx = std::sin(gdirs.theta()) * std::cos(gdirs.phi());
2141  double dy = std::sin(gdirs.theta()) * std::sin(gdirs.phi());
2142  double dz = std::cos(gdirs.theta());
2143 
2144  // vector gdiro
2145 
2146  double dxo = std::sin(gdiro.theta()) * std::cos(gdiro.phi());
2147  double dyo = std::sin(gdiro.theta()) * std::sin(gdiro.phi());
2148  double dzo = std::cos(gdiro.theta());
2149 
2150  // solve system real direction = A * gdir + B * gdiro
2151  // phi global constraint: (1)*sin(phi road) - (2)*cos(phi road) = 0
2152  // ( A * dx + B * dxo ) sin (phi ) - (A * dy + B *dyo ) cos (phi) = 0
2153  // A ( dx sin - dy cos ) + B (dx0 sin -dy0 cos) = A * a0 + B * b0 = 0
2154  // psi = atan (-b0 , a0)
2155 
2156  double a0 = dx * std::sin(roaddir.phi()) - dy * std::cos(roaddir.phi());
2157  double b0 = dxo * std::sin(roaddir.phi()) - dyo * std::cos(roaddir.phi());
2158  if (b0 < 1e-8 && b0 > 0) b0 = 1e-8;
2159  if (b0 > -1e-8 && b0 < 0) b0 = -1e-8;
2160  double dxn = dx - a0 * dxo / b0;
2161  double dyn = dy - a0 * dyo / b0;
2162  double dzn = dz - a0 * dzo / b0;
2163  double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn);
2164 
2165  // flip the sign if the direction NOT parallel to road
2166  if (m_assumePointingPhi) {
2167  if (dxn * roaddir.x() + dyn * roaddir.y() + dzn * roaddir.z() < 0.) { norm = -norm; }
2168  } else {
2169  if (dxn * roaddir.x() + dyn * roaddir.y() < 0.) { norm = -norm; }
2170  }
2171 
2172  if (isCurvedSegment) norm = norm / 2.;
2173 
2174  //
2175  // Follow segment fit direction
2176  //
2177  dxn = dxn / norm;
2178  dyn = dyn / norm;
2179  dzn = dzn / norm;
2180 
2181  return Amg::Vector3D(dxn, dyn, dzn);
2182  }
2183 } // namespace Muon
MdtMultiChamberGeometry.h
Muon::MuonSegmentQuality
Definition: MuonSegmentQuality.h:34
Trk::TrackRoad
Encapsulates the information required by the find() method of the muon segment makers.
Definition: TrackRoad.h:21
Trk::RIO_OnTrack::uniqueClone
std::unique_ptr< RIO_OnTrack > uniqueClone() const
NVI clone returning unique_ptr.
Definition: RIO_OnTrack.h:97
Muon::DCMathSegmentMaker::m_reject1DTgcSpacePoints
Gaudi::Property< bool > m_reject1DTgcSpacePoints
Definition: DCMathSegmentMaker.h:417
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
Muon::DCMathSegmentMaker::residualAndPullWithSegment
static std::pair< double, double > residualAndPullWithSegment(const TrkDriftCircleMath::Segment &segment, const Cluster2D &spacePoint, const Amg::Transform3D &gToStation)
Definition: DCMathSegmentMaker.cxx:1670
beamspotman.r
def r
Definition: beamspotman.py:676
Trk::LocalParameters
Definition: LocalParameters.h:98
Muon::DCMathSegmentMaker::errorScaleFactor
double errorScaleFactor(const Identifier &id, double curvature, bool hasPhiMeasurements) const
calculate error scaling factor
Definition: DCMathSegmentMaker.cxx:646
Muon::DCMathSegmentMaker::m_addUnassociatedPhiHits
Gaudi::Property< bool > m_addUnassociatedPhiHits
Definition: DCMathSegmentMaker.h:410
Trk::PlaneSurface::localToGlobalDirection
void localToGlobalDirection(const Trk::LocalDirection &locdir, Amg::Vector3D &globdir) const
This method transforms a local direction wrt the plane to a global direction.
Definition: PlaneSurface.cxx:242
MdtReadoutElement.h
TrkDriftCircleMath::MdtChamberGeometry::print
void print(MsgStream &msg) const override
Definition: MdtChamberGeometry.cxx:170
Muon::DCMathSegmentMaker::m_createCompetingROTsEta
Gaudi::Property< bool > m_createCompetingROTsEta
Definition: DCMathSegmentMaker.h:407
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:61
Muon::DCMathSegmentMaker::ClusterVec
std::vector< Cluster2D > ClusterVec
Definition: DCMathSegmentMaker.h:158
Trk::Segment::DCMathSegmentMaker
@ DCMathSegmentMaker
Definition: Tracking/TrkEvent/TrkSegment/TrkSegment/Segment.h:68
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
Muon::DCMathSegmentMaker::associateClustersToSegment
std::pair< std::pair< int, int >, bool > associateClustersToSegment(const TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Transform3D &gToStation, ClusterVecPair &spVecs, double phimin, double phimax, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase >> > &rioDistVec) const
Definition: DCMathSegmentMaker.cxx:1287
MuonGM::MdtReadoutElement::getNLayers
int getNLayers() const
Returns the number of tube layers inside the multilayer.
MuonGM::MuonReadoutElement::AmdbLRSToGlobalTransform
virtual Amg::Transform3D AmdbLRSToGlobalTransform() const
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonReadoutElement.cxx:145
Muon::DCMathSegmentMaker::DCMathSegmentMaker
DCMathSegmentMaker(const std::string &, const std::string &, const IInterface *)
Definition: DCMathSegmentMaker.cxx:62
Muon::DCMathSegmentMaker::ClusterVecPair
std::pair< ClusterVec, ClusterVec > ClusterVecPair
Definition: DCMathSegmentMaker.h:159
checkFileSG.line
line
Definition: checkFileSG.py:75
Muon::DCMathSegmentMaker::Cluster2D::phiHit
const MuonClusterOnTrack * phiHit
Definition: DCMathSegmentMaker.h:140
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
get_generator_info.result
result
Definition: get_generator_info.py:21
TrkDriftCircleMath::DCOnTrackVec
std::vector< DCOnTrack > DCOnTrackVec
Definition: DCOnTrack.h:59
StraightLineSurface.h
TrackParameters.h
Muon::DCMathSegmentMaker::segmentCreationInfo::phimax
double phimax
Definition: DCMathSegmentMaker.h:183
Muon::IdDataVec::id
Identifier id
Definition: DCMathSegmentMaker.cxx:1272
MuonGM::RpcReadoutElement::StripLength
double StripLength(bool measphi) const
returns the strip length for the phi or eta plane
Muon::MuonClusterOnTrack::globalPosition
virtual const Amg::Vector3D & globalPosition() const override
Returns global position.
Definition: MuonClusterOnTrack.cxx:93
Muon::MuonTubeIntersect
Definition: MuonTubeIntersect.h:12
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
Muon::MdtDriftCircleOnTrack::prepRawData
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
Definition: MdtDriftCircleOnTrack.h:257
Trk::locX
@ locX
Definition: ParamDefs.h:37
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
TrkDriftCircleMath::DCOnTrack::Delta
@ Delta
used in fit
Definition: DCOnTrack.h:21
TrkDriftCircleMath::MdtId
Definition: MdtId.h:14
TrkDriftCircleMath::ClusterId
Definition: ClusterId.h:12
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:38
MuonGM::MdtReadoutElement::center
virtual const Amg::Vector3D & center(const Identifier &) const override final
Return the center of the surface associated with this identifier In the case of silicon it returns th...
Muon::DCMathSegmentMaker::Cluster2D::gasGapId
Identifier gasGapId
Definition: DCMathSegmentMaker.h:136
Muon::DCMathSegmentMaker::m_segmentSelectionTool
ToolHandle< IMuonSegmentSelectionTool > m_segmentSelectionTool
Definition: DCMathSegmentMaker.h:392
MuonGM::MdtReadoutElement::innerTubeRadius
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
MuonGM::MuonClusterReadoutElement::center
virtual const Amg::Vector3D & center() const override
Return the center of the element.
Definition: MuonClusterReadoutElement.h:125
SegmentFinder.h
Muon::DCMathSegmentMaker::create1DClusters
ClusterVecPair create1DClusters(const std::vector< const MuonClusterOnTrack * > &clusters) const
Definition: DCMathSegmentMaker.cxx:697
ClusterSeg::residual
@ residual
Definition: ClusterNtuple.h:20
TrkDriftCircleMath::DCSLFitter::fit
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed=-99999.) const
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/DCSLFitter.h:38
calibdata.chamber
chamber
Definition: calibdata.py:32
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
index
Definition: index.py:1
TrkDriftCircleMath::ChamberGeometry
Definition: ChamberGeometry.h:17
xAODP4Helpers.h
Muon::DCMathSegmentMaker::find
void find(const std::vector< const Trk::RIO_OnTrack * > &rios, Trk::SegmentCollection *segColl=nullptr) const
find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interf...
Definition: DCMathSegmentMaker.cxx:591
hist_file_dump.d
d
Definition: hist_file_dump.py:137
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
Muon::MuonClusterOnTrack::prepRawData
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
Muon::SortByDistanceToSegment
Function object to sort pairs containing a double and a pointer to a MuonClusterOnTrack.
Definition: DCMathSegmentMaker.h:82
TrkDriftCircleMath::CLVec
std::vector< Cluster > CLVec
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/Cluster.h:70
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Muon::MuonStationIndex::BML
@ BML
Definition: MuonStationIndex.h:17
Muon::IdDataVec::data
EntryVec data
Definition: DCMathSegmentMaker.cxx:1273
EventPrimitivesHelpers.h
Muon::DCMathSegmentMaker::m_removeDeltas
Gaudi::Property< bool > m_removeDeltas
Definition: DCMathSegmentMaker.h:416
MuonGM::MuonReadoutElement::GlobalToAmdbLRSTransform
virtual Amg::Transform3D GlobalToAmdbLRSTransform() const
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonReadoutElement.cxx:153
Trk::PrepRawData::localCovariance
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
Muon::DCMathSegmentMaker::createDCVec
TrkDriftCircleMath::DCVec createDCVec(const std::vector< const MdtDriftCircleOnTrack * > &mdts, double errorScale, std::set< Identifier > &chamberSet, double &phimin, double &phimax, TrkDriftCircleMath::DCStatistics &dcStatistics, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal) const
Definition: DCMathSegmentMaker.cxx:1023
Muon::DCMathSegmentMaker::m_printer
PublicToolHandle< MuonEDMPrinterTool > m_printer
Definition: DCMathSegmentMaker.h:377
skel.it
it
Definition: skel.GENtoEVGEN.py:396
Muon::SortClByPull
Definition: DCMathSegmentMaker.cxx:1280
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
TrkDriftCircleMath::DCSLFitter
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/DCSLFitter.h:17
CompetingMuonClustersOnTrack.h
M_PI
#define M_PI
Definition: ActiveFraction.h:11
TrkDriftCircleMath::ResidualWithLine::residual
double residual(const LocVec2D &pos) const
Definition: ResidualWithLine.h:21
Muon::DCMathSegmentMaker::m_segmentFinder
ToolHandle< IMdtSegmentFinder > m_segmentFinder
Definition: DCMathSegmentMaker.h:382
Muon::DCMathSegmentMaker::Cluster2D::error
double error
Definition: DCMathSegmentMaker.h:138
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
deg
#define deg
Definition: SbPolyhedron.cxx:17
Muon::DCMathSegmentMaker::ChIdHitMap
std::map< Identifier, IdHitMap > ChIdHitMap
Definition: DCMathSegmentMaker.h:102
dq_defect_virtual_defect_validation.d1
d1
Definition: dq_defect_virtual_defect_validation.py:79
xAOD::P4Helpers::deltaPhi
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition: xAODP4Helpers.h:69
MuonGM::RpcReadoutElement
An RpcReadoutElement corresponds to a single RPC module; therefore typicaly a barrel muon station con...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/RpcReadoutElement.h:55
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:35
Segment.h
GasGapData
Definition: RPCDQUtils.h:98
DriftCircle.h
Trk::RIO_OnTrack
Definition: RIO_OnTrack.h:70
Muon::DCMathSegmentMaker::Cluster2D::identify
Identifier identify() const
Definition: DCMathSegmentMaker.h:148
TrkDriftCircleMath::LocVec2D::x
double x() const
Returns the x coordinate of the vector.
Definition: LocVec2D.h:27
MdtPrepData.h
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:112
TrkDriftCircleMath::DCOnTrack::OutOfTime
@ OutOfTime
delta electron
Definition: DCOnTrack.h:22
Muon::DCMathSegmentMaker::updateSegmentPhi
bool updateSegmentPhi(const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, Amg::Vector2D &segLocPos, Trk::LocalDirection &segLocDir, Trk::PlaneSurface &surf, const std::vector< const Trk::MeasurementBase * > &rots, double phimin, double phimax) const
Definition: DCMathSegmentMaker.cxx:1849
MuonSegmentQuality.h
Trk::locR
@ locR
Definition: ParamDefs.h:44
TrkDriftCircleMath::DriftCircle
This class represents a drift time measurement.
Definition: DriftCircle.h:22
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
Muon::MuonStationIndex::BMS
@ BMS
Definition: MuonStationIndex.h:17
Muon::DCMathSegmentMaker::Cluster2D::phiHits
std::vector< const MuonClusterOnTrack * > phiHits
Definition: DCMathSegmentMaker.h:141
Muon::MdtDriftCircleOnTrack::detectorElement
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
Definition: MdtDriftCircleOnTrack.h:268
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon::CompetingMuonClustersOnTrack
Definition: CompetingMuonClustersOnTrack.h:54
MdtDriftCircleOnTrack.h
Muon::DCMathSegmentMaker::TubeEnds::lxmax
double lxmax
Definition: DCMathSegmentMaker.h:164
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
Muon::IdDataVec::Entry
T Entry
Definition: DCMathSegmentMaker.cxx:1266
MuonGM::TgcReadoutElement::stripDir
Amg::Vector3D stripDir(int gasGap, int strip) const
Returns the direction of a strip.
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
Muon::DCMathSegmentMaker::updatePhiRanges
static void updatePhiRanges(double phiminNew, double phimaxNew, double &phiminRef, double &phimaxRef)
update phi ranges
Definition: DCMathSegmentMaker.cxx:2079
x
#define x
ParamDefs.h
Muon::MuonStationIndex::PhiIndex
PhiIndex
enum to classify the different phi layers in the muon spectrometer
Definition: MuonStationIndex.h:31
TgcPrepData.h
Muon::DCMathSegmentMaker::m_DetectorManagerKey
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_DetectorManagerKey
pointers to IdHelpers
Definition: DCMathSegmentMaker.h:338
TrkDriftCircleMath::TransformToLine
Definition: TransformToLine.h:15
Muon::DCMathSegmentMaker::createSpacePoints
ClusterVecPair createSpacePoints(const ChIdHitMap &chIdHitMap) const
Definition: DCMathSegmentMaker.cxx:744
Muon::MdtDriftCircleOnTrack::globalPosition
virtual const Amg::Vector3D & globalPosition() const override final
Returns the global Position.
Definition: MdtDriftCircleOnTrack.cxx:108
Muon::MdtDriftCircleOnTrack::driftTime
double driftTime() const
Returns the value of the drift time used to obtain the drift radius.
Definition: MdtDriftCircleOnTrack.h:280
Muon::DCMathSegmentMaker::checkBoundsInXZ
bool checkBoundsInXZ(double xline, double zline, double dXdZ, const std::vector< HitInXZ > &hits) const
check whether all hits are in bounds in the XZ plane
Definition: DCMathSegmentMaker.cxx:1825
TrkDriftCircleMath::Segment
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/Segment.h:18
TrkDriftCircleMath::LocVec2D
Implementation of 2 dimensional vector class.
Definition: LocVec2D.h:16
TrkDriftCircleMath::DCVec
std::vector< DriftCircle > DCVec
Definition: DriftCircle.h:117
Muon::DCMathSegmentMaker::m_curvedErrorScaling
Gaudi::Property< bool > m_curvedErrorScaling
Definition: DCMathSegmentMaker.h:405
Amg::getRotateZ3D
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Definition: GeoPrimitivesHelpers.h:270
Trk::LocalDirection::angleYZ
double angleYZ() const
access method for angle of local YZ projection
Definition: LocalDirection.h:106
Muon::IdDataVec
Definition: DCMathSegmentMaker.cxx:1265
Muon::DCMathSegmentMaker::m_mdtCreator
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreator
Definition: DCMathSegmentMaker.h:357
Trk::TrackStateOnSurface::Outlier
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
Definition: TrackStateOnSurface.h:122
Muon::DCMathSegmentMaker::segmentCreationInfo::globalTrans
Amg::Transform3D globalTrans
Definition: DCMathSegmentMaker.h:180
TRT::Hit::side
@ side
Definition: HitInfo.h:83
Track.h
TgcClusterOnTrack.h
Trk::StraightLineSurface::globalToLocal
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for StraightLineSurface: GlobalToLocal method without dynamic memory allocation This method...
Definition: StraightLineSurface.cxx:164
TrkDriftCircleMath::Line
Definition: Line.h:17
Muon::MuonClusterOnTrack::detectorElement
virtual const MuonGM::MuonClusterReadoutElement * detectorElement() const override=0
Returns the detector element, associated with the PRD of this class.
Muon::DCMathSegmentMaker::Cluster2D::detElId
Identifier detElId
Definition: DCMathSegmentMaker.h:135
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
TrkDriftCircleMath::Road
TrkDriftCircleMath::Road - encodes the road given to the segment finder in station coordinates.
Definition: Road.h:15
Trk::TrackRoad::globalDirection
const Amg::Vector3D & globalDirection() const
Get the global direction of the road.
Definition: TrackRoad.h:143
Muon::DCMathSegmentMaker::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: DCMathSegmentMaker.h:345
DCMathSegmentMaker.h
Muon::DCMathSegmentMaker::m_compClusterCreator
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compClusterCreator
Definition: DCMathSegmentMaker.h:372
RpcClusterOnTrack.h
Muon::DCMathSegmentMaker::createROTVec
static DataVector< const Trk::MeasurementBase > createROTVec(std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase >> > &rioDistVec)
Definition: DCMathSegmentMaker.cxx:1658
Muon::IdDataVec::IdDataVec
IdDataVec()=default
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
Muon::DCMathSegmentMaker::Cluster2D::etaHit
const MuonClusterOnTrack * etaHit
Definition: DCMathSegmentMaker.h:139
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Muon::DCMathSegmentMaker::createClusterVec
TrkDriftCircleMath::CLVec createClusterVec(const Identifier &chid, ClusterVec &spVec, const Amg::Transform3D &gToStation) const
Definition: DCMathSegmentMaker.cxx:981
DefinedParameter.h
Muon::DCMathSegmentMaker::m_usePreciseError
Gaudi::Property< bool > m_usePreciseError
Definition: DCMathSegmentMaker.h:418
MuonGM::MuonDetectorManager::getMdtReadoutElement
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:204
EventPrimitivesToStringConverter.h
ParticleGun_EoverP_Config.momentum
momentum
Definition: ParticleGun_EoverP_Config.py:63
MuonGM::MdtReadoutElement
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:51
Muon::DCMathSegmentMaker::TubeEnds::phimin
double phimin
Definition: DCMathSegmentMaker.h:165
Muon::DCMathSegmentMaker::associateMDTsToSegment
void associateMDTsToSegment(const Amg::Vector3D &gdir, TrkDriftCircleMath::Segment &segment, const TrkDriftCircleMath::ChamberGeometry *multiGeo, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase >> > &rioDistVec) const
Definition: DCMathSegmentMaker.cxx:1152
lumiFormat.i
int i
Definition: lumiFormat.py:85
SG::OWN_ELEMENTS
@ OWN_ELEMENTS
this data object owns its elements
Definition: OwnershipPolicy.h:17
z
#define z
Muon::DCMathSegmentMaker::errorScalingRegion
bool errorScalingRegion(const Identifier &id) const
apply error scaling for low mometum tracks
Definition: DCMathSegmentMaker.cxx:679
Trk::TrackRoad::globalPosition
const Amg::Vector3D & globalPosition() const
Get the global position of the road.
Definition: TrackRoad.h:137
TrkDriftCircleMath::DCSLHitSelector
Definition: DCSLHitSelector.h:13
Muon::DCMathSegmentMaker::m_segmentFitter
ToolHandle< IMuonSegmentFittingTool > m_segmentFitter
Definition: DCMathSegmentMaker.h:387
beamspotman.n
n
Definition: beamspotman.py:731
Trk::theta
@ theta
Definition: ParamDefs.h:66
Trk::MeasurementBase::uniqueClone
std::unique_ptr< MeasurementBase > uniqueClone() const
NVI Clone giving up unique pointer.
Definition: MeasurementBase.h:77
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
TrkDriftCircleMath::ChamberGeometry::nlay
virtual unsigned int nlay() const =0
angle
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
Definition: TRTDetectorFactory_Full.cxx:73
xAOD::covMatrix
covMatrix
Definition: TrackMeasurement_v1.cxx:19
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Muon::DCMathSegmentMaker::Cluster2D
Definition: DCMathSegmentMaker.h:119
Trk::driftRadius
@ driftRadius
trt, straws
Definition: ParamDefs.h:53
MuonGM::MdtReadoutElement::getActiveTubeLength
double getActiveTubeLength(const int tubeLayer, const int tube) const
Muon::DCMathSegmentMaker::segmentCreationInfo::phimin
double phimin
Definition: DCMathSegmentMaker.h:182
TrkDriftCircleMath::MdtChamberGeometry
Definition: MdtChamberGeometry.h:18
Muon::DCMathSegmentMaker::m_edmHelperSvc
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
Definition: DCMathSegmentMaker.h:350
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::RIGHT
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
Definition: DriftCircleSide.h:22
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
Muon::DCMathSegmentMaker::m_chamberGeoKey
SG::ReadCondHandleKey< Muon::MuonIntersectGeoData > m_chamberGeoKey
Definition: DCMathSegmentMaker.h:431
MuonGM::TgcReadoutElement
A TgcReadoutElement corresponds to a single TGC chamber; therefore typically a TGC station contains s...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/TgcReadoutElement.h:42
Muon::DCMathSegmentMaker::Cluster2D::corrupt
bool corrupt() const
Definition: DCMathSegmentMaker.h:156
Muon::SortIdDataVec::operator()
bool operator()(const IdDataVec< T > &d1, const IdDataVec< T > &d2)
Definition: DCMathSegmentMaker.cxx:1277
TrkDriftCircleMath::LocVec2D::y
double y() const
Returns the y coordinate of the vector.
Definition: LocVec2D.h:29
Muon::DCMathSegmentMaker::TubeEnds::phimax
double phimax
Definition: DCMathSegmentMaker.h:166
Muon::DCMathSegmentMaker::TubeEnds::lxmin
double lxmin
Definition: DCMathSegmentMaker.h:163
Muon::MdtPrepData::globalPosition
virtual const Amg::Vector3D & globalPosition() const
Returns the global position of the CENTER of the drift tube (i.e.
Definition: MdtPrepData.h:133
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:282
ClusterId.h
Muon::DCMathSegmentMaker::createSpacePoint
Cluster2D createSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
Definition: DCMathSegmentMaker.cxx:847
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonGM::TgcReadoutElement::localSpacePoint
Amg::Vector3D localSpacePoint(const Identifier &stripId, const Amg::Vector3D &etaHitPos, const Amg::Vector3D &phiHitPos) const
Definition: MuonDetDescr/MuonReadoutGeometry/src/TgcReadoutElement.cxx:315
Muon::IdDataVec::IdDataVec
IdDataVec(const Identifier &i)
Definition: DCMathSegmentMaker.cxx:1270
MuonGM::MdtReadoutElement::nMDTinStation
unsigned int nMDTinStation() const
How many MDT chambers are in the station.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:62
Muon::DCMathSegmentMaker::Cluster2D::is2D
bool is2D() const
Definition: DCMathSegmentMaker.h:155
Muon::DCMathSegmentMaker::segmentCreationInfo::clusters
ClusterVecPair clusters
Definition: DCMathSegmentMaker.h:178
Muon::DCMathSegmentMaker::m_refitParameters
Gaudi::Property< bool > m_refitParameters
Definition: DCMathSegmentMaker.h:409
Trk::PlaneSurface::globalToLocalDirection
void globalToLocalDirection(const Amg::Vector3D &glodir, Trk::LocalDirection &locdir) const
This method transforms the global direction to a local direction wrt the plane.
Definition: PlaneSurface.cxx:260
Muon::DCMathSegmentMaker::m_allMdtHoles
Gaudi::Property< bool > m_allMdtHoles
Definition: DCMathSegmentMaker.h:415
Muon::DCMathSegmentMaker::createSegment
std::unique_ptr< MuonSegment > createSegment(const EventContext &ctx, TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Vector3D &roadpos, const Amg::Vector3D &roaddir2, const std::vector< const MdtDriftCircleOnTrack * > &mdts, bool hasPhiMeasurements, segmentCreationInfo &sInfo) const
Definition: DCMathSegmentMaker.cxx:229
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
Trk::ParametersBase
Definition: ParametersBase.h:55
Muon::DCMathSegmentMaker::initialize
virtual StatusCode initialize()
Definition: DCMathSegmentMaker.cxx:65
Muon::DCMathSegmentMaker::m_createCompetingROTsPhi
Gaudi::Property< bool > m_createCompetingROTsPhi
Definition: DCMathSegmentMaker.h:408
Muon::DCMathSegmentMaker::m_recoverBadRpcCabling
Gaudi::Property< bool > m_recoverBadRpcCabling
Definition: DCMathSegmentMaker.h:423
Muon::MdtDriftCircleOnTrack::driftRadius
double driftRadius() const
Returns the value of the drift radius.
Definition: MdtDriftCircleOnTrack.h:277
Athena::Timeout::instance
static Timeout & instance()
Get reference to Timeout singleton.
Definition: Timeout.h:64
a0
double a0
Definition: globals.cxx:27
TrkDriftCircleMath::TransformToLine::toLocal
LocVec2D toLocal(const LocVec2D &pos) const
Definition: TransformToLine.h:26
Muon::MuonPrepDataCollection
Template to hold collections of MuonPrepRawData objects.
Definition: MuonPrepDataCollection.h:46
DataVector< Trk::Segment >
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
Trk::LocalDirection
represents the three-dimensional global direction with respect to a planar surface frame.
Definition: LocalDirection.h:81
Muon::DCMathSegmentMaker::IdHitMap
std::map< Identifier, EtaPhiHitsPair > IdHitMap
Definition: DCMathSegmentMaker.h:101
TrkDriftCircleMath::DCOnTrack::OnTrack
@ OnTrack
Definition: DCOnTrack.h:20
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
Trk::Segment::DCMathSegmentMakerCurved
@ DCMathSegmentMakerCurved
Definition: Tracking/TrkEvent/TrkSegment/TrkSegment/Segment.h:75
Road.h
Muon::DCMathSegmentMaker::localTubeEnds
TubeEnds localTubeEnds(const MdtDriftCircleOnTrack &mdt, const Amg::Transform3D &gToSegment, const Amg::Transform3D &segmentToG) const
calculate positions of tube ends
Definition: DCMathSegmentMaker.cxx:2049
Trk::MeasurementBase
Definition: MeasurementBase.h:58
TrkDriftCircleMath::TransformToLine::toLine
LocVec2D toLine(const LocVec2D &pos) const
Definition: TransformToLine.h:20
Trk::TrackStateOnSurface
represents the track state (measurement, material, fit parameters and quality) at a surface.
Definition: TrackStateOnSurface.h:71
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
Muon::DCMathSegmentMaker::calculateHoles
std::vector< Identifier > calculateHoles(const EventContext &ctx, Identifier chid, const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, bool hasMeasuredCoordinate, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, const std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase >> > &rioDistVec) const
Definition: DCMathSegmentMaker.cxx:1692
RIO_OnTrack.h
Muon::DCMathSegmentMaker::m_mdtKey
SG::ReadHandleKey< Muon::MdtPrepDataContainer > m_mdtKey
Definition: DCMathSegmentMaker.h:429
TrkDriftCircleMath::Cluster
class representing a cluster meaurement
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/Cluster.h:22
Muon::DCMathSegmentMaker::create2DClusters
ClusterVecPair create2DClusters(const std::vector< const MuonClusterOnTrack * > &clusters) const
Definition: DCMathSegmentMaker.cxx:723
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Amg::error
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Definition: EventPrimitivesHelpers.h:40
Trk::PrepRawData::localPosition
const Amg::Vector2D & localPosition() const
return the local position reference
Muon::MdtDriftCircleOnTrack
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Definition: MdtDriftCircleOnTrack.h:37
charge
double charge(const T &p)
Definition: AtlasPID.h:756
Muon::DCMathSegmentMaker::findFirstRotInChamberWithMostHits
const MdtDriftCircleOnTrack * findFirstRotInChamberWithMostHits(const std::vector< const MdtDriftCircleOnTrack * > &mdts) const
Definition: DCMathSegmentMaker.cxx:1795
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
TrkDriftCircleMath::ResidualWithSegment
class to calculate residual of a hit with a segment and calculate the local track errors
Definition: ResidualWithSegment.h:20
Muon::MdtPrepData
Class to represent measurements from the Monitored Drift Tubes.
Definition: MdtPrepData.h:33
Muon::CompetingMuonClustersOnTrack::containedROTs
const std::vector< const MuonClusterOnTrack * > & containedROTs() const
returns the vector of SCT_ClusterOnTrack objects .
Definition: CompetingMuonClustersOnTrack.h:184
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
LocalParameters.h
MuonDetectorManager.h
TrkDriftCircleMath::ChamberGeometry::tubePosition
virtual LocVec2D tubePosition(unsigned int ml, unsigned int lay, unsigned int tube) const =0
Muon::DCMathSegmentMaker::m_dcslFitProvider
ToolHandle< IDCSLFitProvider > m_dcslFitProvider
Definition: DCMathSegmentMaker.h:397
MuonGM::MdtReadoutElement::ROPos
Amg::Vector3D ROPos(const int tubelayer, const int tube) const
Definition: MuonDetDescr/MuonReadoutGeometry/src/MdtReadoutElement.cxx:289
Trk::MeasurementBase::localParameters
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
Definition: MeasurementBase.h:132
Muon::DCMathSegmentMaker::m_doSpacePoints
Gaudi::Property< bool > m_doSpacePoints
Definition: DCMathSegmentMaker.h:406
Trk::DriftCircleSide
DriftCircleSide
Enumerates the 'side' of the wire on which the tracks passed (i.e.
Definition: DriftCircleSide.h:16
Muon::SortIdDataVec
Definition: DCMathSegmentMaker.cxx:1276
eflowRec::phiIndex
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition: EtaPhiLUT.cxx:23
Timeout.h
Timeout singleton.
makeTRTBarrelCans.dy
tuple dy
Definition: makeTRTBarrelCans.py:21
Muon::MuonStationIntersect
Definition: MuonStationIntersect.h:12
Muon::DCMathSegmentMaker::createTgcSpacePoint
Cluster2D createTgcSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
Definition: DCMathSegmentMaker.cxx:879
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
DeMoScan.index
string index
Definition: DeMoScan.py:364
Muon::CompetingMuonClustersOnTrack::rioOnTrack
const MuonClusterOnTrack & rioOnTrack(unsigned int) const
returns the RIO_OnTrack (also known as ROT) objects depending on the integer
Definition: CompetingMuonClustersOnTrack.h:190
Muon::DCMathSegmentMaker::m_doTimeOutChecks
Gaudi::Property< bool > m_doTimeOutChecks
Definition: DCMathSegmentMaker.h:421
Muon::DCMathSegmentMaker::m_maxAssociateClusterDistance
Gaudi::Property< double > m_maxAssociateClusterDistance
Definition: DCMathSegmentMaker.h:413
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
Trk::Surface::globalToLocal
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const =0
Specified by each surface type: GlobalToLocal method without dynamic memory allocation - boolean chec...
Muon::DCMathSegmentMaker::m_sinAngleCut
Gaudi::Property< double > m_sinAngleCut
Definition: DCMathSegmentMaker.h:403
Muon::DCMathSegmentMaker::m_redo2DFit
Gaudi::Property< bool > m_redo2DFit
Definition: DCMathSegmentMaker.h:426
Muon::DCMathSegmentMaker::m_doGeometry
Gaudi::Property< bool > m_doGeometry
Definition: DCMathSegmentMaker.h:404
Amg::intersect
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Definition: GeoPrimitivesHelpers.h:347
MuonGM::MuonDetectorManager
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonDetectorManager.h:50
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MuonStationIndex::BIL
@ BIL
Definition: MuonStationIndex.h:17
Trk::PlaneSurface
Definition: PlaneSurface.h:64
TrkDriftCircleMath::DCSLHitSelector::selectHitsOnTrack
const HitSelection selectHitsOnTrack(const DCOnTrackVec &dcs) const
Definition: DCSLHitSelector.h:20
Muon::DCMathSegmentMaker::segmentCreationInfo::geom
const TrkDriftCircleMath::ChamberGeometry * geom
Definition: DCMathSegmentMaker.h:179
PlaneSurface.h
Muon::SortClByPull::operator()
bool operator()(const std::pair< double, DCMathSegmentMaker::Cluster2D > &d1, const std::pair< double, DCMathSegmentMaker::Cluster2D > &d2)
Definition: DCMathSegmentMaker.cxx:1281
Muon::DCMathSegmentMaker::findMdt
const MdtPrepData * findMdt(const EventContext &ctx, const Identifier &id) const
Definition: DCMathSegmentMaker.cxx:1776
ResidualWithSegment.h
JacobianCotThetaPtToThetaP.h
Muon::DCMathSegmentMaker::m_assumePointingPhi
Gaudi::Property< bool > m_assumePointingPhi
Definition: DCMathSegmentMaker.h:425
dq_defect_virtual_defect_validation.d2
d2
Definition: dq_defect_virtual_defect_validation.py:81
Trk::RIO_OnTrack::identify
Identifier identify() const
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:152
DEBUG
#define DEBUG
Definition: page_access.h:11
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
MuonGM::MdtReadoutElement::surface
virtual const Trk::Surface & surface() const override final
Return surface associated with this detector element.
Definition: MuonDetDescr/MuonReadoutGeometry/src/MdtReadoutElement.cxx:891
GeoPrimitivesToStringConverter.h
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
Muon::DCMathSegmentMaker::m_updatePhiUsingPhiHits
Gaudi::Property< bool > m_updatePhiUsingPhiHits
Definition: DCMathSegmentMaker.h:424
TrkDriftCircleMath::DCOnTrack
class representing a drift circle meaurement on segment
Definition: DCOnTrack.h:16
TrkDriftCircleMath::SegVec
std::vector< Segment > SegVec
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/Segment.h:122
Muon::DCMathSegmentMaker::m_clusterCreator
ToolHandle< IMuonClusterOnTrackCreator > m_clusterCreator
Definition: DCMathSegmentMaker.h:367
Muon::MuonStationIndex::ChIndex
ChIndex
enum to classify the different chamber layers in the muon spectrometer
Definition: MuonStationIndex.h:15
Muon::DCMathSegmentMaker::distanceToSegment
static double distanceToSegment(const TrkDriftCircleMath::Segment &segment, const Amg::Vector3D &hitPos, const Amg::Transform3D &gToStation)
Definition: DCMathSegmentMaker.cxx:1635
Muon::DCMathSegmentMaker::createRpcSpacePoint
Cluster2D createRpcSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const std::vector< const MuonClusterOnTrack * > &phiHits) const
Definition: DCMathSegmentMaker.cxx:920
Muon::DCMathSegmentMaker::updateDirection
Amg::Vector3D updateDirection(double linephi, const Trk::PlaneSurface &surf, const Amg::Vector3D &roaddir, bool isCurvedSegment) const
update the global direction, keeping the phi of the input road direction but using the local angle YZ
Definition: DCMathSegmentMaker.cxx:2127
Muon::DCMathSegmentMaker::segmentCreationInfo::amdbTrans
Amg::Transform3D amdbTrans
Definition: DCMathSegmentMaker.h:181
Trk::LEFT
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
Definition: DriftCircleSide.h:20
Trk::phi
@ phi
Definition: ParamDefs.h:75
Trk::RIO_OnTrack::associatedSurface
virtual const Surface & associatedSurface() const override=0
returns the surface for the local to global transformation
LocalDirection.h
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
calibdata.copy
bool copy
Definition: calibdata.py:27
Muon::DCMathSegmentMaker::Cluster2D::globalPos
Amg::Vector3D globalPos
Definition: DCMathSegmentMaker.h:154
Muon::DCMathSegmentMaker::m_outputFittedT0
Gaudi::Property< bool > m_outputFittedT0
Definition: DCMathSegmentMaker.h:419
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
TrkDriftCircleMath::ResidualWithSegment::trackError2
double trackError2(const DriftCircle &dc) const
calculate the track error at the position of a drift circle
Definition: ResidualWithSegment.h:29
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Trk::LocalDirection::angleXZ
double angleXZ() const
access method for angle of local XZ projection
Definition: LocalDirection.h:103
RpcPrepData.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
Trk::PlaneSurface::localToGlobal
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const override final
Specified for PlaneSurface: LocalToGlobal method without dynamic memory allocation.
Definition: PlaneSurface.cxx:204
FitQuality.h
MuonGM::MdtReadoutElement::getNtubesperlayer
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
Muon::DCMathSegmentMaker::HitInXZ
Definition: DCMathSegmentMaker.h:105
Trk::loc1
@ loc1
Definition: ParamDefs.h:34
Muon::DCMathSegmentMaker::m_mdtCreatorT0
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreatorT0
Definition: DCMathSegmentMaker.h:362
error
Definition: IImpactPoint3dEstimator.h:70
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Muon::DCMathSegmentMaker::TubeEnds
Definition: DCMathSegmentMaker.h:161
Muon::MuonStationIndex::BOL
@ BOL
Definition: MuonStationIndex.h:17
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
Muon::MdtPrepData::detectorElement
virtual const MuonGM::MdtReadoutElement * detectorElement() const override
Returns the detector element corresponding to this PRD.
Definition: MdtPrepData.h:141
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
TrackRoad.h
calibdata.tube
tube
Definition: calibdata.py:31
python.SystemOfUnits.degree
tuple degree
Definition: SystemOfUnits.py:106
Trk::driftCircle
@ driftCircle
Definition: MeasurementType.h:25
Muon::DCMathSegmentMaker::createChamberGeometry
TrkDriftCircleMath::MdtChamberGeometry createChamberGeometry(const Identifier &chid, const Amg::Transform3D &gToStation) const
Definition: DCMathSegmentMaker.cxx:1076
Muon::DCMathSegmentMaker::checkPhiConsistency
bool checkPhiConsistency(double phi, double phimin, double phimax) const
check whether phi is consistent with segment phi
Definition: DCMathSegmentMaker.cxx:2101
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
Muon::DCMathSegmentMaker::m_preciseErrorScale
Gaudi::Property< double > m_preciseErrorScale
Definition: DCMathSegmentMaker.h:420
Trk::StraightLineSurface
Definition: StraightLineSurface.h:51
Muon::MuonClusterOnTrack
Base class for Muon cluster RIO_OnTracks.
Definition: MuonClusterOnTrack.h:34
Muon::DCMathSegmentMaker::segmentCreationInfo
Definition: DCMathSegmentMaker.h:169
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
NSWL1::PadTriggerAdapter::segment
Muon::NSW_PadTriggerSegment segment(const NSWL1::PadTrigger &data)
Definition: PadTriggerAdapter.cxx:5
Muon::IdDataVec::EntryVec
std::vector< Entry > EntryVec
Definition: DCMathSegmentMaker.cxx:1267
TrkDriftCircleMath::DriftCircle::InTime
@ InTime
drift time too small to be compatible with drift spectrum
Definition: DriftCircle.h:27
Trk::TrackRoad::deltaEta
double deltaEta() const
Get the width of the road in the eta direction.
Definition: TrackRoad.h:149
RpcReadoutElement.h
TrkDriftCircleMath::DCStatistics
This class offers no functionality, but to define a standard device for the maker to transfer to the ...
Definition: DCStatistics.h:19
Identifier
Definition: IdentifierFieldParser.cxx:14