ATLAS Offline Software
MSVertexRecoTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MSVertexRecoTool.h"
6 
8 #include "CLHEP/Random/RandFlat.h"
10 #include "TMath.h" // for TMath::Prob()
12 #include "xAODTracking/Vertex.h"
16 namespace {
17  constexpr int MAXPLANES = 100;
19  constexpr float sq(float x) { return (x) * (x); }
20 
21 } // namespace
22 
23 /*
24  MS vertex reconstruction routine
25  See documentation at https://cds.cern.ch/record/1455664 and https://cds.cern.ch/record/1520894
26  Takes Tracklets as input and creates vertices in the MS volume
27 */
28 
29 namespace Muon {
30 
31  //** ----------------------------------------------------------------------------------------------------------------- **//
32 
33  MSVertexRecoTool::MSVertexRecoTool(const std::string& type, const std::string& name, const IInterface* parent) :
35  declareInterface<IMSVertexRecoTool>(this);
36  // nominal phi angle for tracklets
37  declareProperty("TrackPhiAngle", m_TrackPhiAngle = 0.0);
38  // chi^2 probability cut
39  declareProperty("VxChi2Probability", m_VxChi2ProbCUT = 0.05);
40  // distance between two adjacent planes
41  declareProperty("VertexPlaneDist", m_VxPlaneDist = 200.);
42  // position of last radial plane
43  declareProperty("VertexMaxRadialPlane", m_VertexMaxRadialPlane = 7000.);
44  // position of first radial plane
45  declareProperty("VertexMinRadialPlane", m_VertexMinRadialPlane = 3500.);
46  // minimum occupancy to be considered "high occupancy"
47  declareProperty("MinimumHighOccupancy", m_ChamberOccupancyMin = 0.25);
48  // number of high occupancy chambers required to be signal like
49  declareProperty("MinimumNumberOfHighOccupancy", m_minHighOccupancyChambers = 2);
50  declareProperty("UseOldMSVxEndcapMethod", m_useOldMSVxEndcapMethod = false);
51  declareProperty("MaxTollDist", m_MaxTollDist = 300);
52 
53  // options to calculate vertex systematic uncertainty from the tracklet reco uncertainty
54  declareProperty("DoSystematicUncertainty", m_doSystematics = false);
55  declareProperty("BarrelTrackletUncertainty", m_BarrelTrackletUncert = 0.1);
56  declareProperty("EndcapTrackletUncertainty", m_EndcapTrackletUncert = 0.1);
57 
58  // cuts to prevent excessive processing timing
59  declareProperty("MaxGlobalTracklets", m_maxGlobalTracklets = 40);
60  declareProperty("MaxClusterTracklets", m_maxClusterTracklets = 50);
61  }
62 
63  //** ----------------------------------------------------------------------------------------------------------------- **//
64 
66  ATH_CHECK(m_idHelperSvc.retrieve());
67  ATH_CHECK(m_rndmSvc.retrieve());
68 
69  ATH_CHECK(m_extrapolator.retrieve());
70  ATH_CHECK(m_xAODContainerKey.initialize());
71  ATH_CHECK(m_rpcTESKey.initialize());
72  ATH_CHECK(m_tgcTESKey.initialize());
73  ATH_CHECK(m_mdtTESKey.initialize());
74 
75  m_decor_nMDT = m_xAODContainerKey.key() + "." + m_decor_nMDT.key();
76  m_decor_nRPC = m_xAODContainerKey.key() + "." + m_decor_nRPC.key();
77  m_decor_nTGC = m_xAODContainerKey.key() + "." + m_decor_nTGC.key();
78 
79  ATH_CHECK(m_decor_nMDT.initialize());
80  ATH_CHECK(m_decor_nRPC.initialize());
81  ATH_CHECK(m_decor_nTGC.initialize());
82  return StatusCode::SUCCESS;
83  }
84 
85  //** ----------------------------------------------------------------------------------------------------------------- **//
86 
87  StatusCode MSVertexRecoTool::findMSvertices(std::vector<Tracklet>& tracklets, std::vector<MSVertex*>& vertices,
88  const EventContext& ctx) const {
89  ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
90  rngWrapper->setSeed(name(), ctx);
91  CLHEP::HepRandomEngine* rndmEngine = rngWrapper->getEngine(ctx);
92 
94  ATH_CHECK(xAODVxContainer.record(std::make_unique<xAOD::VertexContainer>(), std::make_unique<xAOD::VertexAuxContainer>()));
95 
99 
100  // if there are fewer than 3 tracks, vertexing not possible
101  if (tracklets.size() < 3) { return StatusCode::SUCCESS; }
102 
103  if (tracklets.size() > m_maxGlobalTracklets) {
104  ATH_MSG_DEBUG("Too many tracklets found globally. Creating dummy MS vertex and exit.");
105  MSVertex* dummyVtx;
106  MakeDummyVertex(dummyVtx);
107  vertices.push_back(dummyVtx);
108  ATH_CHECK(FillOutputContainer(vertices, xAODVxContainer, hMDT, hRPC, hTGC));
109  }
110 
111  // group the tracks
112  std::vector<Tracklet> BarrelTracklets;
113  std::vector<Tracklet> EndcapTracklets;
114  for (unsigned int i = 0; i < tracklets.size(); ++i) {
115  if (tracklets.at(i).mdtChamber() <= 11 || tracklets.at(i).mdtChamber() == 52)
116  BarrelTracklets.push_back(tracklets.at(i));
117  else
118  EndcapTracklets.push_back(tracklets.at(i));
119  }
120 
121  if (BarrelTracklets.size() > m_maxClusterTracklets || EndcapTracklets.size() > m_maxClusterTracklets) {
122  ATH_MSG_DEBUG("Too many tracklets found in barrel or endcap for clustering. Creating dummy MS vertex and exit");
123  MSVertex* dummyVtx;
124  MakeDummyVertex(dummyVtx);
125  vertices.push_back(dummyVtx);
126  ATH_CHECK(FillOutputContainer(vertices, xAODVxContainer, hMDT, hRPC, hTGC));
127  }
128 
129  ATH_MSG_DEBUG("Running on event with " << BarrelTracklets.size() << " barrel tracklets, " << EndcapTracklets.size()
130  << " endcap tracklets.");
131 
132  // find any clusters of tracks & decide if tracks are from single muon
133  std::vector<Muon::MSVertexRecoTool::TrkCluster> BarrelClusters = findTrackClusters(BarrelTracklets);
134  std::vector<Muon::MSVertexRecoTool::TrkCluster> EndcapClusters = findTrackClusters(EndcapTracklets);
135 
136  for (unsigned int i = 0; i < BarrelClusters.size(); i++) {
137  if (BarrelClusters.at(i).ntrks != (int)BarrelClusters.at(i).tracks.size()) {
138  ATH_MSG_INFO("ntrks not equal to track container size; this should never happen. Exiting quietly.");
139  return FillOutputContainer(vertices, xAODVxContainer, hMDT, hRPC, hTGC);
140  }
141  }
142  for (unsigned int i = 0; i < EndcapClusters.size(); i++) {
143  if (EndcapClusters.at(i).ntrks != (int)EndcapClusters.at(i).tracks.size()) {
144  ATH_MSG_INFO("ntrks not equal to track container size; this should never happen. Exiting quietly.");
145  return FillOutputContainer(vertices, xAODVxContainer, hMDT, hRPC, hTGC);
146  }
147  }
148 
149  // if doSystematics, remove tracklets according to the tracklet reco uncertainty and rerun the cluster finder
150  if (m_doSystematics) {
151  std::vector<Tracklet> BarrelSystTracklets, EndcapSystTracklets;
152  for (unsigned int i = 0; i < BarrelTracklets.size(); ++i) {
153  float prob = CLHEP::RandFlat::shoot(rndmEngine, 0, 1);
154  if (prob > m_BarrelTrackletUncert) BarrelSystTracklets.push_back(BarrelTracklets.at(i));
155  }
156  if (BarrelSystTracklets.size() >= 3) {
157  std::vector<Muon::MSVertexRecoTool::TrkCluster> BarrelSystClusters = findTrackClusters(BarrelSystTracklets);
158  for (unsigned int i = 0; i < BarrelSystClusters.size(); ++i) {
159  BarrelSystClusters.at(i).isSystematic = true;
160  BarrelClusters.push_back(BarrelSystClusters.at(i));
161  }
162  }
163  for (unsigned int i = 0; i < EndcapTracklets.size(); ++i) {
164  float prob = CLHEP::RandFlat::shoot(rndmEngine, 0, 1);
165  if (prob > m_EndcapTrackletUncert) EndcapSystTracklets.push_back(EndcapTracklets.at(i));
166  }
167  if (EndcapSystTracklets.size() >= 3) {
168  std::vector<Muon::MSVertexRecoTool::TrkCluster> EndcapSystClusters = findTrackClusters(EndcapSystTracklets);
169  for (unsigned int i = 0; i < EndcapSystClusters.size(); ++i) {
170  EndcapSystClusters.at(i).isSystematic = true;
171  EndcapClusters.push_back(EndcapSystClusters.at(i));
172  }
173  }
174  }
175 
177  // find vertices in the barrel MS (vertices using barrel tracklets)
178  for (unsigned int i = 0; i < BarrelClusters.size(); ++i) {
179  if (BarrelClusters[i].ntrks < 3) continue;
180  ATH_MSG_DEBUG("Attempting to build vertex from " << BarrelClusters[i].ntrks << " tracklets in the barrel");
181  std::unique_ptr<MSVertex> barvertex(nullptr);
182  MSVxFinder(BarrelClusters[i].tracks, barvertex, ctx);
183  if (!barvertex) continue;
184  if (barvertex->getChi2Probability() > 0.05) {
185  HitCounter(barvertex.get(), ctx);
186  if (barvertex->getNMDT() > 250 && (barvertex->getNRPC() + barvertex->getNTGC()) > 200) {
187  ATH_MSG_DEBUG("Vertex found in the barrel with n_trk = " << barvertex->getNTracks() << " located at (eta,phi) = ("
188  << barvertex->getPosition().eta() << ", "
189  << barvertex->getPosition().phi() << ")");
190  if (BarrelClusters[i].isSystematic) barvertex->setAuthor(3);
191  vertices.push_back(barvertex.release());
192  } // end minimum good vertex criteria
193  }
194  } // end loop on barrel tracklet clusters
195 
196  // find vertices in the endcap MS (vertices using endcap tracklets)
197  for (unsigned int i = 0; i < EndcapClusters.size(); ++i) {
198  if (EndcapClusters[i].ntrks < 3) continue;
199  ATH_MSG_DEBUG("Attempting to build vertex from " << EndcapClusters[i].ntrks << " tracklets in the endcap");
200 
201  std::unique_ptr<MSVertex> endvertex(nullptr);
203  MSStraightLineVx_oldMethod(EndcapClusters[i].tracks, endvertex, ctx);
204  else
205  MSStraightLineVx(EndcapClusters[i].tracks, endvertex, ctx);
206 
207  if (!endvertex) continue;
208  if (endvertex->getPosition().perp() < 10000 && std::abs(endvertex->getPosition().z()) < 14000 &&
209  std::abs(endvertex->getPosition().z()) > 8000 && endvertex->getNTracks() >= 3) {
210  HitCounter(endvertex.get(), ctx);
211  if (endvertex->getNMDT() > 250 && (endvertex->getNRPC() + endvertex->getNTGC()) > 200) {
212  ATH_MSG_DEBUG("Vertex found in the endcap with n_trk = " << endvertex->getNTracks() << " located at (eta,phi) = ("
213  << endvertex->getPosition().eta() << ", "
214  << endvertex->getPosition().phi() << ")");
215  if (EndcapClusters[i].isSystematic) endvertex->setAuthor(4);
216  vertices.push_back(endvertex.release());
217  } // end minimum good vertex criteria
218  }
219 
220  } // end loop on endcap tracklet clusters
221 
222  ATH_CHECK(FillOutputContainer(vertices, xAODVxContainer, hMDT, hRPC, hTGC));
223  return StatusCode::SUCCESS;
224  } // end find vertices
225 
226  //** ----------------------------------------------------------------------------------------------------------------- **//
227 
229  if (tracks.size() > m_maxClusterTracklets) {
230  ATH_MSG_DEBUG("Too many tracks found, returning empty cluster");
231  TrkCluster emptycluster;
232  emptycluster.ntrks = 0;
233  emptycluster.eta = -99999.;
234  emptycluster.phi = -99999.;
235  emptycluster.isSystematic = false;
236  return emptycluster;
237  }
238  TrkCluster trkClu[100];
239  TrkCluster trkClu0[100];
240  trkClu[0].ntrks = 0;
241  trkClu[0].eta = -10;
242  trkClu[0].phi = -10;
243  int ncluster = 0;
244  // use each tracklet as a seed for the clusters
245  for (std::vector<Tracklet>::iterator trkItr = tracks.begin(); trkItr != tracks.end(); ++trkItr) {
246  TrkCluster clu;
247  clu.eta = trkItr->globalPosition().eta();
248  clu.phi = trkItr->globalPosition().phi();
249  clu.ntrks = 0;
250  clu.isSystematic = false;
251  for (unsigned int i = 0; i < tracks.size(); ++i) clu.trks[i] = 0;
252 
253  trkClu[ncluster] = clu;
254  trkClu0[ncluster] = clu;
255  ++ncluster;
256  if (ncluster >= 99) {
257  TrkCluster emptycluster;
258  emptycluster.ntrks = 0;
259  emptycluster.eta = -99999.;
260  emptycluster.phi = -99999.;
261  for (unsigned int i = 0; i < tracks.size(); ++i) emptycluster.trks[i] = 0;
262  emptycluster.isSystematic = false;
263  return emptycluster;
264  }
265  }
266  // loop on the clusters and let the center move to find the optimal cluster centers
267  for (int icl = 0; icl < ncluster; ++icl) {
268  bool improvement = true;
269  int nitr(0);
270 
271  int ntracks(0);
272  for (int jcl = 0; jcl < ncluster; ++jcl) {
273  float dEta = trkClu[icl].eta - trkClu0[jcl].eta;
274  float dPhi = xAOD::P4Helpers::deltaPhi(trkClu[icl].phi , trkClu0[jcl].phi);
275  if (std::abs(dEta) < 0.7 && std::abs(dPhi) < M_PI / 3.) {
276  ntracks++;
277  trkClu[icl].eta = trkClu[icl].eta - dEta / ntracks;
278  trkClu[icl].phi = trkClu[icl].phi - dPhi / ntracks;
279  while (std::abs(trkClu[icl].phi) > M_PI) {
280  if (trkClu[icl].phi > 0)
281  trkClu[icl].phi -= 2 * M_PI;
282  else
283  trkClu[icl].phi += 2 * M_PI;
284  }
285  }
286  } // end jcl loop
287  // find the number of tracks in the new cluster
288  double eta_avg_best = trkClu[icl].eta;
289  double phi_avg_best = trkClu[icl].phi;
290 
291  while (improvement) {
292  int itracks[100];
293  for (int k = 0; k < ncluster; ++k) itracks[k] = 0;
294  int ntracks2(0);
295  double eta_avg = 0.0;
296  double phi_avg = 0.0;
297  double cosPhi_avg = 0.0;
298  double sinPhi_avg = 0.0;
299 
300  for (int jcl = 0; jcl < ncluster; ++jcl) {
301  float dEta = std::abs(trkClu[icl].eta - trkClu0[jcl].eta);
302  float dPhi = xAOD::P4Helpers::deltaPhi(trkClu[icl].phi , trkClu0[jcl].phi);
303  if (dEta < 0.7 && std::abs(dPhi) < M_PI / 3.) {
304  eta_avg += trkClu0[jcl].eta;
305  cosPhi_avg += std::cos(trkClu0[jcl].phi);
306  sinPhi_avg += std::sin(trkClu0[jcl].phi);
307  ntracks2++;
308  itracks[jcl] = 1;
309  }
310  } // end jcl loop
311 
312  eta_avg = eta_avg / ntracks2;
313  phi_avg = std::atan2(sinPhi_avg, cosPhi_avg);
314 
315  if (ntracks2 > trkClu[icl].ntrks) {
316  eta_avg_best = trkClu[icl].eta;
317  phi_avg_best = trkClu[icl].phi;
318  trkClu[icl].ntrks = ntracks2;
319  for (int k = 0; k < ncluster; ++k) { trkClu[icl].trks[k] = itracks[k]; }
320  if (nitr < 6) {
321  trkClu[icl].eta = eta_avg;
322  trkClu[icl].phi = phi_avg;
323  } else
324  break;
325 
326  } else {
327  trkClu[icl].eta = eta_avg_best;
328  trkClu[icl].phi = phi_avg_best;
329  improvement = false;
330  }
331  nitr++;
332  } // end while
333  } // end icl loop
334 
335  // find the best cluster
336 
337  TrkCluster* BestClusterptr = &trkClu[0];
338  for (int icl = 1; icl < ncluster; ++icl) {
339  if (trkClu[icl].ntrks > BestClusterptr->ntrks) BestClusterptr = &trkClu[icl];
340  }
341  TrkCluster BestCluster = *BestClusterptr;
342  // store the tracks inside the cluster
343  std::vector<Tracklet> unusedTracks;
344  for (std::vector<Tracklet>::iterator trkItr = tracks.begin(); trkItr != tracks.end(); ++trkItr) {
345  float dEta = std::abs(BestCluster.eta - trkItr->globalPosition().eta());
346  float dPhi = xAOD::P4Helpers::deltaPhi(BestCluster.phi , trkItr->globalPosition().phi());
347  if (dEta < 0.7 && std::abs(dPhi) < M_PI / 3.)
348  BestCluster.tracks.push_back((*trkItr));
349  else
350  unusedTracks.push_back((*trkItr));
351  }
352  // return the best cluster and the unused tracklets
353  tracks = std::move(unusedTracks);
354  return BestCluster;
355  }
356 
357  //** ----------------------------------------------------------------------------------------------------------------- **//
358 
359  std::vector<Muon::MSVertexRecoTool::TrkCluster> MSVertexRecoTool::findTrackClusters(const std::vector<Tracklet>& tracks) const {
360  std::vector<Tracklet> trks = tracks;
361  std::vector<TrkCluster> clusters;
362  // keep making clusters until there are no more possible
363  while (true) {
364  if (trks.size() < 3) break;
365  TrkCluster clust = ClusterizeTracks(trks);
366  if (clust.ntrks >= 3)
367  clusters.push_back(clust);
368  else
369  break;
370  if (trks.size() < 3) break;
371  }
372 
373  if (clusters.empty()) {
374  TrkCluster clust;
375  clusters.push_back(clust);
376  }
377 
378  return clusters;
379  }
380 
381  //** ----------------------------------------------------------------------------------------------------------------- **//
382 
383  void MSVertexRecoTool::MSVxFinder(const std::vector<Tracklet>& tracklets, std::unique_ptr<MSVertex>& vtx,
384  const EventContext& ctx) const {
385  int nTrkToVertex(0);
386  float NominalAngle(m_TrackPhiAngle), MaxOpenAngle(0.20 + m_TrackPhiAngle);
387  float aveX(0), aveY(0), aveR(0), aveZ(0);
388  float maxError(200); // maximum allowed uncertainty for tracklets [mm] (above this cut tracklets are discarded)
389 
390  // find the average position of the tracklets
391  for (auto trkItr = tracklets.cbegin(); trkItr != tracklets.cend(); ++trkItr) {
392  aveR += trkItr->globalPosition().perp();
393  aveX += trkItr->globalPosition().x();
394  aveY += trkItr->globalPosition().y();
395  aveZ += trkItr->globalPosition().z();
396  }
397 
398  aveX = aveX / (float)tracklets.size();
399  aveY = aveY / (float)tracklets.size();
400  aveZ = aveZ / (float)tracklets.size();
401  aveR = aveR / (float)tracklets.size();
402 
403  float avePhi = std::atan2(aveY, aveX);
404  while (std::abs(avePhi) > M_PI) {
405  if (avePhi < 0)
406  avePhi += 2 * M_PI;
407  else
408  avePhi -= 2 * M_PI;
409  }
410 
411  // calculate the two angles (theta & phi)
412  float LoF = std::atan2(aveR, aveZ); // Line of Flight (theta)
413  avePhi = vxPhiFinder(std::abs(LoF), avePhi, ctx);
414 
415  // find the positions of the radial planes
416  float Rpos[MAXPLANES];
417  float RadialDist = m_VertexMaxRadialPlane - m_VertexMinRadialPlane;
418  float LoFdist = std::abs(RadialDist / std::sin(LoF));
419  int nplanes = LoFdist / m_VxPlaneDist + 1;
420  float PlaneSpacing = std::abs(200. / std::cos(LoF));
421  for (int k = 0; k < nplanes; ++k) Rpos[k] = m_VertexMinRadialPlane + PlaneSpacing * k;
422 
423  // loop on tracklets and create two types of track parameters -- nominal and phi shifted tracklets
424  std::vector<const Trk::TrackParameters*> TracksForVertexing[MAXPLANES]; // vector of tracklets to be used at each vertex plane
425  std::vector<const Trk::TrackParameters*>
426  TracksForErrors[MAXPLANES]; // vector of tracklets to be used for uncertainty at each vertex plane
427  std::vector<bool> isNeutralTrack[MAXPLANES];
428 
429  for (unsigned int i = 0; i < tracklets.size(); ++i) {
430  // only barrel tracklets
431  if (tracklets.at(i).mdtChamber() <= 11 || tracklets.at(i).mdtChamber() == 52) {
432  nTrkToVertex++;
433  // coordinate transform variables
434  Amg::Vector3D trkgpos(tracklets.at(i).globalPosition().perp() * std::cos(avePhi),
435  tracklets.at(i).globalPosition().perp() * std::sin(avePhi), tracklets.at(i).globalPosition().z());
436  float x0 = trkgpos.x();
437  float y0 = trkgpos.y();
438  float r0 = trkgpos.perp();
439 
442  // decide which way the tracklet gets rotated -- positive or negative phi
443  float anglesign = 1.0;
444  if ((tracklets.at(i).globalPosition().phi() - avePhi) < 0) anglesign = -1.0;
445  float NominalTrkAng = anglesign * NominalAngle; // in case there is a nominal tracklet angle
446  float MaxTrkAng = anglesign * MaxOpenAngle; // the rotated tracklet phi position
447 
448  // loop over the planes
449  for (int k = 0; k < nplanes; ++k) {
450  // only use tracklets that start AFTER the vertex plane
451  if (Rpos[k] > tracklets.at(i).globalPosition().perp()) break;
452 
453  // nominal tracks for vertexing
454  float Xp = Rpos[k] * std::cos(avePhi);
455  float Yp = Rpos[k] * std::sin(avePhi);
456  // in case there is a nominal opening angle, calculate tracklet direction
457  // the tracklet must cross the candidate vertex plane at the correct phi
458  float DelR = std::hypot(x0 - Xp, y0 - Yp) / std::cos(NominalAngle);
459  float X1 = DelR * std::cos(NominalTrkAng + avePhi) + Xp;
460  float Y1 = DelR * std::sin(NominalTrkAng + avePhi) + Yp;
461  float R1 = std::hypot(X1, Y1);
462  float Norm = r0 / R1;
463  X1 = X1 * Norm;
464  Y1 = Y1 * Norm;
465  float Dirmag = std::hypot(X1 - Xp, Y1 - Yp);
466  float Xdir = (X1 - Xp) / Dirmag;
467  float Ydir = (Y1 - Yp) / Dirmag;
468  float trkpx = Xdir * tracklets.at(i).momentum().perp();
469  float trkpy = Ydir * tracklets.at(i).momentum().perp();
470  float trkpz = tracklets.at(i).momentum().z();
471  // check if the tracklet has a charge & momentum measurement -- if not, set charge=1 so extrapolator will work
472  float charge = tracklets.at(i).charge();
473  if (std::abs(charge) < 0.1) {
474  charge = 1; // for "straight" tracks, set charge = 1
475  isNeutralTrack[k].push_back(true);
476  } else
477  isNeutralTrack[k].push_back(false);
478 
479  // store the tracklet as a Trk::Perigee
480  Amg::Vector3D trkmomentum(trkpx, trkpy, trkpz);
481  Amg::Vector3D trkgpos(X1, Y1, tracklets.at(i).globalPosition().z());
482  AmgSymMatrix(5) covariance = AmgSymMatrix(5)(tracklets.at(i).errorMatrix());
483  Trk::Perigee* myPerigee = new Trk::Perigee(0., 0., trkmomentum.phi(), trkmomentum.theta(), charge / trkmomentum.mag(),
484  Trk::PerigeeSurface(trkgpos), covariance);
485  TracksForVertexing[k].push_back(myPerigee);
486 
487  // tracks for errors -- rotate the plane & recalculate the tracklet parameters
488  float xp = Rpos[k] * std::cos(avePhi);
489  float yp = Rpos[k] * std::sin(avePhi);
490  float delR = std::hypot(x0 - xp, y0 - yp) / std::cos(MaxOpenAngle);
491  float x1 = delR * std::cos(MaxTrkAng + avePhi) + xp;
492  float y1 = delR * std::sin(MaxTrkAng + avePhi) + yp;
493  float r1 = std::hypot(x1, y1);
494  float norm = r0 / r1;
495  x1 = x1 * norm;
496  y1 = y1 * norm;
497  float dirmag = std::hypot(x1 - xp, y1 - yp);
498  float xdir = (x1 - xp) / dirmag;
499  float ydir = (y1 - yp) / dirmag;
500  float errpx = xdir * tracklets.at(i).momentum().perp();
501  float errpy = ydir * tracklets.at(i).momentum().perp();
502  float errpz = tracklets.at(i).momentum().z();
503 
504  // store the tracklet as a Trk::Perigee
505  AmgSymMatrix(5) covariance2 = AmgSymMatrix(5)(tracklets.at(i).errorMatrix());
506  Amg::Vector3D trkerrmom(errpx, errpy, errpz);
507  Amg::Vector3D trkerrpos(x1, y1, tracklets.at(i).globalPosition().z());
508  Trk::Perigee* errPerigee = new Trk::Perigee(0., 0., trkerrmom.phi(), trkerrmom.theta(), charge / trkerrmom.mag(),
509  Trk::PerigeeSurface(trkerrpos), covariance2);
510 
511  TracksForErrors[k].push_back(errPerigee);
512  } // end loop on vertex planes
513  } // end selection of barrel tracks
514  } // end loop on tracks
515 
516  // return if there are not enough tracklets
517  if (nTrkToVertex < 3) return;
518 
519  // calculate the tracklet positions on each surface
520  bool boundaryCheck = true;
521  std::vector<float> ExtrapZ[MAXPLANES], dlength[MAXPLANES]; // extrapolated position & uncertainty
522  std::vector<std::pair<unsigned int, unsigned int> > UsedTracks[MAXPLANES];
523  std::vector<bool> ExtrapSuc[MAXPLANES]; // did the extrapolation succeed?
524  std::vector<MSVertex*> vertices;
525  vertices.reserve(nplanes);
526 
527  // total uncertainty at each plane
528  std::vector<float> sigmaZ[MAXPLANES];
529 
530  // tracklet momentum expressed at the plane
531  std::vector<Amg::Vector3D> pAtVx[MAXPLANES];
532 
533  for (int k = 0; k < nplanes; ++k) {
534  float rpos = Rpos[k];
535 
536  for (unsigned int i = 0; i < TracksForVertexing[k].size(); ++i) {
537  // at least three tracklets per plane are needed
538  if (TracksForVertexing[k].size() < 3) break;
539 
540  Amg::Transform3D surfaceTransformMatrix;
541  surfaceTransformMatrix.setIdentity();
542  Trk::CylinderSurface cyl(surfaceTransformMatrix, rpos, 10000.); // create the surface
543  // extrapolate to the surface
544  std::unique_ptr<const Trk::TrackParameters> extrap_par(
545  m_extrapolator->extrapolate(ctx,
546  *TracksForVertexing[k].at(i), cyl, Trk::anyDirection, boundaryCheck, Trk::muon));
547 
548  const Trk::AtaCylinder* extrap = dynamic_cast<const Trk::AtaCylinder*>(extrap_par.get());
549 
550  if (extrap) {
551  // if the track is neutral just store the uncertainty due to angular uncertainty of the orignal tracklet
552  if (isNeutralTrack[k].at(i)) {
553  float pTot =
554  std::hypot(TracksForVertexing[k].at(i)->momentum().perp(), TracksForVertexing[k].at(i)->momentum().z());
555  float dirErr = Amg::error(*TracksForVertexing[k].at(i)->covariance(), Trk::theta);
556  float extrapRdist = TracksForVertexing[k].at(i)->position().perp() - Rpos[k];
557  float sz = std::abs(20 * dirErr * extrapRdist * sq(pTot) / sq(TracksForVertexing[k].at(i)->momentum().perp()));
558  float ExtrapErr = sz;
559  if (ExtrapErr > maxError)
560  ExtrapSuc[k].push_back(false);
561  else {
562  ExtrapSuc[k].push_back(true);
563  std::pair<unsigned int, unsigned int> trkmap(ExtrapZ[k].size(), i);
564  UsedTracks[k].push_back(trkmap);
565  ExtrapZ[k].push_back(extrap->localPosition().y());
566  sigmaZ[k].push_back(sz);
567  pAtVx[k].push_back(extrap->momentum());
568  dlength[k].push_back(0);
569  }
570  } // end neutral tracklets
571  // if the tracklet has a momentum measurement
572  else {
573  // now extrapolate taking into account the extra path length & differing magnetic field
574  Amg::Transform3D srfTransMat2;
575  srfTransMat2.setIdentity();
576  Trk::CylinderSurface cyl2(srfTransMat2, rpos, 10000.);
577  std::unique_ptr<const Trk::TrackParameters> extrap_par2(
578  m_extrapolator->extrapolate(ctx,
579  *TracksForErrors[k].at(i), cyl, Trk::anyDirection, boundaryCheck, Trk::muon));
580  const Trk::AtaCylinder* extrap2 = dynamic_cast<const Trk::AtaCylinder*>(extrap_par2.get());
581 
582  if (extrap2) {
583  float sz = Amg::error(*extrap->covariance(), Trk::locY);
584  float zdiff = extrap->localPosition().y() - extrap2->localPosition().y();
585  float ExtrapErr = std::hypot(sz, zdiff);
586  if (ExtrapErr > maxError)
587  ExtrapSuc[k].push_back(false);
588  else {
589  // iff both extrapolations succeed && error is acceptable, store the information
590  ExtrapSuc[k].push_back(true);
591  std::pair<unsigned int, unsigned int> trkmap(ExtrapZ[k].size(), i);
592  UsedTracks[k].push_back(trkmap);
593  ExtrapZ[k].push_back(extrap->localPosition().y());
594  sigmaZ[k].push_back(sz);
595  pAtVx[k].push_back(extrap->momentum());
596  dlength[k].push_back(zdiff);
597  }
598  } else
599  ExtrapSuc[k].push_back(false); // not possible to calculate the uncertainty -- do not use tracklet in vertex
600  }
601  } // fi extrap
602  else
603  ExtrapSuc[k].push_back(false); // not possible to extrapolate the tracklet
604  } // end loop on perigeebase
605  } // end loop on radial planes
606 
607  // vertex routine
608  std::vector<Amg::Vector3D> trkp[MAXPLANES];
609  // loop on planes
610  for (int k = 0; k < nplanes; ++k) {
611  if (ExtrapZ[k].size() < 3) continue; // require at least 3 tracklets to build a vertex
612  // initialize the variables used in the routine
613  float zLoF = Rpos[k] / std::tan(LoF);
614  float dzLoF(10);
615  float aveZpos(0), posWeight(0);
616  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) {
617  float ExtrapErr = std::hypot(sigmaZ[k][i], dlength[k][i], dzLoF);
618  if (isNeutralTrack[k][i]) ExtrapErr = std::hypot(sigmaZ[k][i], dzLoF);
619  aveZpos += ExtrapZ[k][i] / sq(ExtrapErr);
620  posWeight += 1. / sq(ExtrapErr);
621  }
622  // calculate the weighted average position of the tracklets
623  zLoF = aveZpos / posWeight;
624  float zpossigma(dzLoF), Chi2(0), Chi2Prob(-1);
625  int Nitr(0);
626  std::vector<unsigned int> vxtracks; // tracklets to be used in the vertex routine
627  std::vector<bool> blacklist; // tracklets that do not belong to the vertex
628  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) blacklist.push_back(false);
629  // minimum chi^2 iterative fit
630  while (true) {
631  vxtracks.clear();
632  trkp[k].clear();
633  int tmpnTrks(0);
634  float tmpzLoF(0);
635  float tmpzpossigma(0);
636  float tmpchi2(0);
637  float posWeight(0);
638  float worstdelz(0);
639  unsigned int iworst(0xC0FFEE);
640  // loop on the tracklets, find the chi^2 contribution from each tracklet
641  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) {
642  if (blacklist[i]) continue;
643  trkp[k].push_back(pAtVx[k][i]);
644  float delz = zLoF - ExtrapZ[k][i];
645  float ExtrapErr = std::hypot(sigmaZ[k][i], dlength[k][i], dzLoF);
646  float trkchi2 = sq(delz) / sq(ExtrapErr);
647  if (trkchi2 > worstdelz) {
648  iworst = i;
649  worstdelz = trkchi2;
650  }
651  tmpzLoF += ExtrapZ[k][i] / sq(ExtrapErr);
652  posWeight += 1. / sq(ExtrapErr);
653  tmpzpossigma += sq(delz);
654  tmpchi2 += trkchi2;
655  tmpnTrks++;
656  } // end loop on tracks
657  if (tmpnTrks < 3) break; // stop searching for a vertex at this plane
658  tmpzpossigma = std::sqrt(tmpzpossigma / (float)tmpnTrks);
659  zLoF = tmpzLoF / posWeight;
660  zpossigma = tmpzpossigma;
661  float testChi2 = TMath::Prob(tmpchi2, tmpnTrks - 1);
662  if (testChi2 < m_VxChi2ProbCUT)
663  blacklist[iworst] = true;
664  else {
665  Chi2 = tmpchi2;
666  Chi2Prob = testChi2;
667  // loop on the tracklets and find all that belong to the vertex
668  for (unsigned int i = 0; i < ExtrapZ[k].size(); ++i) {
669  float delz = zLoF - ExtrapZ[k][i];
670  float ExtrapErr = std::hypot(sigmaZ[k][i], dlength[k][i], dzLoF);
671  float trkErr = std::hypot(ExtrapErr, zpossigma) + 0.001;
672  float trkNsigma = std::abs(delz / trkErr);
673  if (trkNsigma < 3) vxtracks.push_back(i);
674  }
675  break; // found a vertex, stop removing tracklets!
676  }
677  if (Nitr >= ((int)ExtrapZ[k].size() - 3)) break; // stop searching for a vertex at this plane
678  Nitr++;
679  } // end while
680  if (vxtracks.size() < 3) continue;
681  std::vector<xAOD::TrackParticle*> vxTrackParticles;
682  // create TrackParticle vector for all tracklets used in the vertex fit
683  vxTrackParticles.reserve(vxtracks.size());
684  for (std::vector<unsigned int>::iterator vxtrk = vxtracks.begin(); vxtrk != vxtracks.end(); ++vxtrk) {
685  for (unsigned int i = 0; i < UsedTracks[k].size(); ++i) {
686  if ((*vxtrk) == UsedTracks[k].at(i).first) {
687  const Tracklet& trklt = tracklets.at(UsedTracks[k].at(i).second);
688  AmgSymMatrix(5) covariance = AmgSymMatrix(5)(trklt.errorMatrix());
689  Trk::Perigee* myPerigee = new Trk::Perigee(0., 0., trklt.momentum().phi(), trklt.momentum().theta(),
690  trklt.charge() / trklt.momentum().mag(),
691  Trk::PerigeeSurface(trklt.globalPosition()), covariance);
692  xAOD::TrackParticle* trackparticle = new xAOD::TrackParticle();
693  trackparticle->makePrivateStore();
694  trackparticle->setFitQuality(1., (int)trklt.mdtHitsOnTrack().size());
696 
697  trackparticle->setDefiningParameters(myPerigee->parameters()[Trk::d0], myPerigee->parameters()[Trk::z0],
698  myPerigee->parameters()[Trk::phi0], myPerigee->parameters()[Trk::theta],
699  myPerigee->parameters()[Trk::qOverP]);
700  std::vector<float> covMatrixVec;
701  Amg::compress(covariance, covMatrixVec);
702  trackparticle->setDefiningParametersCovMatrixVec(covMatrixVec);
703 
704  vxTrackParticles.push_back(trackparticle);
705 
706  delete myPerigee;
707  break;
708  }
709  }
710  }
711  Amg::Vector3D position(Rpos[k] * std::cos(avePhi), Rpos[k] * std::sin(avePhi), zLoF);
712  vertices.push_back(new MSVertex(1, position, vxTrackParticles, Chi2Prob, Chi2, 0, 0, 0));
713  } // end loop on Radial planes
714 
715  // delete the perigeebase
716  for (int k = 0; k < nplanes; ++k) {
717  for (unsigned int i = 0; i < TracksForVertexing[k].size(); ++i) delete TracksForVertexing[k].at(i);
718  for (unsigned int i = 0; i < TracksForErrors[k].size(); ++i) delete TracksForErrors[k].at(i);
719  }
720 
721  // return an empty vertex in case none were reconstructed
722  if (vertices.empty()) { return; }
723 
724  // loop on the vertex candidates and select the best based on max n(tracks) and max chi^2 probability
725  unsigned int bestVx(0);
726  for (unsigned int k = 1; k < vertices.size(); ++k) {
727  if (vertices[k]->getChi2Probability() < m_VxChi2ProbCUT || vertices[k]->getNTracks() < 3) continue;
728  if (vertices[k]->getNTracks() < vertices[bestVx]->getNTracks()) continue;
729  if (vertices[k]->getNTracks() == vertices[bestVx]->getNTracks() &&
730  vertices[k]->getChi2Probability() < vertices[bestVx]->getChi2Probability())
731  continue;
732  bestVx = k;
733  }
734  vtx.reset(vertices[bestVx]->clone());
735  // cleanup
736  for (std::vector<MSVertex*>::iterator it = vertices.begin(); it != vertices.end(); ++it) {
737  delete (*it);
738  (*it) = 0;
739  }
740  vertices.clear();
741  }
742 
743  //** ----------------------------------------------------------------------------------------------------------------- **//
744 
745  void MSVertexRecoTool::MSStraightLineVx(const std::vector<Tracklet>& trks, std::unique_ptr<MSVertex>& vtx,
746  const EventContext& ctx) const {
747  // Running set of all vertices found. The inner set is the indices of trks that are used to make the vertex
748  std::set<std::set<int> > prelim_vx;
749 
750  // We don't consider all 3-tracklet combinations when a high number of tracklets is found
751  // Faster method is used for > 40 tracklets
752  if (trks.size() > 40) {
753  MSStraightLineVx_oldMethod(trks, vtx, ctx);
754  return;
755  }
756 
757  // Okay, if we get here then we know there's 40 or fewer tracklets in the cluster.
758  // Make a list of all 3-tracklet combinations that make vertices
759  for (unsigned int i = 0; i < trks.size() - 2; i++) {
760  for (unsigned int j = i + 1; j < trks.size() - 1; j++) {
761  for (unsigned int k = j + 1; k < trks.size(); k++) {
762  std::set<int> tmpTracks;
763  tmpTracks.insert(i);
764  tmpTracks.insert(j);
765  tmpTracks.insert(k);
766 
767  Amg::Vector3D MyVx;
768  MyVx = VxMinQuad(getTracklets(trks, tmpTracks));
769  if (MyVx.perp() < 10000 && std::abs(MyVx.z()) > 7000 && std::abs(MyVx.z()) < 15000 &&
770  !EndcapHasBadTrack(getTracklets(trks, tmpTracks), MyVx))
771  prelim_vx.insert(tmpTracks);
772  }
773  }
774  }
775 
776  // If no preliminary vertices were found from 3 tracklets, then there is no vertex and we are done.
777  if (prelim_vx.empty()) return;
778 
779  // The remaining algorithm is very time consuming for large numbers of tracklets. To control this,
780  // we run the old algorithm when there are too many tracklets and a vertex is found.
781  if (trks.size() <= 20) {
782  std::set<std::set<int> > new_prelim_vx = prelim_vx;
783  std::set<std::set<int> > old_prelim_vx;
784 
785  int foundNewVx = true;
786  while (foundNewVx) {
787  foundNewVx = false;
788 
789  old_prelim_vx = new_prelim_vx;
790  new_prelim_vx.clear();
791 
792  for (std::set<std::set<int> >::iterator itr = old_prelim_vx.begin(); itr != old_prelim_vx.end(); ++itr) {
793  for (unsigned int i_trks = 0; i_trks < trks.size(); i_trks++) {
794  std::set<int> tempCluster = *itr;
795  if (tempCluster.insert(i_trks).second) {
796  Amg::Vector3D MyVx = VxMinQuad(getTracklets(trks, tempCluster));
797  if (MyVx.perp() < 10000 && std::abs(MyVx.z()) > 7000 && std::abs(MyVx.z()) < 15000 &&
798  !EndcapHasBadTrack(getTracklets(trks, tempCluster), MyVx)) {
799  new_prelim_vx.insert(tempCluster);
800  prelim_vx.insert(tempCluster);
801  foundNewVx = true;
802  }
803  }
804  }
805  }
806  }
807  } else {
808  // Since there are 20 or more tracklets, we're going to use the old MSVx finding method. Note that
809  // if the old method fails, we do not return here; in this case a 3-tracklet vertex that was found
810  // earlier in this algorithm will be returned
811  MSStraightLineVx_oldMethod(trks, vtx, ctx);
812  if (vtx) return;
813  }
814 
815  // Find the preliminary vertex with the maximum number of tracklets - that is the final vertex. If
816  // multiple preliminary vertices with same number of tracklets, the first one found is returned
817  std::set<std::set<int> >::iterator prelim_vx_max = prelim_vx.begin();
818  for (std::set<std::set<int> >::iterator itr = prelim_vx.begin(); itr != prelim_vx.end(); ++itr) {
819  if ((*itr).size() > (*prelim_vx_max).size()) prelim_vx_max = itr;
820  }
821 
822  std::vector<Tracklet> tracklets = getTracklets(trks, *prelim_vx_max);
823  // use tracklets to estimate the line of flight of decaying particle
824  float aveX(0);
825  float aveY(0);
826  for (std::vector<Tracklet>::iterator trkItr = tracklets.begin(); trkItr != tracklets.end(); ++trkItr) {
827  aveX += ((Tracklet)*trkItr).globalPosition().x();
828  aveY += ((Tracklet)*trkItr).globalPosition().y();
829  }
830  float tracklet_vxphi = std::atan2(aveY, aveX);
831  Amg::Vector3D MyVx = VxMinQuad(tracklets);
832  float vxtheta = std::atan2(MyVx.x(), MyVx.z());
833  float vxphi = vxPhiFinder(std::abs(vxtheta), tracklet_vxphi, ctx);
834  Amg::Vector3D vxpos(MyVx.x() * std::cos(vxphi), MyVx.x() * std::sin(vxphi), MyVx.z());
835  std::vector<xAOD::TrackParticle*> vxTrkTracks;
836  for (std::vector<Tracklet>::iterator tracklet = tracklets.begin(); tracklet != tracklets.end(); ++tracklet) {
837  AmgSymMatrix(5) covariance = AmgSymMatrix(5)(((Tracklet)*tracklet).errorMatrix());
838  Trk::Perigee* myPerigee = new Trk::Perigee(vxpos, ((Tracklet)*tracklet).momentum(), 0, vxpos, covariance);
839  xAOD::TrackParticle* myTrack = new xAOD::TrackParticle();
840 
841  myTrack->makePrivateStore();
842  myTrack->setFitQuality(1., (int)((Tracklet)*tracklet).mdtHitsOnTrack().size());
843  myTrack->setDefiningParameters(myPerigee->parameters()[Trk::d0], myPerigee->parameters()[Trk::z0],
844  myPerigee->parameters()[Trk::phi0], myPerigee->parameters()[Trk::theta],
845  myPerigee->parameters()[Trk::qOverP]);
846 
847  std::vector<float> covMatrixVec;
848  Amg::compress(covariance, covMatrixVec);
849  myTrack->setDefiningParametersCovMatrixVec(covMatrixVec);
850 
851  vxTrkTracks.push_back(myTrack);
852 
853  delete myPerigee;
854  }
855 
856  vtx = std::make_unique<MSVertex>(2, vxpos, vxTrkTracks, 1, vxTrkTracks.size(), 0, 0, 0);
857  }
858 
859  //** ----------------------------------------------------------------------------------------------------------------- **//
860 
862  const Amg::Vector3D vxpos(-9.99, -9.99, -9.99);
863  MSVertex* vertex = new MSVertex(-1, vxpos, 1., 1., 0, 0, 0);
864  vtx = vertex;
865  }
866 
867  //** ----------------------------------------------------------------------------------------------------------------- **//
868 
869  // vertex finding routine for the endcap
870  void MSVertexRecoTool::MSStraightLineVx_oldMethod(const std::vector<Tracklet>& trks, std::unique_ptr<MSVertex>& vtx,
871  const EventContext& ctx) const {
872  // find the line of flight of the vpion
873  float aveX(0), aveY(0);
874  for (auto trkItr = trks.cbegin(); trkItr != trks.cend(); ++trkItr) {
875  aveX += trkItr->globalPosition().x();
876  aveY += trkItr->globalPosition().y();
877  }
878  float vxphi = std::atan2(aveY, aveX);
879 
880  Amg::Vector3D MyVx(0, 0, 0);
881  std::vector<Tracklet> tracks = RemoveBadTrk(trks, MyVx);
882  if (tracks.size() < 2) return;
883 
884  while (true) {
885  MyVx = VxMinQuad(tracks);
886  std::vector<Tracklet> Tracks = RemoveBadTrk(tracks, MyVx);
887  if (tracks.size() == Tracks.size()) break;
888  tracks = std::move(Tracks);
889  }
890  if (tracks.size() >= 3 && MyVx.x() > 0) {
891  float vxtheta = std::atan2(MyVx.x(), MyVx.z());
892  vxphi = vxPhiFinder(std::abs(vxtheta), vxphi, ctx);
893  Amg::Vector3D vxpos(MyVx.x() * std::cos(vxphi), MyVx.x() * std::sin(vxphi), MyVx.z());
894  // make Trk::Track for each tracklet used in the vertex fit
895  std::vector<xAOD::TrackParticle*> vxTrackParticles;
896  for (std::vector<Tracklet>::iterator trklt = tracks.begin(); trklt != tracks.end(); ++trklt) {
897  AmgSymMatrix(5) covariance = AmgSymMatrix(5)(trklt->errorMatrix());
898  Trk::Perigee* myPerigee =
899  new Trk::Perigee(0., 0., trklt->momentum().phi(), trklt->momentum().theta(), trklt->charge() / trklt->momentum().mag(),
900  Trk::PerigeeSurface(trklt->globalPosition()), covariance);
901  xAOD::TrackParticle* trackparticle = new xAOD::TrackParticle();
902  trackparticle->makePrivateStore();
903  trackparticle->setFitQuality(1., (int)trklt->mdtHitsOnTrack().size());
905 
906  trackparticle->setDefiningParameters(myPerigee->parameters()[Trk::d0], myPerigee->parameters()[Trk::z0],
907  myPerigee->parameters()[Trk::phi0], myPerigee->parameters()[Trk::theta],
908  myPerigee->parameters()[Trk::qOverP]);
909  std::vector<float> covMatrixVec;
910  Amg::compress(covariance, covMatrixVec);
911  trackparticle->setDefiningParametersCovMatrixVec(covMatrixVec);
912 
913  vxTrackParticles.push_back(trackparticle);
914 
915  delete myPerigee;
916  }
917 
918  vtx = std::make_unique<MSVertex>(2, vxpos, vxTrackParticles, 1, (float)vxTrackParticles.size(), 0, 0, 0);
919  }
920  }
921 
922  //** ----------------------------------------------------------------------------------------------------------------- **//
923 
924  std::vector<Tracklet> MSVertexRecoTool::RemoveBadTrk(const std::vector<Tracklet>& tracks, const Amg::Vector3D& Vx) {
925  float MaxTollDist = 300; // max distance between the vertex and tracklet [mm]
926  std::vector<Tracklet> Tracks;
927  if (Vx.x() == 0 && Vx.z() == 0) return tracks;
928  // loop on all tracks and find the worst
929  float WorstTrkDist = MaxTollDist;
930  unsigned int iWorstTrk = 0xC0FFEE;
931  for (unsigned int i = 0; i < tracks.size(); ++i) {
932  float TrkSlope = std::tan(tracks.at(i).getML1seg().alpha());
933  float TrkInter = tracks.at(i).getML1seg().globalPosition().perp() - tracks.at(i).getML1seg().globalPosition().z() * TrkSlope;
934  float dist = std::abs((TrkSlope * Vx.z() - Vx.x() + TrkInter) / std::sqrt(sq(TrkSlope) + 1));
935  if (dist > MaxTollDist && dist > WorstTrkDist) {
936  iWorstTrk = i;
937  WorstTrkDist = dist;
938  }
939  }
940 
941  // Remove the worst track from the list
942  for (unsigned int i = 0; i < tracks.size(); ++i) {
943  if (i != iWorstTrk) Tracks.push_back(tracks.at(i));
944  }
945  return Tracks;
946  }
947 
948  std::vector<Tracklet> MSVertexRecoTool::getTracklets(const std::vector<Tracklet>& trks, const std::set<int>& tracklet_subset) const {
949  std::vector<Tracklet> returnVal;
950  for (auto itr = tracklet_subset.cbegin(); itr != tracklet_subset.cend(); ++itr) {
951  if ((unsigned int)*itr > trks.size()) ATH_MSG_ERROR("ERROR - Index out of bounds in getTracklets");
952  returnVal.push_back(trks.at(*itr));
953  }
954 
955  return returnVal;
956  }
957 
958  //** ----------------------------------------------------------------------------------------------------------------- **//
959 
960  bool MSVertexRecoTool::EndcapHasBadTrack(const std::vector<Tracklet>& tracks, const Amg::Vector3D& Vx) const {
961  float MaxTollDist = m_MaxTollDist;
962  if (Vx.x() == 0 && Vx.z() == 0) return true;
963  // loop on all tracks and find the worst
964  float WorstTrkDist = MaxTollDist;
965  for (auto track = tracks.cbegin(); track != tracks.cend(); ++track) {
966  float TrkSlope = std::tan(((Tracklet)*track).getML1seg().alpha());
967  float TrkInter =
968  ((Tracklet)*track).getML1seg().globalPosition().perp() - ((Tracklet)*track).getML1seg().globalPosition().z() * TrkSlope;
969  float dist = std::abs((TrkSlope * Vx.z() - Vx.x() + TrkInter) / std::sqrt(sq(TrkSlope) + 1));
970  if (dist > MaxTollDist && dist > WorstTrkDist) { return true; }
971  }
972 
973  // No tracks found that are too far, so it is okay.
974  return false;
975  }
976 
977  //** ----------------------------------------------------------------------------------------------------------------- **//
978 
979  StatusCode MSVertexRecoTool::FillOutputContainer(std::vector<MSVertex*>& vertices,
983  for (std::vector<MSVertex*>::const_iterator vxIt = vertices.begin(); vxIt != vertices.end(); ++vxIt) {
984  xAOD::Vertex* xAODVx = new xAOD::Vertex();
985  xAODVx->makePrivateStore();
987  xAODVx->setPosition((*vxIt)->getPosition());
988  xAODVx->setFitQuality((*vxIt)->getChi2(), (*vxIt)->getNTracks() - 1);
989 
990  // store the new xAOD vertex
991  xAODVxContainer->push_back(xAODVx);
992 
993  // dress the vertex with the hit counts
994  hMDT(*xAODVx) = (*vxIt)->getNMDT();
995  hRPC(*xAODVx) = (*vxIt)->getNRPC();
996  hTGC(*xAODVx) = (*vxIt)->getNTGC();
997  }
998 
999  // cleanup
1000  for (auto *x : vertices) delete x;
1001 
1002  vertices.clear();
1003 
1004  return StatusCode::SUCCESS;
1005  }
1006 
1007  //** ----------------------------------------------------------------------------------------------------------------- **//
1008 
1009  // core algorithm for endcap vertex reconstruction
1010  Amg::Vector3D MSVertexRecoTool::VxMinQuad(const std::vector<Tracklet>& tracks) {
1011  double s(0.), sx(0.), sy(0.), sxy(0.), sxx(0.), d(0.);
1012  double sigma = 1.;
1013  for (unsigned int i = 0; i < tracks.size(); ++i) {
1014  double TrkSlope = std::tan(tracks.at(i).getML1seg().alpha());
1015  double TrkInter = tracks.at(i).getML1seg().globalPosition().perp() - tracks.at(i).getML1seg().globalPosition().z() * TrkSlope;
1016  s += 1. / (sq(sigma));
1017  sx += TrkSlope / (sq(sigma));
1018  sxx += sq(TrkSlope) / sq(sigma);
1019  sy += TrkInter / sq(sigma);
1020  sxy += (TrkSlope * TrkInter) / sq(sigma);
1021  }
1022  d = s * sxx - sq(sx);
1023  if (d == 0.) {
1024  Amg::Vector3D MyVx(0., 0., 0.); // return 0, no vertex was found.
1025  return MyVx;
1026  }
1027 
1028  double Rpos = (sxx * sy - sx * sxy) / d;
1029  double Zpos = (sx * sy - s * sxy) / d;
1030 
1031  Amg::Vector3D MyVx(Rpos, 0, Zpos);
1032 
1033  return MyVx;
1034  }
1035 
1036  //** ----------------------------------------------------------------------------------------------------------------- **//
1037 
1038  // vertex phi location -- determined from the RPC/TGC hits
1039  float MSVertexRecoTool::vxPhiFinder(const float theta, const float phi, const EventContext& ctx) const {
1040  float nmeas(0);
1041  float sinphi(0);
1042  float cosphi(0);
1043  if (theta == 0) {
1044  ATH_MSG_WARNING("vxPhiFinder() called with theta=" << theta << " and phi=" << phi << ", return 0");
1045  return 0;
1046  } else if (theta > M_PI) {
1047  ATH_MSG_WARNING("vxPhiFinder() called with theta=" << std::setprecision(15) << theta << " and phi=" << phi
1048  << ", (theta>M_PI), return 0");
1049  return 0;
1050  }
1051  float tanThetaHalf = std::tan(0.5 * theta);
1052  if (tanThetaHalf <= 0) {
1053  ATH_MSG_WARNING("vxPhiFinder() called with theta=" << std::setprecision(15) << theta << " and phi=" << phi
1054  << ", resulting in tan(0.5*theta)<=0, return 0");
1055  return 0;
1056  }
1057  float eta = -std::log(tanThetaHalf);
1058  if (std::abs(eta) < 1.5) {
1060  if (!rpcTES.isValid()) {
1061  ATH_MSG_WARNING("No RpcPrepDataContainer found in SG!");
1062  return 0;
1063  }
1065  Muon::RpcPrepDataContainer::const_iterator RpcItrE = rpcTES->end();
1066  for (; RpcItr != RpcItrE; ++RpcItr) {
1067  Muon::RpcPrepDataCollection::const_iterator rpcItr = (*RpcItr)->begin();
1068  Muon::RpcPrepDataCollection::const_iterator rpcItrE = (*RpcItr)->end();
1069  for (; rpcItr != rpcItrE; ++rpcItr) {
1070  if (m_idHelperSvc->rpcIdHelper().measuresPhi((*rpcItr)->identify())) {
1071  float rpcEta = (*rpcItr)->globalPosition().eta();
1072  float rpcPhi = (*rpcItr)->globalPosition().phi();
1073  float dphi = phi - rpcPhi;
1074  if (dphi > M_PI)
1075  dphi -= 2 * M_PI;
1076  else if (dphi < -M_PI)
1077  dphi += 2 * M_PI;
1078  float deta = eta - rpcEta;
1079  float DR = std::hypot(deta, dphi);
1080  if (DR < 0.6) {
1081  nmeas++;
1082  sinphi += std::sin(rpcPhi);
1083  cosphi += std::cos(rpcPhi);
1084  }
1085  }
1086  }
1087  }
1088  }
1089  if (std::abs(eta) > 0.5) {
1091  if (!tgcTES.isValid()) {
1092  ATH_MSG_WARNING("No TgcPrepDataContainer found in SG!");
1093  return 0;
1094  }
1096  Muon::TgcPrepDataContainer::const_iterator TgcItrE = tgcTES->end();
1097  for (; TgcItr != TgcItrE; ++TgcItr) {
1098  Muon::TgcPrepDataCollection::const_iterator tgcItr = (*TgcItr)->begin();
1099  Muon::TgcPrepDataCollection::const_iterator tgcItrE = (*TgcItr)->end();
1100  for (; tgcItr != tgcItrE; ++tgcItr) {
1101  if (m_idHelperSvc->tgcIdHelper().isStrip((*tgcItr)->identify())) {
1102  float tgcEta = (*tgcItr)->globalPosition().eta();
1103  float tgcPhi = (*tgcItr)->globalPosition().phi();
1104  float dphi = phi - tgcPhi;
1105  if (dphi > M_PI)
1106  dphi -= 2 * M_PI;
1107  else if (dphi < -M_PI)
1108  dphi += 2 * M_PI;
1109  float deta = eta - tgcEta;
1110  float DR = std::hypot(deta, dphi);
1111  if (DR < 0.6) {
1112  nmeas++;
1113  sinphi += std::sin(tgcPhi);
1114  cosphi += std::cos(tgcPhi);
1115  }
1116  }
1117  }
1118  }
1119  }
1120  float vxphi = phi;
1121  if (nmeas > 0) vxphi = std::atan2(sinphi / nmeas, cosphi / nmeas);
1122  return vxphi;
1123  }
1124 
1125  //** ----------------------------------------------------------------------------------------------------------------- **//
1126 
1127  // count the hits (MDT, RPC & TGC) around the vertex
1128  void MSVertexRecoTool::HitCounter(MSVertex* MSRecoVx, const EventContext& ctx) const {
1129  int nHighOccupancy(0);
1130  // Amg::Vector3D.eta() will crash via floating point exception if both x() and y() are zero (eta=inf)
1131  // thus, check it manually here:
1132  const Amg::Vector3D msVtxPos = MSRecoVx->getPosition();
1133  if (msVtxPos.x() == 0 && msVtxPos.y() == 0 && msVtxPos.z() != 0) {
1134  ATH_MSG_WARNING("given MSVertex has position x=y=0 and z!=0, eta() method will cause FPE, returning...");
1135  return;
1136  }
1138  if (!mdtTES.isValid()) ATH_MSG_ERROR("Unable to retrieve the MDT hits");
1139  // MDTs -- count the number around the vertex
1140  int nmdt(0);
1142  Muon::MdtPrepDataContainer::const_iterator MDTItrE = mdtTES->end();
1143  for (; MDTItr != MDTItrE; ++MDTItr) {
1144  if ((*MDTItr)->empty()) continue;
1145  Muon::MdtPrepDataCollection::const_iterator mdt = (*MDTItr)->begin();
1146  Muon::MdtPrepDataCollection::const_iterator mdtE = (*MDTItr)->end();
1147  Amg::Vector3D ChamberCenter = (*mdt)->detectorElement()->center();
1148  float deta = std::abs(msVtxPos.eta() - ChamberCenter.eta());
1149  if (deta > 0.6) continue;
1150  float dphi = msVtxPos.phi() - ChamberCenter.phi();
1151  if (dphi > M_PI)
1152  dphi -= 2 * M_PI;
1153  else if (dphi < -M_PI)
1154  dphi += 2 * M_PI;
1155  if (std::abs(dphi) > 0.6) continue;
1156  int nChHits(0);
1157  Identifier id = (*mdt)->identify();
1158  auto [tubeLayerMin, tubeLayerMax] = m_idHelperSvc->mdtIdHelper().tubeLayerMinMax(id);
1159  auto [tubeMin, tubeMax] = m_idHelperSvc->mdtIdHelper().tubeMinMax(id);
1160  float nTubes = (tubeLayerMax - tubeLayerMin + 1) *
1161  (tubeMax - tubeMin + 1);
1162  for (; mdt != mdtE; ++mdt) {
1163  if ((*mdt)->adc() < 50) continue;
1164  if ((*mdt)->status() != 1) continue;
1165  if ((*mdt)->localPosition()[Trk::locR] == 0.) continue;
1166  nChHits++;
1167  }
1168  nmdt += nChHits;
1169  double ChamberOccupancy = nChHits / nTubes;
1170  if (ChamberOccupancy > m_ChamberOccupancyMin) nHighOccupancy++;
1171  }
1172 
1173  ATH_MSG_DEBUG("Found " << nHighOccupancy << " chambers near the MS vertex with occupancy greater than " << m_ChamberOccupancyMin);
1174  if (nHighOccupancy < m_minHighOccupancyChambers) return;
1175 
1177  if (!rpcTES.isValid()) ATH_MSG_ERROR("Unable to retrieve the RPC hits");
1178  // RPC -- count the number around the vertex
1179  int nrpc(0);
1181  Muon::RpcPrepDataContainer::const_iterator RpcItrE = rpcTES->end();
1182  for (; RpcItr != RpcItrE; ++RpcItr) {
1183  Muon::RpcPrepDataCollection::const_iterator rpcItr = (*RpcItr)->begin();
1184  Muon::RpcPrepDataCollection::const_iterator rpcItrE = (*RpcItr)->end();
1185  for (; rpcItr != rpcItrE; ++rpcItr) {
1186  float rpcEta = (*rpcItr)->globalPosition().eta();
1187  float rpcPhi = (*rpcItr)->globalPosition().phi();
1188  float dphi = msVtxPos.phi() - rpcPhi;
1189  if (dphi > M_PI)
1190  dphi -= 2 * M_PI;
1191  else if (dphi < -M_PI)
1192  dphi += 2 * M_PI;
1193  float deta = msVtxPos.eta() - rpcEta;
1194  float DR = std::hypot(deta, dphi);
1195  if (DR < 0.6) nrpc++;
1196  if (DR > 1.2) break;
1197  }
1198  }
1199  // TGC -- count the number around the vertex
1201  if (!tgcTES.isValid()) ATH_MSG_ERROR("Unable to retrieve the TGC hits");
1202  int ntgc(0);
1204  Muon::TgcPrepDataContainer::const_iterator TgcItrE = tgcTES->end();
1205  for (; TgcItr != TgcItrE; ++TgcItr) {
1206  Muon::TgcPrepDataCollection::const_iterator tgcItr = (*TgcItr)->begin();
1207  Muon::TgcPrepDataCollection::const_iterator tgcItrE = (*TgcItr)->end();
1208  for (; tgcItr != tgcItrE; ++tgcItr) {
1209  float tgcEta = (*tgcItr)->globalPosition().eta();
1210  float tgcPhi = (*tgcItr)->globalPosition().phi();
1211  float dphi = msVtxPos.phi() - tgcPhi;
1212  if (dphi > M_PI)
1213  dphi -= 2 * M_PI;
1214  else if (dphi < -M_PI)
1215  dphi += 2 * M_PI;
1216  float deta = msVtxPos.eta() - tgcEta;
1217  float DR = std::hypot(deta, dphi);
1218  if (DR < 0.6) ntgc++;
1219  if (DR > 1.2) break;
1220  }
1221  }
1222 
1223  MSRecoVx->setNMDT(nmdt);
1224  MSRecoVx->setNRPC(nrpc);
1225  MSRecoVx->setNTGC(ntgc);
1226  }
1227 
1228 } // namespace Muon
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
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:88
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
Muon::MSVertexRecoTool::vxPhiFinder
float vxPhiFinder(const float theta, const float phi, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:1039
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
xAOD::Vertex_v1::setPosition
void setPosition(const Amg::Vector3D &position)
Sets the 3-position.
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
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
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
Muon::MSVertexRecoTool::FillOutputContainer
static StatusCode FillOutputContainer(std::vector< MSVertex * > &, SG::WriteHandle< xAOD::VertexContainer > &xAODVxContainer, SG::WriteDecorHandle< decortype, int > &, SG::WriteDecorHandle< decortype, int > &, SG::WriteDecorHandle< decortype, int > &)
Definition: MSVertexRecoTool.cxx:979
Amg::compress
void compress(const AmgSymMatrix(N) &covMatrix, std::vector< float > &vec)
Definition: EventPrimitivesHelpers.h:56
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
beamspotman.sigmaZ
sigmaZ
Definition: beamspotman.py:1625
xAOD::Vertex
Vertex_v1 Vertex
Define the latest version of the vertex class.
Definition: Event/xAOD/xAODTracking/xAODTracking/Vertex.h:16
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:44
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:35
Muon::MSVertexRecoTool::m_doSystematics
bool m_doSystematics
Definition: MSVertexRecoTool.h:77
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
xAODP4Helpers.h
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
hist_file_dump.d
d
Definition: hist_file_dump.py:137
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
EventPrimitivesHelpers.h
Muon::MSVertexRecoTool::TrkCluster::isSystematic
bool isSystematic
Definition: MSVertexRecoTool.h:51
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:71
python.compressB64.sx
string sx
Definition: compressB64.py:96
Muon::MSVertexRecoTool::m_VxChi2ProbCUT
float m_VxChi2ProbCUT
Definition: MSVertexRecoTool.h:67
skel.it
it
Definition: skel.GENtoEVGEN.py:423
M_PI
#define M_PI
Definition: ActiveFraction.h:11
Trk::Perigee
ParametersT< 5, Charged, PerigeeSurface > Perigee
Definition: Tracking/TrkEvent/TrkParameters/TrkParameters/TrackParameters.h:29
Muon::sq
constexpr float sq(float x)
Definition: MSVertexTrackletTool.cxx:43
xAOD::TrackParticle_v1::setDefiningParameters
void setDefiningParameters(float d0, float z0, float phi0, float theta, float qOverP)
Set the defining parameters.
Definition: TrackParticle_v1.cxx:177
Trk::z0
@ z0
Definition: ParamDefs.h:70
MSVertexRecoTool.h
xAOD::P4Helpers::deltaPhi
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition: xAODP4Helpers.h:69
Muon::MSVertexRecoTool::TrkCluster::eta
float eta
Definition: MSVertexRecoTool.h:47
Muon::MSVertexRecoTool::m_VertexMaxRadialPlane
float m_VertexMaxRadialPlane
Definition: MSVertexRecoTool.h:69
Muon::MSVertexRecoTool::TrkCluster::ntrks
int ntrks
Definition: MSVertexRecoTool.h:49
Muon::MSVertexRecoTool::MSVertexRecoTool
MSVertexRecoTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: MSVertexRecoTool.cxx:33
Trk::locR
@ locR
Definition: ParamDefs.h:50
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
MSVertex
Definition: MSVertex.h:12
covarianceTool.prob
prob
Definition: covarianceTool.py:678
x
#define x
Muon::MSVertexRecoTool::EndcapHasBadTrack
bool EndcapHasBadTrack(const std::vector< Tracklet > &tracklets, const Amg::Vector3D &Vx) const
Definition: MSVertexRecoTool.cxx:960
Muon::MSVertexRecoTool::findTrackClusters
std::vector< TrkCluster > findTrackClusters(const std::vector< Tracklet > &tracklets) const
Definition: MSVertexRecoTool.cxx:359
AmgSymMatrix
#define AmgSymMatrix(dim)
Definition: EventPrimitives.h:52
python.Utilities.clone
clone
Definition: Utilities.py:134
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
Muon::MSVertexRecoTool::m_TrackPhiAngle
float m_TrackPhiAngle
Definition: MSVertexRecoTool.h:66
Muon::MSVertexRecoTool::m_VertexMinRadialPlane
float m_VertexMinRadialPlane
Definition: MSVertexRecoTool.h:70
xAOD::TrackParticle
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Definition: Event/xAOD/xAODTracking/xAODTracking/TrackParticle.h:13
xAOD::TrackParticle_v1::setFitQuality
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
Definition: TrackParticle_v1.cxx:534
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:110
Muon::MSVertexRecoTool::m_mdtTESKey
SG::ReadHandleKey< Muon::MdtPrepDataContainer > m_mdtTESKey
Definition: MSVertexRecoTool.h:103
Muon::MSVertexRecoTool::m_BarrelTrackletUncert
float m_BarrelTrackletUncert
Definition: MSVertexRecoTool.h:64
tubeMax
double tubeMax
Definition: MDT_ResponseTest.cxx:31
Muon::MSVertexRecoTool::m_maxClusterTracklets
unsigned int m_maxClusterTracklets
Definition: MSVertexRecoTool.h:75
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
MSVertex::getNRPC
int getNRPC() const
Definition: MSVertex.cxx:100
FlavorTagDiscriminants::internal::Tracks
std::vector< const xAOD::TrackParticle * > Tracks
Definition: DataPrepUtilities.h:65
ParticleGun_EoverP_Config.momentum
momentum
Definition: ParticleGun_EoverP_Config.py:63
MSVertex::getNMDT
int getNMDT() const
Definition: MSVertex.cxx:99
MSVertex::setNRPC
void setNRPC(const int)
Definition: MSVertex.cxx:96
lumiFormat.i
int i
Definition: lumiFormat.py:92
z
#define z
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
Trk::theta
@ theta
Definition: ParamDefs.h:72
Muon::MSVertexRecoTool::findMSvertices
StatusCode findMSvertices(std::vector< Tracklet > &traklets, std::vector< MSVertex * > &vertices, const EventContext &ctx) const override
Definition: MSVertexRecoTool.cxx:87
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:572
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
sq
#define sq(x)
Definition: CurvedSegmentFinder.cxx:6
Muon::MSVertexRecoTool::MSVxFinder
void MSVxFinder(const std::vector< Tracklet > &tracklets, std::unique_ptr< MSVertex > &vtx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:383
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:530
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:99
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MSVertex::getChi2Probability
float getChi2Probability() const
Definition: MSVertex.cxx:85
JetVoronoiDiagramHelpers::Norm
Point Norm(const Point &a)
Definition: JetVoronoiDiagramHelpers.cxx:79
MSVertex::setNTGC
void setNTGC(const int)
Definition: MSVertex.cxx:97
xAOD::LowPtTrack
@ LowPtTrack
A LowPt track.
Definition: TrackingPrimitives.h:77
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Muon::MSVertexRecoTool::HitCounter
void HitCounter(MSVertex *MSRecoVx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:1128
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
IdentifiableContainerMT::end
const_iterator end() const
return const_iterator for end of container
Definition: IdentifiableContainerMT.h:242
IdentifiableContainerMT::const_iterator
Definition: IdentifiableContainerMT.h:82
MSVertex::setAuthor
void setAuthor(const int)
Definition: MSVertex.cxx:82
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
IdentifiableContainerMT::begin
const_iterator begin() const
return const_iterator for first entry
Definition: IdentifiableContainerMT.h:236
MSVertex::getNTGC
int getNTGC() const
Definition: MSVertex.cxx:101
Muon::MSVertexRecoTool::getTracklets
std::vector< Tracklet > getTracklets(const std::vector< Tracklet > &trks, const std::set< int > &tracklet_subset) const
Definition: MSVertexRecoTool.cxx:948
Trk::muon
@ muon
Definition: ParticleHypothesis.h:28
Vertex.h
xAOD::TrackParticle_v1::setTrackProperties
void setTrackProperties(const TrackProperties properties)
Methods setting the TrackProperties.
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Muon::MSVertexRecoTool::MSStraightLineVx
void MSStraightLineVx(const std::vector< Tracklet > &trks, std::unique_ptr< MSVertex > &vtx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:745
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:224
Muon::MSVertexRecoTool::m_decor_nTGC
SG::WriteDecorHandleKey< decortype > m_decor_nTGC
Definition: MSVertexRecoTool.h:107
Muon::MSVertexRecoTool::m_minHighOccupancyChambers
int m_minHighOccupancyChambers
Definition: MSVertexRecoTool.h:71
Muon::MSVertexRecoTool::m_ChamberOccupancyMin
float m_ChamberOccupancyMin
Definition: MSVertexRecoTool.h:72
Muon::MSVertexRecoTool::MSStraightLineVx_oldMethod
void MSStraightLineVx_oldMethod(const std::vector< Tracklet > &trks, std::unique_ptr< MSVertex > &vtx, const EventContext &ctx) const
Definition: MSVertexRecoTool.cxx:870
Tracklet::mdtHitsOnTrack
const std::vector< const Muon::MdtPrepData * > & mdtHitsOnTrack() const
Muon::MSVertexRecoTool::m_xAODContainerKey
SG::WriteHandleKey< xAOD::VertexContainer > m_xAODContainerKey
Definition: MSVertexRecoTool.h:99
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
Trk::d0
@ d0
Definition: ParamDefs.h:69
Muon::MSVertexRecoTool::TrkCluster::phi
float phi
Definition: MSVertexRecoTool.h:48
ATHRNG::RNGWrapper
A wrapper class for event-slot-local random engines.
Definition: RNGWrapper.h:56
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:494
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
Tracklet::momentum
void momentum(const Amg::Vector3D &p)
Definition: Tracklet.cxx:35
SG::AuxElement::makePrivateStore
void makePrivateStore()
Create a new (empty) private store for this object.
Definition: AuxElement.cxx:172
Muon::MSVertexRecoTool::TrkCluster::trks
int trks[100]
Definition: MSVertexRecoTool.h:50
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::m_rpcTESKey
SG::ReadHandleKey< Muon::RpcPrepDataContainer > m_rpcTESKey
Definition: MSVertexRecoTool.h:101
TrackParticle.h
xAOD::TrackParticle_v1::setDefiningParametersCovMatrixVec
void setDefiningParametersCovMatrixVec(const std::vector< float > &cov)
Definition: TrackParticle_v1.cxx:460
Muon::MSVertexRecoTool::m_EndcapTrackletUncert
float m_EndcapTrackletUncert
Definition: MSVertexRecoTool.h:65
Muon::MSVertexRecoTool::m_useOldMSVxEndcapMethod
int m_useOldMSVxEndcapMethod
Definition: MSVertexRecoTool.h:73
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
Muon::MSVertexRecoTool::m_decor_nMDT
SG::WriteDecorHandleKey< decortype > m_decor_nMDT
Definition: MSVertexRecoTool.h:105
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
MSVertex::setNMDT
void setNMDT(const int)
Definition: MSVertex.cxx:95
VertexContainer.h
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:1010
Muon::MSVertexRecoTool::m_maxGlobalTracklets
unsigned int m_maxGlobalTracklets
Definition: MSVertexRecoTool.h:74
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MSVertexRecoTool::initialize
virtual StatusCode initialize(void) override
Definition: MSVertexRecoTool.cxx:65
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
Muon::MSVertexRecoTool::m_MaxTollDist
float m_MaxTollDist
Definition: MSVertexRecoTool.h:76
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:73
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
Tracklet::globalPosition
const Amg::Vector3D & globalPosition() const
Definition: Tracklet.cxx:47
Muon::MSVertexRecoTool::ClusterizeTracks
TrkCluster ClusterizeTracks(std::vector< Tracklet > &tracks) const
Definition: MSVertexRecoTool.cxx:228
Muon::MSVertexRecoTool::TrkCluster
Definition: MSVertexRecoTool.h:46
Muon::MSVertexRecoTool::m_VxPlaneDist
float m_VxPlaneDist
Definition: MSVertexRecoTool.h:68
Muon::MSVertexRecoTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MSVertexRecoTool.h:109
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
AthAlgTool
Definition: AthAlgTool.h:26
Muon::MSVertexRecoTool::m_tgcTESKey
SG::ReadHandleKey< Muon::TgcPrepDataContainer > m_tgcTESKey
Definition: MSVertexRecoTool.h:102
Muon::MSVertexRecoTool::MakeDummyVertex
static void MakeDummyVertex(MSVertex *&)
Definition: MSVertexRecoTool.cxx:861
Tracklet::charge
void charge(float charge)
Definition: Tracklet.cxx:38
TauGNNUtils::Variables::Track::dEta
bool dEta(const xAOD::TauJet &tau, const xAOD::TauTrack &track, double &out)
Definition: TauGNNUtils.cxx:525
Muon::MSVertexRecoTool::TrkCluster::tracks
std::vector< Tracklet > tracks
Definition: MSVertexRecoTool.h:52
Tracklet
Definition: Tracklet.h:15
readCCLHist.float
float
Definition: readCCLHist.py:83
Trk::phi0
@ phi0
Definition: ParamDefs.h:71
VertexAuxContainer.h
fitman.k
k
Definition: fitman.py:528
Muon::MSVertexRecoTool::m_extrapolator
ToolHandle< Trk::IExtrapolator > m_extrapolator
Definition: MSVertexRecoTool.h:63
Muon::MSVertexRecoTool::m_decor_nRPC
SG::WriteDecorHandleKey< decortype > m_decor_nRPC
Definition: MSVertexRecoTool.h:106
MSVertex::getPosition
const Amg::Vector3D & getPosition() const
Definition: MSVertex.cxx:78
Muon::MSVertexRecoTool::RemoveBadTrk
static std::vector< Tracklet > RemoveBadTrk(const std::vector< Tracklet > &tracklets, const Amg::Vector3D &Vx)
Definition: MSVertexRecoTool.cxx:924