ATLAS Offline Software
MSVertexRecoTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MSVertexRecoTool.h"
6 
8 #include "EventPrimitives/EventPrimitivesHelpers.h" //Amg::error
10 
11 #include "CLHEP/Random/RandFlat.h"
12 #include "TMath.h"
13 
14 
15 /*
16  MS vertex reconstruction routine
17  See documentation at https://cds.cern.ch/record/1455664 and https://cds.cern.ch/record/1520894
18  Takes Tracklets as input and creates vertices in the MS volume
19 */
20 
21 namespace {
22  constexpr unsigned int MAXPLANES = 100;
23 }
24 
25 namespace Muon {
26 
27  //** ----------------------------------------------------------------------------------------------------------------- **//
28 
29  MSVertexRecoTool::MSVertexRecoTool(const std::string& type, const std::string& name, const IInterface* parent) :
31  declareInterface<IMSVertexRecoTool>(this);
32  }
33 
34  //** ----------------------------------------------------------------------------------------------------------------- **//
35 
37  ATH_CHECK(m_idHelperSvc.retrieve());
38  ATH_CHECK(m_rndmSvc.retrieve());
39 
40  ATH_CHECK(m_extrapolator.retrieve());
41  ATH_CHECK(m_xAODContainerKey.initialize());
42  ATH_CHECK(m_rpcTESKey.initialize());
43  ATH_CHECK(m_tgcTESKey.initialize());
44  ATH_CHECK(m_mdtTESKey.initialize());
45 
46  for (const std::string& str : m_accMDT_str) m_nMDT_accs.push_back(SG::AuxElement::Accessor<int>(str));
47  for (const std::string& str : m_accRPC_str) m_nRPC_accs.push_back(SG::AuxElement::Accessor<int>(str));
48  for (const std::string& str : m_accTGC_str) m_nTGC_accs.push_back(SG::AuxElement::Accessor<int>(str));
49 
50  return StatusCode::SUCCESS;
51  }
52 
53  //** ----------------------------------------------------------------------------------------------------------------- **//
54 
55  StatusCode MSVertexRecoTool::findMSvertices(const std::vector<Tracklet>& tracklets, std::vector<std::unique_ptr<MSVertex>>& vertices,
56  const EventContext& ctx) const {
57  ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
58  rngWrapper->setSeed(name(), ctx);
59  CLHEP::HepRandomEngine* rndmEngine = rngWrapper->getEngine(ctx);
60 
62  ATH_CHECK(xAODVxContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()));
63 
64  if (tracklets.size() < 3) {
65  ATH_MSG_DEBUG("Fewer than 3 tracks found, vertexing not possible. Exiting...");
66  return StatusCode::SUCCESS;
67  }
68 
69  if (tracklets.size() > m_maxGlobalTracklets) {
70  ATH_MSG_DEBUG("Too many tracklets found globally. Exiting...");
71  return StatusCode::SUCCESS;
72  }
73 
74  // group the tracks
75  std::vector<Tracklet> BarrelTracklets;
76  std::vector<Tracklet> EndcapTracklets;
77  for (const Tracklet &tracklet : tracklets){
78  if (m_idHelperSvc->mdtIdHelper().isBarrel(tracklet.muonIdentifier()))
79  BarrelTracklets.push_back(tracklet);
80  else if (m_idHelperSvc->mdtIdHelper().isEndcap(tracklet.muonIdentifier()))
81  EndcapTracklets.push_back(tracklet);
82  }
83 
84  if (BarrelTracklets.size() > m_maxClusterTracklets || EndcapTracklets.size() > m_maxClusterTracklets) {
85  ATH_MSG_DEBUG("Too many tracklets found in barrel or endcap for clustering. Exiting...");
86  return StatusCode::SUCCESS;
87  }
88 
89  ATH_MSG_DEBUG("Running on event with " << BarrelTracklets.size() << " barrel tracklets, " << EndcapTracklets.size()
90  << " endcap tracklets.");
91 
92  // find any clusters of tracks & decide if tracks are from single muon
93  std::vector<Muon::MSVertexRecoTool::TrkCluster> BarrelClusters = findTrackClusters(BarrelTracklets);
94  std::vector<Muon::MSVertexRecoTool::TrkCluster> EndcapClusters = findTrackClusters(EndcapTracklets);
95 
96  // if doSystematics, remove tracklets according to the tracklet reco uncertainty and rerun the cluster finder
97  if (m_doSystematics) {
98  std::vector<Tracklet> BarrelSystTracklets, EndcapSystTracklets;
99  for (const Tracklet &BarrelTracklet : BarrelTracklets) {
100  double prob = CLHEP::RandFlat::shoot(rndmEngine, 0, 1);
101  if (prob > m_BarrelTrackletUncert) BarrelSystTracklets.push_back(BarrelTracklet);
102  }
103  if (BarrelSystTracklets.size() >= 3) {
104  std::vector<Muon::MSVertexRecoTool::TrkCluster> BarrelSystClusters = findTrackClusters(BarrelSystTracklets);
105  for (Muon::MSVertexRecoTool::TrkCluster &BarrelSystCluster : BarrelSystClusters) {
106  BarrelSystCluster.isSystematic = true;
107  BarrelClusters.push_back(BarrelSystCluster);
108  }
109  }
110 
111  for (const Tracklet &EndcapTracklet : EndcapTracklets) {
112  double prob = CLHEP::RandFlat::shoot(rndmEngine, 0, 1);
113  if (prob > m_EndcapTrackletUncert) EndcapSystTracklets.push_back(EndcapTracklet);
114  }
115  if (EndcapSystTracklets.size() >= 3) {
116  std::vector<Muon::MSVertexRecoTool::TrkCluster> EndcapSystClusters = findTrackClusters(EndcapSystTracklets);
117  for (Muon::MSVertexRecoTool::TrkCluster &EndcapSystCluster : EndcapSystClusters) {
118  EndcapSystCluster.isSystematic = true;
119  EndcapClusters.push_back(EndcapSystCluster);
120  }
121  }
122  }
123 
125  // find vertices in the barrel MS (vertices using barrel tracklets)
126  for (const Muon::MSVertexRecoTool::TrkCluster &BarrelCluster : BarrelClusters) {
127  if (BarrelCluster.ntrks < 3) continue;
128  ATH_MSG_DEBUG("Attempting to build vertex from " << BarrelCluster.ntrks << " tracklets in the barrel");
129  std::unique_ptr<MSVertex> barvertex(nullptr);
130  MSVxFinder(BarrelCluster.tracks, barvertex, ctx);
131  if (!barvertex) continue;
132  // barrel minimum good vertex criteria
133  if (barvertex->getChi2Probability() > m_VxChi2ProbCUT) {
134  HitCounter(barvertex.get(), ctx);
135  if (barvertex->getNMDT() > m_MinMDTHits && (barvertex->getNRPC() + barvertex->getNTGC()) > m_MinTrigHits) {
136  ATH_MSG_DEBUG("Vertex found in the barrel with n_trk = " << barvertex->getNTracks() << " located at (eta,phi) = ("
137  << barvertex->getPosition().eta() << ", "
138  << barvertex->getPosition().phi() << ")");
139  if (BarrelCluster.isSystematic) barvertex->setAuthor(3);
140  vertices.push_back(std::move(barvertex));
141  }
142  }
143  }
144 
145  // find vertices in the endcap MS (vertices using endcap tracklets)
146  for (const Muon::MSVertexRecoTool::TrkCluster &EndcapCluster : EndcapClusters) {
147  if (EndcapCluster.ntrks < 3) continue;
148  ATH_MSG_DEBUG("Attempting to build vertex from " << EndcapCluster.ntrks << " tracklets in the endcap");
149 
150  std::unique_ptr<MSVertex> endvertex(nullptr);
152  MSStraightLineVx_oldMethod(EndcapCluster.tracks, endvertex, ctx);
153  else
154  MSStraightLineVx(EndcapCluster.tracks, endvertex, ctx);
155 
156  if (!endvertex) continue;
157  // endcap minimum good vertex criteria
158  if (endvertex->getPosition().perp() < m_MaxLxyEndcap && std::abs(endvertex->getPosition().z()) < m_MaxZEndcap &&
159  std::abs(endvertex->getPosition().z()) > m_MinZEndcap && endvertex->getNTracks() >= 3) {
160  HitCounter(endvertex.get(), ctx);
161  if (endvertex->getNMDT() > m_MinMDTHits && (endvertex->getNRPC() + endvertex->getNTGC()) > m_MinTrigHits) {
162  ATH_MSG_DEBUG("Vertex found in the endcap with n_trk = " << endvertex->getNTracks() << " located at (eta,phi) = ("
163  << endvertex->getPosition().eta() << ", "
164  << endvertex->getPosition().phi() << ")");
165  if (EndcapCluster.isSystematic) endvertex->setAuthor(4);
166  vertices.push_back(std::move(endvertex));
167  }
168  }
169 
170  } // end loop on endcap tracklet clusters
171 
172  ATH_CHECK(FillOutputContainer(vertices, xAODVxContainer));
173  return StatusCode::SUCCESS;
174  } // end find vertices
175 
176  //** ----------------------------------------------------------------------------------------------------------------- **//
177 
178  std::optional<Muon::MSVertexRecoTool::TrkCluster> MSVertexRecoTool::ClusterizeTracks(std::vector<Tracklet>& tracks) const {
179  // returns the best cluster of tracklets and removes them from the input vector for the next iteration
180 
181  if (tracks.size() > m_maxClusterTracklets) {
182  ATH_MSG_DEBUG("Too many tracks found, returning empty cluster");
183  return std::nullopt;
184  }
185 
186  std::vector<TrkCluster> trkClu;
187  std::vector<TrkCluster> trkClu0;
188  // use each tracklet as a seed for the clusters
189  int ncluster = 0;
190  for (const Tracklet& trk : tracks) {
191  TrkCluster clu;
192  clu.eta = trk.globalPosition().eta();
193  clu.phi = trk.globalPosition().phi();
194 
195  trkClu.push_back(clu);
196  trkClu0.push_back(clu);
197  ++ncluster;
198  if (ncluster >= 99) {
199  return std::nullopt;
200  }
201  }
202 
203  // loop on the clusters and let the center move to find the optimal cluster centers
204  for (TrkCluster& clu : trkClu) {
205  // add tracklets to the cluster and update it
206  int ntracks = 0;
207  for (const TrkCluster& trk : trkClu0) {
208  double dEta = clu.eta - trk.eta;
209  double dPhi = xAOD::P4Helpers::deltaPhi(clu.phi , trk.phi);
210  if (std::abs(dEta) < m_ClusterdEta && std::abs(dPhi) < m_ClusterdPhi) {
211  ++ntracks;
212  clu.eta = clu.eta - dEta / ntracks;
213  clu.phi = xAOD::P4Helpers::deltaPhi(clu.phi - dPhi / ntracks, 0);
214  }
215  }
216 
217  // the updated cluster position might cause tracklets considered near the start of the loop to now lie inside or outside the cluster
218  // run over all tracklets again to check is any more tracklets are picked up. Is so, do this at most 5 times
219  // *_best store the centre of the cluster containing the most tracklets
220  double eta_best = clu.eta;
221  double phi_best = clu.phi;
222  int nitr = 0;
223  bool improvement = true;
224  while (improvement) {
225  unsigned int ntracks_new = 0;
226  double eta_new = 0.0;
227  double phi_new = 0.0;
228  double cosPhi_new = 0.0;
229  double sinPhi_new = 0.0;
230 
231  for (const TrkCluster& trk : trkClu0) {
232  double dEta = clu.eta - trk.eta;
233  double dPhi = xAOD::P4Helpers::deltaPhi(clu.phi , trk.phi);
234  if (std::abs(dEta) < m_ClusterdEta && std::abs(dPhi) < m_ClusterdPhi) {
235  eta_new += trk.eta;
236  cosPhi_new += std::cos(trk.phi);
237  sinPhi_new += std::sin(trk.phi);
238  ++ntracks_new;
239  }
240  }
241 
242  eta_new = eta_new / ntracks_new;
243  phi_new = std::atan2(sinPhi_new / ntracks_new, cosPhi_new / ntracks_new);
244 
245  if (ntracks_new > clu.ntrks) {
246  // better cluster found - update the centre and number of tracklets
247  eta_best = clu.eta; // not eta_new in case the iteration threshold was exceeded
248  phi_best = clu.phi;
249  clu.ntrks = ntracks_new;
250  if (nitr < 6) {
251  // update the cluster for the next improvement iteration
252  clu.eta = eta_new;
253  clu.phi = phi_new;
254  }
255  else
256  break;
257  }
258  else {
259  clu.eta = eta_best;
260  clu.phi = phi_best;
261  improvement = false;
262  }
263  ++nitr;
264  } // end while loop to check for cluster improvements
265  } // end loop over clusters
266 
267  // find the best cluster as the one containing the most tracklets
268  TrkCluster& BestCluster = trkClu[0];
269  for (const TrkCluster& clu : trkClu) {
270  if (clu.ntrks > BestCluster.ntrks) BestCluster = clu;
271  }
272 
273  // store the tracks inside the cluster
274  std::vector<Tracklet> unusedTracks;
275  for (const Tracklet& trk : tracks) {
276  double dEta = BestCluster.eta - trk.globalPosition().eta();
277  double dPhi = xAOD::P4Helpers::deltaPhi(BestCluster.phi , trk.globalPosition().phi());
278  if (std::abs(dEta) < m_ClusterdEta && std::abs(dPhi) < m_ClusterdPhi)
279  BestCluster.tracks.push_back(trk);
280  else
281  unusedTracks.push_back(trk);
282  }
283  // return the best cluster and the unused tracklets
284  tracks = std::move(unusedTracks);
285  return BestCluster;
286  }
287 
288  //** ----------------------------------------------------------------------------------------------------------------- **//
289 
290  std::vector<Muon::MSVertexRecoTool::TrkCluster> MSVertexRecoTool::findTrackClusters(const std::vector<Tracklet>& tracks) const {
291  // only clusters with 3 or more tracklets are returned
292  std::vector<Tracklet> trks = tracks;
293  std::vector<TrkCluster> clusters;
294  // keep making clusters until there are no more possible
295  while (true) {
296  if (trks.size() < 3) break;
297  std::optional<TrkCluster> clust = ClusterizeTracks(trks);
298  if (clust && clust->ntrks>=3) clusters.push_back(clust.value());
299  else break;
300  }
301 
302  return clusters;
303  }
304 
305  //** ----------------------------------------------------------------------------------------------------------------- **//
306 
307  void MSVertexRecoTool::MSVxFinder(const std::vector<Tracklet>& tracklets, std::unique_ptr<MSVertex>& vtx,
308  const EventContext& ctx) const {
309  int nTrkToVertex(0);
310  double NominalAngle(m_TrackPhiAngle.value()), RotationAngle(m_TrackPhiAngle.value() + m_TrackPhiRotation.value());
311 
312  Amg::Vector3D aveTrkPos(0, 0, 0);
313  for (const Tracklet &trk : tracklets) aveTrkPos += trk.globalPosition();
314  aveTrkPos /= tracklets.size();
315 
316  // calculate the two angles (theta & phi)
317  double avePhi = aveTrkPos.phi();
318  double LoF = std::atan2(aveTrkPos.perp(), aveTrkPos.z()); // Line of Flight (theta)
319  avePhi = vxPhiFinder(std::abs(LoF), avePhi, ctx);
320 
321  // find the positions of the radial planes
322  std::vector<double> Rpos;
323  double RadialDist = m_VertexMaxRadialPlane - m_VertexMinRadialPlane;
324  double LoFdist = std::abs(RadialDist / std::sin(LoF));
325  int nplanes = LoFdist / m_VxPlaneDist + 1;
326  double PlaneSpacing = std::abs(m_VxPlaneDist / std::cos(LoF));
327  for (int k = 0; k < nplanes; ++k) Rpos.push_back(m_VertexMinRadialPlane + PlaneSpacing * k);
328 
329  // loop on barrel tracklets and create two types of track parameters -- nominal and phi shifted tracklets
330  std::array< std::vector<std::unique_ptr<Trk::TrackParameters>>, MAXPLANES> TracksForVertexing{}; // vector of tracklets to be used at each vertex plane
331  std::array< std::vector<std::unique_ptr<Trk::TrackParameters>>, MAXPLANES> TracksForErrors{}; // vector of tracklets to be used for uncertainty at each vertex plane
332  std::array< std::vector<bool>, MAXPLANES> isNeutralTrack{};
333 
334  for (const Tracklet &trk : tracklets) {
335  if (m_idHelperSvc->isEndcap(trk.muonIdentifier())) continue;
336  ++nTrkToVertex;
337  // coordinate transform variables
338  Amg::Vector3D trkgpos(trk.globalPosition().perp() * std::cos(avePhi),
339  trk.globalPosition().perp() * std::sin(avePhi),
340  trk.globalPosition().z());
341  double x0 = trkgpos.x();
342  double y0 = trkgpos.y();
343  double r0 = trkgpos.perp();
344 
345  // decide which way the tracklet gets rotated -- positive or negative phi
346  double anglesign = xAOD::P4Helpers::deltaPhi(trk.globalPosition().phi(), avePhi) < 0 ? -1.0 : 1.0;
347  double NominalTrkAng = anglesign * NominalAngle; // in case there is a nominal tracklet angle
348  double MaxTrkAng = anglesign * RotationAngle; // the rotated tracklet phi position
349 
350  // loop over the radial planes
351  for (int k = 0; k < nplanes; ++k) {
352  // only use tracklets that start AFTER the vertex plane
353  if (Rpos[k] > trk.globalPosition().perp()) break;
354 
355  // nominal tracks for vertexing
356  double Xp = Rpos[k] * std::cos(avePhi);
357  double Yp = Rpos[k] * std::sin(avePhi);
358  // in case there is a nominal opening angle, calculate tracklet direction
359  // the tracklet must cross the candidate vertex plane at the correct phi
360  double DelR = std::hypot(x0 - Xp, y0 - Yp) / std::cos(NominalAngle);
361  double X1 = DelR * std::cos(NominalTrkAng + avePhi) + Xp;
362  double Y1 = DelR * std::sin(NominalTrkAng + avePhi) + Yp;
363  double R1 = std::hypot(X1, Y1);
364  double Norm = r0 / R1;
365  X1 = X1 * Norm;
366  Y1 = Y1 * Norm;
367  double Dirmag = std::hypot(X1 - Xp, Y1 - Yp);
368  double Xdir = (X1 - Xp) / Dirmag;
369  double Ydir = (Y1 - Yp) / Dirmag;
370  double trkpx = Xdir * trk.momentum().perp();
371  double trkpy = Ydir * trk.momentum().perp();
372  double trkpz = trk.momentum().z();
373 
374  // check if the tracklet has a charge & momentum measurement -- if not, set charge=1 so extrapolator will work
375  double charge = trk.charge();
376  if (std::abs(charge) < 0.1) {
377  charge = 1; // for "straight" tracks, set charge = 1
378  isNeutralTrack[k].push_back(true);
379  } else
380  isNeutralTrack[k].push_back(false);
381 
382  // store the tracklet as a Trk::Perigee
383  Amg::Vector3D trkmomentum(trkpx, trkpy, trkpz);
384  Amg::Vector3D trkgpos(X1, Y1, trk.globalPosition().z());
385  AmgSymMatrix(5) covariance = AmgSymMatrix(5)(trk.errorMatrix());
386  TracksForVertexing[k].push_back(std::make_unique<Trk::Perigee>(0., 0., trkmomentum.phi(), trkmomentum.theta(), charge / trkmomentum.mag(), Trk::PerigeeSurface(trkgpos), covariance));
387 
388  // tracks for errors -- rotate the plane & recalculate the tracklet parameters
389  double xp = Rpos[k] * std::cos(avePhi);
390  double yp = Rpos[k] * std::sin(avePhi);
391  double delR = std::hypot(x0 - xp, y0 - yp) / std::cos(RotationAngle);
392  double x1 = delR * std::cos(MaxTrkAng + avePhi) + xp;
393  double y1 = delR * std::sin(MaxTrkAng + avePhi) + yp;
394  double r1 = std::hypot(x1, y1);
395  double norm = r0 / r1;
396  x1 = x1 * norm;
397  y1 = y1 * norm;
398  double dirmag = std::hypot(x1 - xp, y1 - yp);
399  double xdir = (x1 - xp) / dirmag;
400  double ydir = (y1 - yp) / dirmag;
401  double errpx = xdir * trk.momentum().perp();
402  double errpy = ydir * trk.momentum().perp();
403  double errpz = trk.momentum().z();
404 
405  // store the tracklet as a Trk::Perigee
406  AmgSymMatrix(5) covariance2 = AmgSymMatrix(5)(trk.errorMatrix());
407  Amg::Vector3D trkerrmom(errpx, errpy, errpz);
408  Amg::Vector3D trkerrpos(x1, y1, trk.globalPosition().z());
409  TracksForErrors[k].push_back(std::make_unique<Trk::Perigee>(0., 0., trkerrmom.phi(), trkerrmom.theta(), charge / trkerrmom.mag(), Trk::PerigeeSurface(trkerrpos), covariance2));
410  } // end loop on vertex planes
411  } // end loop on tracks
412 
413  // return if there are not enough tracklets
414  if (nTrkToVertex < 3) return;
415 
416  // calculate the tracklet positions and uncertainty on each surface
417  bool boundaryCheck = true;
418  std::array<std::vector<double>, MAXPLANES> ExtrapZ{}; // extrapolated z position
419  std::array<std::vector<double>, MAXPLANES> dlength{}; // extrapolated z position uncertainty
420  std::array<std::vector<std::pair<unsigned int, unsigned int>>, MAXPLANES> UsedTracks{};
421  std::array<std::vector<bool>, MAXPLANES> ExtrapSuc{}; // did the extrapolation succeed?
422  std::vector<std::unique_ptr<MSVertex>> vertices; vertices.reserve(nplanes);
423  std::array<std::vector<double>, MAXPLANES> sigmaZ{}; // total uncertainty at each plane
424  std::array<std::vector<Amg::Vector3D>, MAXPLANES> pAtVx{}; // tracklet momentum expressed at the plane
425 
426  // extrapolate tracklates and store results at each radial plane
427  for (int k = 0; k < nplanes; ++k) { // loop on planes
428  double rpos = Rpos[k];
429  for (unsigned int i = 0; i < TracksForVertexing[k].size(); ++i) { // loop on tracklets
430  // at least three tracklets per plane are needed
431  if (TracksForVertexing[k].size() < 3) break;
432 
433  Amg::Transform3D surfaceTransformMatrix;
434  surfaceTransformMatrix.setIdentity();
435  Trk::CylinderSurface cyl(surfaceTransformMatrix, rpos, 10000.); // create the surface
436  // extrapolate to the surface
437  std::unique_ptr<const Trk::TrackParameters> extrap_par(
438  m_extrapolator->extrapolate(ctx,
439  *TracksForVertexing[k].at(i), cyl, Trk::anyDirection, boundaryCheck, Trk::muon));
440 
441  const Trk::AtaCylinder* extrap = dynamic_cast<const Trk::AtaCylinder*>(extrap_par.get());
442 
443  if (extrap) {
444  // if the track is neutral just store the uncertainty due to angular uncertainty of the orignal tracklet
445  if (isNeutralTrack[k].at(i)) {
446  double pTot = std::hypot(TracksForVertexing[k].at(i)->momentum().perp(), TracksForVertexing[k].at(i)->momentum().z());
447  double dirErr = Amg::error(*TracksForVertexing[k].at(i)->covariance(), Trk::theta);
448  double extrapRdist = TracksForVertexing[k].at(i)->position().perp() - Rpos[k];
449  double sz = std::abs(20 * dirErr * extrapRdist * std::pow(pTot,2) / std::pow(TracksForVertexing[k].at(i)->momentum().perp(), 2));
450  double ExtrapErr = sz;
451  if (ExtrapErr > m_MaxTrackUncert)
452  ExtrapSuc[k].push_back(false);
453  else {
454  ExtrapSuc[k].push_back(true);
455  std::pair<unsigned int, unsigned int> trkmap(ExtrapZ[k].size(), i);
456  UsedTracks[k].push_back(trkmap);
457  ExtrapZ[k].push_back(extrap->localPosition().y());
458  sigmaZ[k].push_back(sz);
459  pAtVx[k].push_back(extrap->momentum());
460  dlength[k].push_back(0);
461  }
462  } // end neutral tracklets
463  // if the tracklet has a momentum measurement
464  else {
465  // now extrapolate taking into account the extra path length & differing magnetic field
466  Amg::Transform3D srfTransMat2;
467  srfTransMat2.setIdentity();
468  Trk::CylinderSurface cyl2(srfTransMat2, rpos, 10000.);
469  std::unique_ptr<const Trk::TrackParameters> extrap_par2(
470  m_extrapolator->extrapolate(ctx,
471  *TracksForErrors[k].at(i), cyl, Trk::anyDirection, boundaryCheck, Trk::muon));
472  const Trk::AtaCylinder* extrap2 = dynamic_cast<const Trk::AtaCylinder*>(extrap_par2.get());
473 
474  if (extrap2) {
475  double sz = Amg::error(*extrap->covariance(), Trk::locY);
476  double zdiff = extrap->localPosition().y() - extrap2->localPosition().y();
477  double ExtrapErr = std::hypot(sz, zdiff);
478  if (ExtrapErr > m_MaxTrackUncert)
479  ExtrapSuc[k].push_back(false);
480  else {
481  // iff both extrapolations succeed && error is acceptable, store the information
482  ExtrapSuc[k].push_back(true);
483  std::pair<unsigned int, unsigned int> trkmap(ExtrapZ[k].size(), i);
484  UsedTracks[k].push_back(trkmap);
485  ExtrapZ[k].push_back(extrap->localPosition().y());
486  sigmaZ[k].push_back(sz);
487  pAtVx[k].push_back(extrap->momentum());
488  dlength[k].push_back(zdiff);
489  }
490  } else
491  ExtrapSuc[k].push_back(false); // not possible to calculate the uncertainty -- do not use tracklet in vertex
492  }
493  }
494  // not possible to extrapolate the tracklet
495  else
496  ExtrapSuc[k].push_back(false);
497  } // loop on tracklets
498  } // loop on radial planes
499 
500 
501  // perform the vertex fit
502  std::array<std::vector<Amg::Vector3D>, MAXPLANES> trkp{}; // tracklet momentum
503  // loop on planes
504  for (int k = 0; k < nplanes; ++k) {
505  if (ExtrapZ[k].size() < 3) continue; // require at least 3 tracklets to build a vertex
506  // initialize the variables used in the routine
507  double zLoF = Rpos[k] / std::tan(LoF);
508  double dzLoF(10);
509  double aveZpos(0), posWeight(0);
510  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) {
511  double ExtrapErr = std::hypot(sigmaZ[k][i], dlength[k][i], dzLoF);
512  if (isNeutralTrack[k][i]) ExtrapErr = std::hypot(sigmaZ[k][i], dzLoF);
513  aveZpos += ExtrapZ[k][i] / std::pow(ExtrapErr,2);
514  posWeight += 1. / std::pow(ExtrapErr,2);
515  }
516  // calculate the weighted average position of the tracklets
517  zLoF = aveZpos / posWeight;
518  double zpossigma(dzLoF), Chi2(0), Chi2Prob(-1);
519  unsigned int Nitr(0);
520  std::vector<unsigned int> vxtracks; // tracklets to be used in the vertex routine
521  std::vector<bool> blocklist(ExtrapZ[k].size(), false); // tracklets that do not belong to the vertex
522 
523  // minimum chi^2 iterative fit
524  while (true) {
525  vxtracks.clear(); trkp[k].clear();
526  int tmpnTrks(0);
527  double tmpzLoF(0), tmpzpossigma(0), tmpchi2(0), posWeight(0), worstdelz(0);
528  unsigned int iworst(0); // tracklet index contributing to the vertex chi2 the most
529  // loop on the tracklets, find the chi^2 contribution from each tracklet
530  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) {
531  if (blocklist[i]) continue;
532  trkp[k].push_back(pAtVx[k][i]);
533  double delz = zLoF - ExtrapZ[k][i];
534  double ExtrapErr = std::hypot(sigmaZ[k][i], dlength[k][i], dzLoF);
535  double trkchi2 = std::pow(delz,2) / std::pow(ExtrapErr,2);
536  if (trkchi2 > worstdelz) {
537  iworst = i;
538  worstdelz = trkchi2;
539  }
540  tmpzLoF += ExtrapZ[k][i] / std::pow(ExtrapErr,2);
541  posWeight += 1. / std::pow(ExtrapErr,2);
542  tmpzpossigma += std::pow(delz,2);
543  tmpchi2 += trkchi2;
544  ++tmpnTrks;
545  }
546 
547  if (tmpnTrks < 3) break; // stop searching for a vertex at this plane
548  tmpzpossigma = std::sqrt(tmpzpossigma / (double)tmpnTrks);
549  zLoF = tmpzLoF / posWeight;
550  zpossigma = tmpzpossigma;
551  double testChi2 = TMath::Prob(tmpchi2, tmpnTrks - 1);
552  if (testChi2 < m_VxChi2ProbCUT)
553  blocklist[iworst] = true;
554  else {
555  Chi2 = tmpchi2;
556  Chi2Prob = testChi2;
557  // loop on the tracklets and find all that belong to the vertex
558  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) {
559  double delz = zLoF - ExtrapZ[k][i];
560  double ExtrapErr = std::hypot(sigmaZ[k][i], dlength[k][i], dzLoF);
561  double trkErr = std::hypot(ExtrapErr, zpossigma) + 0.001;
562  double trkNsigma = std::abs(delz / trkErr);
563  if (trkNsigma < 3) vxtracks.push_back(i);
564  }
565  break; // found a vertex, stop removing tracklets! Break chi^2 iterative fit at this radial plane
566  }
567  if (Nitr >= (ExtrapZ[k].size() - 3)) break; // stop searching for a vertex at this plane
568  ++Nitr;
569  } // end while
570 
571  if (vxtracks.size() < 3) continue;
572 
573  // create TrackParticle vector for all tracklets used in the vertex fit
574  std::vector<const xAOD::TrackParticle*> vxTrackParticles;
575  vxTrackParticles.reserve(vxtracks.size());
576  for (std::vector<unsigned int>::iterator vxtrk = vxtracks.begin(); vxtrk != vxtracks.end(); ++vxtrk) {
577  for (unsigned int i = 0; i < UsedTracks[k].size(); ++i) {
578  if ((*vxtrk) != UsedTracks[k].at(i).first) continue;
579  const Tracklet& trklt = tracklets.at(UsedTracks[k].at(i).second);
580  vxTrackParticles.push_back(trklt.getTrackParticle());
581  break; // found the tracklet used for the vertex reconstruction in the tracklet collection. Hence can stop looking
582  }
583  }
584  Amg::Vector3D position(Rpos[k] * std::cos(avePhi), Rpos[k] * std::sin(avePhi), zLoF);
585  vertices.push_back(std::make_unique<MSVertex>(1, position, vxTrackParticles, Chi2Prob, Chi2, 0, 0, 0));
586  } // end loop on Radial planes
587 
588  if (vertices.empty()) return;
589 
590  // loop on the vertex candidates and select the best based on max n(tracks) and max chi^2 probability
591 
592  unsigned int bestVx(0);
593  for (unsigned int k = 1; k < vertices.size(); ++k) {
594  if (vertices[k]->getChi2Probability() < m_VxChi2ProbCUT || vertices[k]->getNTracks() < 3) continue;
595  if (vertices[k]->getNTracks() < vertices[bestVx]->getNTracks()) continue;
596  if (vertices[k]->getNTracks() == vertices[bestVx]->getNTracks() &&
597  vertices[k]->getChi2Probability() < vertices[bestVx]->getChi2Probability())
598  continue;
599  bestVx = k;
600  }
601  vtx = std::make_unique<MSVertex>(*vertices[bestVx]);
602  vertices.clear(); // cleanup
603  }
604 
605  //** ----------------------------------------------------------------------------------------------------------------- **//
606 
607  void MSVertexRecoTool::MSStraightLineVx(const std::vector<Tracklet>& trks, std::unique_ptr<MSVertex>& vtx,
608  const EventContext& ctx) const {
609  // Running set of all vertices found. The inner set is the indices of trks that are used to make the vertex
610  std::set<std::set<int> > prelim_vx;
611 
612  // We don't consider all 3-tracklet combinations when a high number of tracklets is found
613  // Faster method is used for > 40 tracklets
614  if (trks.size() > 40) {
615  MSStraightLineVx_oldMethod(trks, vtx, ctx);
616  return;
617  }
618 
619  // Okay, if we get here then we know there's 40 or fewer tracklets in the cluster.
620  // Make a list of all 3-tracklet combinations that make vertices
621  for (unsigned int i = 0; i < trks.size() - 2; ++i) {
622  for (unsigned int j = i + 1; j < trks.size() - 1; ++j) {
623  for (unsigned int k = j + 1; k < trks.size(); ++k) {
624  std::set<int> tmpTracks;
625  tmpTracks.insert(i);
626  tmpTracks.insert(j);
627  tmpTracks.insert(k);
628 
629  Amg::Vector3D MyVx;
630  MyVx = VxMinQuad(getTracklets(trks, tmpTracks));
631  if (MyVx.perp() < 10000 && std::abs(MyVx.z()) > 7000 && std::abs(MyVx.z()) < 15000 &&
632  !EndcapHasBadTrack(getTracklets(trks, tmpTracks), MyVx))
633  prelim_vx.insert(tmpTracks);
634  }
635  }
636  }
637 
638  // If no preliminary vertices were found from 3 tracklets, then there is no vertex and we are done.
639  if (prelim_vx.empty()) return;
640 
641  // The remaining algorithm is very time consuming for large numbers of tracklets. To control this,
642  // we run the old algorithm when there are too many tracklets and a vertex is found.
643  if (trks.size() <= 20) {
644  std::set<std::set<int> > new_prelim_vx = prelim_vx;
645  std::set<std::set<int> > old_prelim_vx;
646 
647  int foundNewVx = true;
648  while (foundNewVx) {
649  foundNewVx = false;
650 
651  old_prelim_vx = new_prelim_vx;
652  new_prelim_vx.clear();
653 
654  for (std::set<std::set<int> >::iterator itr = old_prelim_vx.begin(); itr != old_prelim_vx.end(); ++itr) {
655  for (unsigned int i_trks = 0; i_trks < trks.size(); ++i_trks) {
656  std::set<int> tempCluster = *itr;
657  if (tempCluster.insert(i_trks).second) {
658  Amg::Vector3D MyVx = VxMinQuad(getTracklets(trks, tempCluster));
659  if (MyVx.perp() < 10000 && std::abs(MyVx.z()) > 7000 && std::abs(MyVx.z()) < 15000 &&
660  !EndcapHasBadTrack(getTracklets(trks, tempCluster), MyVx)) {
661  new_prelim_vx.insert(tempCluster);
662  prelim_vx.insert(tempCluster);
663  foundNewVx = true;
664  }
665  }
666  }
667  }
668  }
669  } else {
670  // Since there are 20 or more tracklets, we're going to use the old MSVx finding method. Note that
671  // if the old method fails, we do not return here; in this case a 3-tracklet vertex that was found
672  // earlier in this algorithm will be returned
673  MSStraightLineVx_oldMethod(trks, vtx, ctx);
674  if (vtx) return;
675  }
676 
677  // Find the preliminary vertex with the maximum number of tracklets - that is the final vertex. If
678  // multiple preliminary vertices with same number of tracklets, the first one found is returned
679  std::set<std::set<int> >::iterator prelim_vx_max = prelim_vx.begin();
680  for (std::set<std::set<int> >::iterator itr = prelim_vx.begin(); itr != prelim_vx.end(); ++itr) {
681  if ((*itr).size() > (*prelim_vx_max).size()) prelim_vx_max = itr;
682  }
683 
684  std::vector<Tracklet> tracklets = getTracklets(trks, *prelim_vx_max);
685  // use tracklets to estimate the line of flight of decaying particle
686  double aveX(0);
687  double aveY(0);
688  for (const Tracklet &trk : tracklets) {
689  aveX += trk.globalPosition().x();
690  aveY += trk.globalPosition().y();
691  }
692 
693  Amg::Vector3D MyVx = VxMinQuad(tracklets);
694  double vxtheta = std::atan2(MyVx.x(), MyVx.z());
695  double tracklet_vxphi = std::atan2(aveY, aveX);
696  double vxphi = vxPhiFinder(std::abs(vxtheta), tracklet_vxphi, ctx);
697 
698  Amg::Vector3D vxpos(MyVx.x() * std::cos(vxphi), MyVx.x() * std::sin(vxphi), MyVx.z());
699 
700  std::vector<const xAOD::TrackParticle*> vxTrackParticles;
701  for (const Tracklet &trk : tracklets) vxTrackParticles.push_back(trk.getTrackParticle());
702 
703  vtx = std::make_unique<MSVertex>(2, vxpos, vxTrackParticles, 1, vxTrackParticles.size(), 0, 0, 0);
704  }
705 
706  //** ----------------------------------------------------------------------------------------------------------------- **//
707 
708  // vertex finding routine for the endcap
709  void MSVertexRecoTool::MSStraightLineVx_oldMethod(const std::vector<Tracklet>& trks, std::unique_ptr<MSVertex>& vtx,
710  const EventContext& ctx) const {
711  // find the line of flight
712  double aveX(0), aveY(0);
713  for (const Tracklet &trk : trks) {
714  aveX += trk.globalPosition().x();
715  aveY += trk.globalPosition().y();
716  }
717  double vxphi = std::atan2(aveY, aveX);
718 
719  Amg::Vector3D MyVx(0, 0, 0);
720  std::vector<Tracklet> tracks = RemoveBadTrk(trks, MyVx);
721  if (tracks.size() < 2) return;
722 
723  // remove back tracks one by one until non are considered bad (large distance from the vertex)
724  while (true) {
725  MyVx = VxMinQuad(tracks);
726  std::vector<Tracklet> Tracks = RemoveBadTrk(tracks, MyVx);
727  if (tracks.size() == Tracks.size()) break;
728  tracks = std::move(Tracks);
729  }
730 
731  if (tracks.size() >= 3 && MyVx.x() > 0) {
732  double vxtheta = std::atan2(MyVx.x(), MyVx.z());
733  vxphi = vxPhiFinder(std::abs(vxtheta), vxphi, ctx);
734  Amg::Vector3D vxpos(MyVx.x() * std::cos(vxphi), MyVx.x() * std::sin(vxphi), MyVx.z());
735 
736  std::vector<const xAOD::TrackParticle*> vxTrackParticles;
737  for (const Tracklet &trk : tracks) vxTrackParticles.push_back(trk.getTrackParticle());
738 
739  vtx = std::make_unique<MSVertex>(2, vxpos, vxTrackParticles, 1, (double)vxTrackParticles.size(), 0, 0, 0);
740  }
741  }
742 
743  //** ----------------------------------------------------------------------------------------------------------------- **//
744 
745  std::vector<Tracklet> MSVertexRecoTool::RemoveBadTrk(const std::vector<Tracklet>& tracks, const Amg::Vector3D& Vx) const {
746  // Removes at most one track with the largest distance to the vertex above the predefined threshold set by m_MaxTollDist
747  // check for default vertex
748  if (Vx.x() == 0 && Vx.z() == 0) return tracks;
749 
750  double WorstTrkDist = m_MaxTollDist;
751  unsigned int iWorstTrk = -1;
752  for (unsigned int i = 0; i < tracks.size(); ++i) {
753  double TrkSlope = std::tan(tracks.at(i).getML1seg().alpha());
754  double TrkInter = tracks.at(i).getML1seg().globalPosition().perp() - tracks.at(i).getML1seg().globalPosition().z() * TrkSlope;
755  double dist = std::abs((TrkSlope * Vx.z() - Vx.x() + TrkInter) / std::hypot(TrkSlope, 1));
756  if (dist > m_MaxTollDist && dist > WorstTrkDist) {
757  iWorstTrk = i;
758  WorstTrkDist = dist;
759  }
760  }
761 
762  // Remove the worst track from the list
763  std::vector<Tracklet> Tracks;
764  for (unsigned int i = 0; i < tracks.size(); ++i) {
765  if (i != iWorstTrk) Tracks.push_back(tracks.at(i));
766  }
767  return Tracks;
768  }
769 
770  std::vector<Tracklet> MSVertexRecoTool::getTracklets(const std::vector<Tracklet>& trks, const std::set<int>& tracklet_subset) const {
771  std::vector<Tracklet> returnVal;
772  for (std::set<int>::const_iterator itr = tracklet_subset.cbegin(); itr != tracklet_subset.cend(); ++itr) {
773  if ((unsigned int)*itr > trks.size()) ATH_MSG_ERROR("ERROR - Index out of bounds in getTracklets");
774  returnVal.push_back(trks.at(*itr));
775  }
776 
777  return returnVal;
778  }
779 
780  //** ----------------------------------------------------------------------------------------------------------------- **//
781 
782  bool MSVertexRecoTool::EndcapHasBadTrack(const std::vector<Tracklet>& tracks, const Amg::Vector3D& Vx) const {
783  if (Vx.x() == 0 && Vx.z() == 0) return true;
784  // return true a track is further away from the vertex than m_MaxTollDist
785  for (const Tracklet &track : tracks) {
786  double TrkSlope = std::tan(track.getML1seg().alpha());
787  double TrkInter = track.getML1seg().globalPosition().perp() - track.getML1seg().globalPosition().z() * TrkSlope;
788  double dist = std::abs((TrkSlope * Vx.z() - Vx.x() + TrkInter) / std::hypot(TrkSlope, 1));
789  if (dist > m_MaxTollDist) { return true; }
790  }
791 
792  // No tracks found that are too far, so it is okay.
793  return false;
794  }
795 
796  //** ----------------------------------------------------------------------------------------------------------------- **//
797 
798  void MSVertexRecoTool::dressVtxHits(xAOD::Vertex* xAODVx, const std::vector<SG::AuxElement::Accessor<int>>& accs, const std::vector<int>& hits) const {
799  unsigned int i{0};
800  for (const SG::AuxElement::Accessor<int> &acc : accs) {
801  acc(*xAODVx) = hits[i];
802  ++i;
803  }
804 
805  return;
806  }
807 
808  //** ----------------------------------------------------------------------------------------------------------------- **//
809 
810  StatusCode MSVertexRecoTool::FillOutputContainer(const std::vector<std::unique_ptr<MSVertex>>& vertices,
811  SG::WriteHandle<xAOD::VertexContainer>& xAODVxContainer) const {
812  for (const std::unique_ptr<MSVertex> &vtx : vertices){
813  xAOD::Vertex* xAODVx = new xAOD::Vertex();
814  xAODVx->makePrivateStore();
816  xAODVx->setPosition(vtx->getPosition());
817  xAODVx->setFitQuality(vtx->getChi2(), vtx->getNTracks() - 1);
818 
819  // link TrackParticle to vertex
820  for (const xAOD::TrackParticle *trk : *(vtx->getTracks())) {
821  ElementLink<xAOD::TrackParticleContainer> link_trk(*(dynamic_cast<const xAOD::TrackParticleContainer *>(trk->container())), trk->index());
822  if (link_trk.isValid()) xAODVx->addTrackAtVertex(link_trk);
823  }
824 
825  // store the new xAOD vertex
826  xAODVxContainer->push_back(xAODVx);
827 
828  // dress the vertex with the hit counts
829  dressVtxHits(xAODVx, m_nMDT_accs, vtx->getNMDT_all());
830  dressVtxHits(xAODVx, m_nRPC_accs, vtx->getNRPC_all());
831  dressVtxHits(xAODVx, m_nTGC_accs, vtx->getNTGC_all());
832  }
833 
834  return StatusCode::SUCCESS;
835  }
836 
837  //** ----------------------------------------------------------------------------------------------------------------- **//
838 
839  // core algorithm for endcap vertex reconstruction
840  Amg::Vector3D MSVertexRecoTool::VxMinQuad(const std::vector<Tracklet>& tracks) {
841  double s(0.), sx(0.), sy(0.), sxy(0.), sxx(0.), d(0.);
842  double sigma = 1.;
843  for (const Tracklet &track : tracks) {
844  double TrkSlope = std::tan(track.getML1seg().alpha());
845  double TrkInter = track.getML1seg().globalPosition().perp() - track.getML1seg().globalPosition().z() * TrkSlope;
846  s += 1. / std::pow(sigma,2);
847  sx += TrkSlope / std::pow(sigma,2);
848  sxx += std::pow(TrkSlope,2) / std::pow(sigma,2);
849  sy += TrkInter / std::pow(sigma,2);
850  sxy += (TrkSlope * TrkInter) / std::pow(sigma,2);
851  }
852  d = s * sxx - std::pow(sx,2);
853  if (d == 0.) {
854  Amg::Vector3D MyVx(0., 0., 0.); // return 0, no vertex was found.
855  return MyVx;
856  }
857 
858  double Rpos = (sxx * sy - sx * sxy) / d;
859  double Zpos = (sx * sy - s * sxy) / d;
860 
861  Amg::Vector3D MyVx(Rpos, 0, Zpos);
862 
863  return MyVx;
864  }
865 
866  //** ----------------------------------------------------------------------------------------------------------------- **//
867 
868  // vertex phi location -- determined from the RPC/TGC hits
869  double MSVertexRecoTool::vxPhiFinder(const double theta, const double phi, const EventContext& ctx) const {
870  double nmeas(0), sinphi(0), cosphi(0);
871  if (theta == 0) {
872  ATH_MSG_WARNING("vxPhiFinder() called with theta=" << theta << " and phi=" << phi << ", return 0");
873  return 0;
874  } else if (theta > M_PI) {
875  ATH_MSG_WARNING("vxPhiFinder() called with theta=" << std::setprecision(15) << theta << " and phi=" << phi
876  << ", (theta>M_PI), return 0");
877  return 0;
878  }
879  double tanThetaHalf = std::tan(0.5 * theta);
880  if (tanThetaHalf <= 0) {
881  ATH_MSG_WARNING("vxPhiFinder() called with theta=" << std::setprecision(15) << theta << " and phi=" << phi
882  << ", resulting in tan(0.5*theta)<=0, return 0");
883  return 0;
884  }
885  double eta = -std::log(tanThetaHalf);
886  if (std::abs(eta) < 1.5) {
888  if (!rpcTES.isValid()) {
889  ATH_MSG_WARNING("No RpcPrepDataContainer found in SG!");
890  return 0;
891  }
892  for (const Muon::RpcPrepDataCollection* RPC_coll : *rpcTES){
893  for (const Muon::RpcPrepData* rpc : *RPC_coll){
894  if (!m_idHelperSvc->rpcIdHelper().measuresPhi(rpc->identify())) continue;
895  double rpcEta = rpc->globalPosition().eta();
896  double rpcPhi = rpc->globalPosition().phi();
897  double DR = xAOD::P4Helpers::deltaR(eta, phi, rpcEta, rpcPhi);
898  if (DR >= 0.6) continue;
899  sinphi += std::sin(rpcPhi);
900  cosphi += std::cos(rpcPhi);
901  ++nmeas;
902  }
903  }
904  }
905  if (std::abs(eta) > 0.5) {
907  if (!tgcTES.isValid()) {
908  ATH_MSG_WARNING("No TgcPrepDataContainer found in SG!");
909  return 0;
910  }
911  for (const Muon::TgcPrepDataCollection* TGC_coll : *tgcTES){
912  for (const Muon::TgcPrepData* tgc : *TGC_coll){
913  if (!m_idHelperSvc->tgcIdHelper().isStrip(tgc->identify())) continue;
914  double tgcEta = tgc->globalPosition().eta();
915  double tgcPhi = tgc->globalPosition().phi();
916  double DR = xAOD::P4Helpers::deltaR(eta, phi, tgcEta, tgcPhi);
917  if (DR >= 0.6) continue;
918  sinphi += std::sin(tgcPhi);
919  cosphi += std::cos(tgcPhi);
920  ++nmeas;
921  }
922  }
923  }
924 
925  double vxphi = phi;
926  if (nmeas > 0) vxphi = std::atan2(sinphi / nmeas, cosphi / nmeas);
927  return vxphi;
928  }
929 
930  //** ----------------------------------------------------------------------------------------------------------------- **//
931 
932  void MSVertexRecoTool::HitCounter(MSVertex* MSRecoVx, const EventContext& ctx) const {
933  // count the hits (MDT, RPC & TGC) around the vertex and split them by layer
934  int nHighOccupancy(0);
935  int stationRegion(-1);
936  // Amg::Vector3D.eta() will crash via floating point exception if both x() and y() are zero (eta=inf)
937  // thus, check it manually here:
938  const Amg::Vector3D msVtxPos = MSRecoVx->getPosition();
939  if (msVtxPos.x() == 0 && msVtxPos.y() == 0 && msVtxPos.z() != 0) {
940  ATH_MSG_WARNING("given MSVertex has position x=y=0 and z!=0, eta() method will cause FPE, returning...");
941  return;
942  }
943 
944  // MDTs -- count the number around the vertex
946  if (!mdtTES.isValid()) ATH_MSG_ERROR("Unable to retrieve the MDT hits");
947  int nmdt(0), nmdt_inwards(0), nmdt_I(0), nmdt_E(0), nmdt_M(0), nmdt_O(0);
948  // loop on the MDT collections, a collection corresponds to a chamber
949  for(const Muon::MdtPrepDataCollection* MDT_coll : *mdtTES){
950  if (MDT_coll->empty()) continue;
951  Muon::MdtPrepDataCollection::const_iterator mdtItr = MDT_coll->begin();
952  Amg::Vector3D ChamberCenter = (*mdtItr)->detectorElement()->center();
953  double deta = msVtxPos.eta() - ChamberCenter.eta();
954  if (std::abs(deta) > m_nMDTHitsEta) continue;
955  double dphi = xAOD::P4Helpers::deltaPhi(msVtxPos.phi(),ChamberCenter.phi());
956  if (std::abs(dphi) > m_nMDTHitsPhi) continue;
957 
958  Identifier id = (*mdtItr)->identify();
959  stationRegion = m_idHelperSvc->mdtIdHelper().stationRegion(id);
960  auto [tubeLayerMin, tubeLayerMax] = m_idHelperSvc->mdtIdHelper().tubeLayerMinMax(id);
961  auto [tubeMin, tubeMax] = m_idHelperSvc->mdtIdHelper().tubeMinMax(id);
962  double nTubes = (tubeLayerMax - tubeLayerMin + 1) * (tubeMax - tubeMin + 1);
963 
964  int nChHits(0), nChHits_inwards(0);
965  // loop on the MDT hits in the chamber
966  for (const Muon::MdtPrepData* mdt : *MDT_coll){
967  if (mdt->adc() < 50) continue;
968  if (mdt->status() != 1) continue;
969  if (mdt->localPosition()[Trk::locR] == 0.) continue;
970  ++nChHits;
971  if (mdt->globalPosition().mag() < msVtxPos.mag()) ++nChHits_inwards;
972  }
973  nmdt += nChHits;
974  nmdt_inwards += nChHits_inwards;
975  double ChamberOccupancy = nChHits / nTubes;
976  if (ChamberOccupancy > m_ChamberOccupancyMin) ++nHighOccupancy;
977 
978  if (stationRegion == 0) nmdt_I += nChHits;
979  else if (stationRegion == 1) nmdt_E += nChHits;
980  else if (stationRegion == 2) nmdt_M += nChHits;
981  else if (stationRegion == 3) nmdt_O += nChHits;
982  }
983  ATH_MSG_DEBUG("Found " << nHighOccupancy << " chambers near the MS vertex with occupancy greater than " << m_ChamberOccupancyMin);
984  if (nHighOccupancy < m_minHighOccupancyChambers) return;
985 
986  // RPC -- count the number around the vertex
988  if (!rpcTES.isValid()) ATH_MSG_ERROR("Unable to retrieve the RPC hits");
989  int nrpc(0), nrpc_inwards(0), nrpc_I(0), nrpc_E(0), nrpc_M(0), nrpc_O(0);
990  for (const Muon::RpcPrepDataCollection* RPC_coll : *rpcTES){
991  Muon::RpcPrepDataCollection::const_iterator rpcItr = RPC_coll->begin();
992  stationRegion = m_idHelperSvc->rpcIdHelper().stationRegion((*rpcItr)->identify());
993  int nChHits(0), nChHits_inwards(0);
994  for (const Muon::RpcPrepData* rpc : *RPC_coll){
995  double rpcEta = rpc->globalPosition().eta();
996  double rpcPhi = rpc->globalPosition().phi();
997  double DR = xAOD::P4Helpers::deltaR(msVtxPos.eta(), msVtxPos.phi(), rpcEta, rpcPhi);
998  if (DR < m_nTrigHitsdR) {
999  ++nChHits;
1000  if (rpc->globalPosition().mag() < msVtxPos.mag()) ++nChHits_inwards;
1001  }
1002  if (DR > 1.2) break;
1003  }
1004  nrpc += nChHits;
1005  nrpc_inwards += nChHits_inwards;
1006  if (stationRegion == 0) nrpc_I += nChHits;
1007  else if (stationRegion == 1) nrpc_E += nChHits;
1008  else if (stationRegion == 2) nrpc_M += nChHits;
1009  else if (stationRegion == 3) nrpc_O += nChHits;
1010  }
1011 
1012  // TGC -- count the number around the vertex
1014  if (!tgcTES.isValid()) ATH_MSG_ERROR("Unable to retrieve the TGC hits");
1015  int ntgc(0), ntgc_inwards(0), ntgc_I(0), ntgc_E(0), ntgc_M(0), ntgc_O(0);
1016  for (const Muon::TgcPrepDataCollection* TGC_coll : *tgcTES){
1017  Muon::TgcPrepDataCollection::const_iterator tgcItr = TGC_coll->begin();
1018  stationRegion = m_idHelperSvc->tgcIdHelper().stationRegion((*tgcItr)->identify());
1019  int nChHits(0), nChHits_inwards(0);
1020  for (const Muon::TgcPrepData* tgc : *TGC_coll){
1021  double tgcEta = tgc->globalPosition().eta();
1022  double tgcPhi = tgc->globalPosition().phi();
1023  double DR = xAOD::P4Helpers::deltaR(msVtxPos.eta(), msVtxPos.phi(), tgcEta, tgcPhi);
1024  if (DR < m_nTrigHitsdR) {
1025  ++nChHits;
1026  if (tgc->globalPosition().mag() < msVtxPos.mag()) ++nChHits_inwards;
1027  }
1028  if (DR > 1.2) break;
1029  }
1030  ntgc += nChHits;
1031  ntgc_inwards += nChHits_inwards;
1032  if (stationRegion == 0) ntgc_I += nChHits;
1033  else if (stationRegion == 1) ntgc_E += nChHits;
1034  else if (stationRegion == 2) ntgc_M += nChHits;
1035  else if (stationRegion == 3) ntgc_O += nChHits;
1036  }
1037 
1038  // store the hit counts in the MSVertex object
1039  MSRecoVx->setNMDT(nmdt, nmdt_inwards, nmdt_I, nmdt_E, nmdt_M, nmdt_O);
1040  MSRecoVx->setNRPC(nrpc, nrpc_inwards, nrpc_I, nrpc_E, nrpc_M, nrpc_O);
1041  MSRecoVx->setNTGC(ntgc, ntgc_inwards, ntgc_I, ntgc_E, ntgc_M, ntgc_O);
1042  }
1043 
1044 } // namespace Muon
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Muon::MSVertexRecoTool::m_ClusterdEta
Gaudi::Property< double > m_ClusterdEta
Definition: MSVertexRecoTool.h:89
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
ATHRNG::RNGWrapper::setSeed
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition: RNGWrapper.h:169
MSVertex::getNTracks
int getNTracks() const
Definition: MSVertex.cxx:38
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:215
InDetGNNHardScatterSelection::getter_utils::Tracks
std::vector< const xAOD::TrackParticle * > Tracks
Definition: InnerDetector/InDetRecTools/InDetGNNHardScatterSelection/InDetGNNHardScatterSelection/CustomGetterUtils.h:49
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
xAOD::Vertex_v1::setPosition
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
Muon::MSVertexRecoTool::findMSvertices
StatusCode findMSvertices(const std::vector< Tracklet > &tracklets, std::vector< std::unique_ptr< MSVertex >> &vertices, const EventContext &ctx) const override
Definition: MSVertexRecoTool.cxx:55
Muon::MSVertexRecoTool::m_nMDT_accs
std::vector< SG::AuxElement::Accessor< int > > m_nMDT_accs
Definition: MSVertexRecoTool.h:73
fitman.sy
sy
Definition: fitman.py:524
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
pdg_comparison.sigma
sigma
Definition: pdg_comparison.py:324
Tracklet::getTrackParticle
const xAOD::TrackParticle * getTrackParticle() const
Definition: Tracklet.cxx:44
xAOD::Vertex_v1::setFitQuality
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
Definition: Vertex_v1.cxx:150
fitman.sz
sz
Definition: fitman.py:527
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
beamspotman.sigmaZ
sigmaZ
Definition: beamspotman.py:1623
xAOD::Vertex
Vertex_v1 Vertex
Define the latest version of the vertex class.
Definition: Event/xAOD/xAODTracking/xAODTracking/Vertex.h:16
Muon::MSVertexRecoTool::m_maxClusterTracklets
Gaudi::Property< unsigned int > m_maxClusterTracklets
Definition: MSVertexRecoTool.h:84
Muon::MSVertexRecoTool::m_doSystematics
Gaudi::Property< bool > m_doSystematics
Definition: MSVertexRecoTool.h:92
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:38
MSVertex::setNTGC
void setNTGC(const int, const int, const int, const int, const int, const int)
Definition: MSVertex.cxx:63
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:44
Muon::MSVertexRecoTool::m_nMDTHitsEta
Gaudi::Property< double > m_nMDTHitsEta
Definition: MSVertexRecoTool.h:106
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
hist_file_dump.d
d
Definition: hist_file_dump.py:142
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
Muon::MSVertexRecoTool::m_maxGlobalTracklets
Gaudi::Property< unsigned int > m_maxGlobalTracklets
Definition: MSVertexRecoTool.h:83
EventPrimitivesHelpers.h
MSVertex::getChi2Probability
double getChi2Probability() const
Definition: MSVertex.cxx:35
python.compressB64.sx
string sx
Definition: compressB64.py:96
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
M_PI
#define M_PI
Definition: ActiveFraction.h:11
MSVertex::setNMDT
void setNMDT(const int, const int, const int, const int, const int, const int)
Definition: MSVertex.cxx:45
Muon::MSVertexRecoTool::RemoveBadTrk
std::vector< Tracklet > RemoveBadTrk(const std::vector< Tracklet > &tracklets, const Amg::Vector3D &Vx) const
Definition: MSVertexRecoTool.cxx:745
MSVertexRecoTool.h
xAOD::P4Helpers::deltaPhi
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition: xAODP4Helpers.h:69
Muon::MSVertexRecoTool::MSVertexRecoTool
MSVertexRecoTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: MSVertexRecoTool.cxx:29
Muon::MSVertexRecoTool::m_nTGC_accs
std::vector< SG::AuxElement::Accessor< int > > m_nTGC_accs
Definition: MSVertexRecoTool.h:75
Muon::MSVertexRecoTool::m_MinTrigHits
Gaudi::Property< int > m_MinTrigHits
Definition: MSVertexRecoTool.h:111
Trk::locR
@ locR
Definition: ParamDefs.h:44
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
MSVertex
Definition: MSVertex.h:13
covarianceTool.prob
prob
Definition: covarianceTool.py:678
Muon::MSVertexRecoTool::EndcapHasBadTrack
bool EndcapHasBadTrack(const std::vector< Tracklet > &tracklets, const Amg::Vector3D &Vx) const
Definition: MSVertexRecoTool.cxx:782
Muon::MSVertexRecoTool::findTrackClusters
std::vector< TrkCluster > findTrackClusters(const std::vector< Tracklet > &tracklets) const
Definition: MSVertexRecoTool.cxx:290
AmgSymMatrix
#define AmgSymMatrix(dim)
Definition: EventPrimitives.h:50
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
Muon::MSVertexRecoTool::m_nRPC_accs
std::vector< SG::AuxElement::Accessor< int > > m_nRPC_accs
Definition: MSVertexRecoTool.h:74
Muon::MSVertexRecoTool::m_VertexMinRadialPlane
Gaudi::Property< double > m_VertexMinRadialPlane
Definition: MSVertexRecoTool.h:100
Muon::MSVertexRecoTool::m_VertexMaxRadialPlane
Gaudi::Property< double > m_VertexMaxRadialPlane
Definition: MSVertexRecoTool.h:101
xAOD::Vertex_v1::setVertexType
void setVertexType(VxType::VertexType vType)
Set the type of the vertex.
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
Muon::MSVertexRecoTool::m_rndmSvc
ServiceHandle< IAthRNGSvc > m_rndmSvc
Definition: MSVertexRecoTool.h:78
Muon::MSVertexRecoTool::m_mdtTESKey
SG::ReadHandleKey< Muon::MdtPrepDataContainer > m_mdtTESKey
Definition: MSVertexRecoTool.h:66
tubeMax
double tubeMax
Definition: MDT_ResponseTest.cxx:31
xAOD::Vertex_v1::addTrackAtVertex
void addTrackAtVertex(const ElementLink< TrackParticleContainer > &tr, float weight=1.0)
Add a new track to the vertex.
Definition: Vertex_v1.cxx:314
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
MSVertex::getNRPC
int getNRPC() const
Definition: MSVertex.cxx:74
ParticleGun_EoverP_Config.momentum
momentum
Definition: ParticleGun_EoverP_Config.py:63
MSVertex::getNMDT
int getNMDT() const
Definition: MSVertex.cxx:73
Muon::MSVertexRecoTool::TrkCluster::phi
double phi
Definition: MSVertexRecoTool.h:53
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
Muon::RpcPrepData
Class to represent RPC measurements.
Definition: RpcPrepData.h:35
Muon::MSVertexRecoTool::vxPhiFinder
double vxPhiFinder(const double theta, const double phi, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:869
xAOD::P4Helpers::deltaR
double deltaR(double rapidity1, double phi1, double rapidity2, double phi2)
from bare bare rapidity,phi
Definition: xAODP4Helpers.h:150
Trk::theta
@ theta
Definition: ParamDefs.h:66
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::VxType::SecVtx
@ SecVtx
Secondary vertex.
Definition: TrackingPrimitives.h:573
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Muon::MSVertexRecoTool::MSVxFinder
void MSVxFinder(const std::vector< Tracklet > &tracklets, std::unique_ptr< MSVertex > &vtx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:307
Trk::CylinderSurface
Definition: CylinderSurface.h:55
TauGNNUtils::Variables::Track::dPhi
bool dPhi(const xAOD::TauJet &tau, const xAOD::TauTrack &track, double &out)
Definition: TauGNNUtils.cxx:549
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MSVertex::setNRPC
void setNRPC(const int, const int, const int, const int, const int, const int)
Definition: MSVertex.cxx:54
JetVoronoiDiagramHelpers::Norm
Point Norm(const Point &a)
Definition: JetVoronoiDiagramHelpers.cxx:79
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Muon::MSVertexRecoTool::m_nMDTHitsPhi
Gaudi::Property< double > m_nMDTHitsPhi
Definition: MSVertexRecoTool.h:107
Muon::MSVertexRecoTool::HitCounter
void HitCounter(MSVertex *MSRecoVx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:932
AthenaPoolTestRead.acc
acc
Definition: AthenaPoolTestRead.py:16
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MSVertex::setAuthor
void setAuthor(const int)
Definition: MSVertex.cxx:32
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
MSVertex::getNTGC
int getNTGC() const
Definition: MSVertex.cxx:75
Muon::MSVertexRecoTool::getTracklets
std::vector< Tracklet > getTracklets(const std::vector< Tracklet > &trks, const std::set< int > &tracklet_subset) const
Definition: MSVertexRecoTool.cxx:770
Trk::muon
@ muon
Definition: ParticleHypothesis.h:31
Muon::MSVertexRecoTool::m_useOldMSVxEndcapMethod
Gaudi::Property< bool > m_useOldMSVxEndcapMethod
Definition: MSVertexRecoTool.h:104
Muon::MSVertexRecoTool::m_ChamberOccupancyMin
Gaudi::Property< double > m_ChamberOccupancyMin
Definition: MSVertexRecoTool.h:86
Muon::MuonPrepDataCollection
Template to hold collections of MuonPrepRawData objects.
Definition: MuonPrepDataCollection.h:46
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
Muon::MSVertexRecoTool::dressVtxHits
void dressVtxHits(xAOD::Vertex *xAODVx, const std::vector< SG::AuxElement::Accessor< int >> &accs, const std::vector< int > &hits) const
Definition: MSVertexRecoTool.cxx:798
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Muon::MSVertexRecoTool::TrkCluster::ntrks
unsigned int ntrks
Definition: MSVertexRecoTool.h:54
Muon::MSVertexRecoTool::MSStraightLineVx
void MSStraightLineVx(const std::vector< Tracklet > &trks, std::unique_ptr< MSVertex > &vtx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:607
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
Muon::MSVertexRecoTool::m_MaxZEndcap
Gaudi::Property< double > m_MaxZEndcap
Definition: MSVertexRecoTool.h:114
Muon::MSVertexRecoTool::m_ClusterdPhi
Gaudi::Property< double > m_ClusterdPhi
Definition: MSVertexRecoTool.h:90
Muon::MSVertexRecoTool::m_accMDT_str
const std::vector< std::string > m_accMDT_str
Definition: MSVertexRecoTool.h:69
Muon::MSVertexRecoTool::MSStraightLineVx_oldMethod
void MSStraightLineVx_oldMethod(const std::vector< Tracklet > &trks, std::unique_ptr< MSVertex > &vtx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:709
Muon::MSVertexRecoTool::m_xAODContainerKey
SG::WriteHandleKey< xAOD::VertexContainer > m_xAODContainerKey
Definition: MSVertexRecoTool.h:62
Muon::MSVertexRecoTool::m_TrackPhiRotation
Gaudi::Property< double > m_TrackPhiRotation
Definition: MSVertexRecoTool.h:97
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
Muon::MSVertexRecoTool::m_VxPlaneDist
Gaudi::Property< double > m_VxPlaneDist
Definition: MSVertexRecoTool.h:102
ATHRNG::RNGWrapper
A wrapper class for event-slot-local random engines.
Definition: RNGWrapper.h:56
Muon::MSVertexRecoTool::FillOutputContainer
StatusCode FillOutputContainer(const std::vector< std::unique_ptr< MSVertex >> &, SG::WriteHandle< xAOD::VertexContainer > &xAODVxContainer) const
Definition: MSVertexRecoTool.cxx:810
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
charge
double charge(const T &p)
Definition: AtlasPID.h:986
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::AuxElement::makePrivateStore
void makePrivateStore()
Create a new (empty) private store for this object.
Definition: AuxElement.cxx:192
Muon::MdtPrepData
Class to represent measurements from the Monitored Drift Tubes.
Definition: MdtPrepData.h:33
Muon::MSVertexRecoTool::m_MaxLxyEndcap
Gaudi::Property< double > m_MaxLxyEndcap
Definition: MSVertexRecoTool.h:112
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
ATHRNG::RNGWrapper::getEngine
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition: RNGWrapper.h:134
RNGWrapper.h
Muon::MSVertexRecoTool::TrkCluster::eta
double eta
Definition: MSVertexRecoTool.h:52
Muon::MSVertexRecoTool::m_rpcTESKey
SG::ReadHandleKey< Muon::RpcPrepDataContainer > m_rpcTESKey
Definition: MSVertexRecoTool.h:64
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
Muon::MSVertexRecoTool::m_TrackPhiAngle
Gaudi::Property< double > m_TrackPhiAngle
Definition: MSVertexRecoTool.h:96
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Muon::MSVertexRecoTool::VxMinQuad
static Amg::Vector3D VxMinQuad(const std::vector< Tracklet > &tracks)
Definition: MSVertexRecoTool.cxx:840
Muon::MSVertexRecoTool::m_accTGC_str
const std::vector< std::string > m_accTGC_str
Definition: MSVertexRecoTool.h:71
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MSVertexRecoTool::initialize
virtual StatusCode initialize(void) override
Definition: MSVertexRecoTool.cxx:36
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Muon::MSVertexRecoTool::m_MaxTollDist
Gaudi::Property< double > m_MaxTollDist
Definition: MSVertexRecoTool.h:103
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
Muon::TgcPrepData
Class to represent TGC measurements.
Definition: TgcPrepData.h:32
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
str
Definition: BTagTrackIpAccessor.cxx:11
Muon::MSVertexRecoTool::TrkCluster
Definition: MSVertexRecoTool.h:51
Muon::MSVertexRecoTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MSVertexRecoTool.h:77
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
Muon::MSVertexRecoTool::m_accRPC_str
const std::vector< std::string > m_accRPC_str
Definition: MSVertexRecoTool.h:70
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Muon::MSVertexRecoTool::m_MinZEndcap
Gaudi::Property< double > m_MinZEndcap
Definition: MSVertexRecoTool.h:113
AthAlgTool
Definition: AthAlgTool.h:26
Muon::MSVertexRecoTool::m_tgcTESKey
SG::ReadHandleKey< Muon::TgcPrepDataContainer > m_tgcTESKey
Definition: MSVertexRecoTool.h:65
Muon::MSVertexRecoTool::ClusterizeTracks
std::optional< TrkCluster > ClusterizeTracks(std::vector< Tracklet > &tracks) const
Definition: MSVertexRecoTool.cxx:178
Muon::MSVertexRecoTool::m_BarrelTrackletUncert
Gaudi::Property< double > m_BarrelTrackletUncert
Definition: MSVertexRecoTool.h:93
TauGNNUtils::Variables::Track::dEta
bool dEta(const xAOD::TauJet &tau, const xAOD::TauTrack &track, double &out)
Definition: TauGNNUtils.cxx:538
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
Muon::MSVertexRecoTool::TrkCluster::tracks
std::vector< Tracklet > tracks
Definition: MSVertexRecoTool.h:56
Tracklet
Definition: Tracklet.h:17
Muon::MSVertexRecoTool::m_EndcapTrackletUncert
Gaudi::Property< double > m_EndcapTrackletUncert
Definition: MSVertexRecoTool.h:94
Muon::MSVertexRecoTool::m_minHighOccupancyChambers
Gaudi::Property< int > m_minHighOccupancyChambers
Definition: MSVertexRecoTool.h:87
Muon::MSVertexRecoTool::m_MaxTrackUncert
Gaudi::Property< double > m_MaxTrackUncert
Definition: MSVertexRecoTool.h:98
Muon::MSVertexRecoTool::m_nTrigHitsdR
Gaudi::Property< double > m_nTrigHitsdR
Definition: MSVertexRecoTool.h:108
VertexAuxContainer.h
fitman.k
k
Definition: fitman.py:528
Muon::MSVertexRecoTool::m_extrapolator
ToolHandle< Trk::IExtrapolator > m_extrapolator
Definition: MSVertexRecoTool.h:79
Muon::MSVertexRecoTool::m_MinMDTHits
Gaudi::Property< int > m_MinMDTHits
Definition: MSVertexRecoTool.h:110
Muon::MSVertexRecoTool::m_VxChi2ProbCUT
Gaudi::Property< double > m_VxChi2ProbCUT
Definition: MSVertexRecoTool.h:99
MSVertex::getPosition
const Amg::Vector3D & getPosition() const
Definition: MSVertex.cxx:28
Identifier
Definition: IdentifierFieldParser.cxx:14