ATLAS Offline Software
MooCandidateMatchingTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <cmath>
8 #include <cstdlib>
9 #include <iomanip>
10 #include <sstream>
11 #include <string>
12 
25 
26 namespace { // local funcs
27 
28  // limit angle difference to -pi/2 < x <= pi/2
29  inline double theta_diff(double x) {
30  while (x <= -M_PI_2) x += M_PI;
31  while (x > +M_PI_2) x -= M_PI;
32  return x;
33  }
34 
35  // limit angle difference to -pi < x <= pi
36  inline double phi_diff(double x) {
37  while (x <= -M_PI) x += 2.0 * M_PI;
38  while (x > +M_PI) x -= 2.0 * M_PI;
39  return x;
40  }
41 
42  // print covariance and correlation on one line
43  std::string printCovCorr(Amg::MatrixX& cov, const std::string& title, unsigned int prec = 3) {
44  std::ostringstream oss;
45  oss << title << " " << Amg::toString(cov, prec) << std::endl;
46  return oss.str();
47  }
48 
49 } // namespace
50 
51 namespace Muon {
52 
54 
57  MCTBTrack = nullptr;
58  MCTBSegment = nullptr;
59  }
60 
61  MooCandidateMatchingTool::MooCandidateMatchingTool(const std::string& t, const std::string& n, const IInterface* p) :
62  AthAlgTool(t, n, p) {
63  declareInterface<MooCandidateMatchingTool>(this);
64  declareInterface<IMuonTrackSegmentMatchingTool>(this);
65 
66  declareProperty("RequireSameSide", m_requireSameSide = false,
67  "require entries to be on the same side of the Perigee or Calorimeter");
68  declareProperty("MinimumRadiusSideMatch", m_minimumSideMatchRadius = 4000., "All intersects outside the radius will be accepted");
69  declareProperty("CaloMatchZ", m_caloMatchZ = 6500., "limit in Z to determine Calo crossing");
70  declareProperty("MatchAngleXCut", m_matchAngXCut = 0.1,
71  "Local X (phi) angle difference cut for track-segment matching. Disabled if 0");
72  declareProperty("MatchAngleYCut", m_matchAngYCut = 0.01,
73  "Local Y (theta) angle difference cut for track-segment matching. Disabled if 0");
74  declareProperty("MatchAngleXPullCut", m_matchAngXPullCut = 10.0,
75  "Local X (phi) angle difference pull cut for track-segment matching. Disabled if 0");
76  declareProperty("MatchAngleYPullCut", m_matchAngYPullCut = 25.0,
77  "Local Y (theta) angle difference pull cut for track-segment matching. Disabled if 0");
78  declareProperty("MatchPosXCut", m_matchPosXCut = 100.0,
79  "Local X (2nd coord) position difference cut (mm) for track-segment matching. Disabled if 0");
80  declareProperty("MatchPosYCut", m_matchPosYCut = 30.0,
81  "Local Y (precision) position difference cut (mm) for track-segment matching. Disabled if 0");
82  declareProperty("MatchPosPullCut", m_matchPosPullCut = 10.0, "Local position pull cut for track-segment matching. Disabled if 0");
83  declareProperty("MatchChiSquaredCut", m_matchChiSquaredCut = 100.0, "Cut on the track-segment matching chi-squared");
84  declareProperty("MatchChiSquaredCutTight", m_matchChiSquaredCutTight = 25.0,
85  "Cut on the track-segment matching chi-squared in case a tight cut is requested");
86  declareProperty("AlignmentErrorPosX", m_alignErrorPosX = 0.0, "Alignment precision in local X direction");
87  declareProperty("AlignmentErrorPosY", m_alignErrorPosY = 0.0, "Alignment precision in local Y direction");
88  declareProperty("AlignmentErrorAngleX", m_alignErrorAngleX = 0.0, "Alignment precision in local X angle");
89  declareProperty("AlignmentErrorAngleY", m_alignErrorAngleY = 0.0, "Alignment precision in local Y angle");
90 
91  for (unsigned int i = 0; i < TrackSegmentMatchResult::NumberOfReasons; i++) {
92  m_reasonsForMatchOk[i].store(0, std::memory_order_relaxed);
93  m_reasonsForMatchNotOk[i].store(0, std::memory_order_relaxed);
94  }
95  }
96 
98 
100  ATH_CHECK(m_atlasExtrapolator.retrieve());
101  ATH_CHECK(m_idHelperSvc.retrieve());
102  ATH_CHECK(m_edmHelperSvc.retrieve());
103  ATH_CHECK(m_printer.retrieve());
105  ATH_CHECK(m_segmentMatchingTool.retrieve());
107  ATH_CHECK(m_candidateTool.retrieve());
108 
109  return StatusCode::SUCCESS;
110  }
111 
113  int segmentMatchesLoose = m_segmentMatches - m_segmentMatchesTight;
114  int goodSegmentMatchesLoose = m_goodSegmentMatches - m_goodSegmentMatchesTight;
115  double sameScale = m_sameSideOfPerigee != 0 ? m_segmentMatches / m_sameSideOfPerigee : 1.;
116  double scale = m_segmentMatches != 0 ? 1. / ((double)m_segmentMatches) : 1.;
117  double scaleTight = m_segmentMatchesTight != 0 ? 1. / ((double)m_segmentMatchesTight) : 1.;
118  double scaleLoose = segmentMatchesLoose != 0.0 ? 1. / ((double)segmentMatchesLoose) : 1.;
119  msg(MSG::INFO) << std::fixed << std::setprecision(3);
120  msg(MSG::INFO) << "Segment/segment matches: total " << std::setw(7) << m_segmentMatches << " tight " << std::setw(7)
121  << m_segmentMatchesTight << endmsg << " same side " << std::setw(7) << m_sameSideOfPerigee << " fraction "
122  << m_sameSideOfPerigee * scale << endmsg << " other side " << std::setw(7) << m_otherSideOfPerigee << " fraction "
123  << m_otherSideOfPerigee * scale << endmsg << " good total " << std::setw(7) << m_goodSegmentMatches << " fraction "
124  << m_goodSegmentMatches * scale * sameScale << endmsg << " good loose " << std::setw(7) << goodSegmentMatchesLoose
125  << " fraction " << goodSegmentMatchesLoose * scaleLoose * sameScale << endmsg << " good tight " << std::setw(7)
126  << m_goodSegmentMatchesTight << " fraction " << m_goodSegmentMatchesTight * scaleTight * sameScale << endmsg;
127 
128  int segmentTrackMatchesLoose = m_segmentTrackMatches - m_segmentTrackMatchesTight;
129  int goodSegmentTrackMatchesLoose = m_goodSegmentTrackMatches - m_goodSegmentTrackMatchesTight;
130  double sameScaleTrack = m_sameSideOfPerigeeTrk != 0 ? m_segmentTrackMatches / m_sameSideOfPerigeeTrk : 1.;
131  double scaleTrack = m_segmentTrackMatches != 0 ? 1. / ((double)m_segmentTrackMatches) : 1.;
132  double scaleTrackTight = m_segmentTrackMatchesTight != 0 ? 1. / ((double)m_segmentTrackMatchesTight) : 1.;
133  double scaleTrackLoose = segmentTrackMatchesLoose != 0.0 ? 1. / ((double)segmentTrackMatchesLoose) : 1.;
134  msg(MSG::INFO) << "Track/segment matches: total " << std::setw(7) << m_segmentTrackMatches << " tight " << std::setw(7)
135  << m_segmentTrackMatchesTight << endmsg << " same side " << std::setw(7) << m_sameSideOfPerigeeTrk << " fraction "
136  << m_sameSideOfPerigeeTrk * scaleTrack << endmsg << " other side " << std::setw(7) << m_otherSideOfPerigeeTrk
137  << " fraction " << m_otherSideOfPerigeeTrk * scaleTrack << endmsg << " good total " << std::setw(7)
138  << m_goodSegmentTrackMatches << " fraction " << m_goodSegmentTrackMatches * scaleTrack * sameScaleTrack << endmsg
139  << " good loose " << std::setw(7) << goodSegmentTrackMatchesLoose << " fraction "
140  << goodSegmentTrackMatchesLoose * scaleTrackLoose * sameScaleTrack << endmsg << " good tight " << std::setw(7)
141  << m_goodSegmentTrackMatchesTight << " fraction "
142  << m_goodSegmentTrackMatchesTight * scaleTrackTight * sameScaleTrack << endmsg;
143  // get printing width
144  unsigned int nReasons = (int)TrackSegmentMatchResult::NumberOfReasons;
145  unsigned int width = 0;
146  for (unsigned int i = 0; i < nReasons; ++i) {
148  if (w > width) width = w;
149  }
150  // print it
151  msg(MSG::INFO) << " Reasons for match failures:" << endmsg;
152  for (unsigned int i = 0; i < nReasons; ++i) {
155  if (cnt > 0)
156  msg(MSG::INFO) << " " << std::left << std::setw(width) << TrackSegmentMatchResult::reasonString(reason) << std::right
157  << ": " << cnt << endmsg;
158  }
159  msg(MSG::INFO) << " Reasons for match successes:" << endmsg;
160  for (unsigned int i = 0; i < nReasons; ++i) {
161  int cnt = m_reasonsForMatchOk[i];
163  if (cnt > 0)
164  msg(MSG::INFO) << " " << std::left << std::setw(width) << TrackSegmentMatchResult::reasonString(reason) << std::right
165  << ": " << cnt << endmsg;
166  }
167 
168  return StatusCode::SUCCESS;
169  }
170 
171  bool MooCandidateMatchingTool::match(const EventContext& ctx, const MuPatSegment& entry1, const MuPatSegment& entry2, bool useTightCuts) const {
173 
174  // same segments should never be matched!
175  if (&entry1 == &entry2) {
176  ATH_MSG_DEBUG("Matching segment with itself: " << entry1.name << ". Should not happen!. Returning false.");
177  return false;
178  }
179 
180  // check whether SL overlap => same station index, just one station
181  bool isSLOverlap = false;
182  if (entry1.stations().size() == 1 && entry2.stations().size() == 1 && entry1.stations().count(*entry2.stations().begin()))
183  isSLOverlap = true;
184  if (isSLOverlap) {
185  ATH_MSG_DEBUG("Small/large overlap");
186  // don't combine CSC and MDT segments
187  if (entry1.isMdt != entry2.isMdt) {
188  ATH_MSG_DEBUG(" mdt/csc mix ignored");
189  return false;
190  }
191 
192  if (!areInNeighbouringChambers(entry1, entry2)) {
193  ATH_MSG_DEBUG(" not in neighbouring chambers");
194  return false;
195  }
196 
197  if (!checkSegmentDistance(entry1, entry2)) {
198  ATH_MSG_DEBUG(" distance between segments too large");
199  return false;
200  }
201 
202  // check whether there are hits in the same chamber layer
203  std::vector<MuonStationIndex::ChIndex> intersection;
204  std::set_intersection(entry1.chambers().begin(), entry1.chambers().end(), entry2.chambers().begin(), entry2.chambers().end(),
205  std::back_inserter(intersection));
206 
207  if (!intersection.empty()) {
208  ATH_MSG_DEBUG(" Segments are in the same chamber ");
209  return false;
210  }
211 
212  if (m_idHelperSvc->issTgc(*entry1.chamberIds().begin()) || m_idHelperSvc->isMM(*entry1.chamberIds().begin())) { return true; }
213  }
214 
215  ATH_MSG_VERBOSE("Matching segments: " << entry1.name << " and " << entry2.name);
216 
217  if (useTightCuts) ++m_segmentMatchesTight;
218 
219  if (m_requireSameSide && !sameSide(entry1, entry2, m_requireSameSide)) {
221  return false;
222  } else {
224  }
225 
226  // call segment matching tool
227  bool match = true;
228  if (useTightCuts) {
229  match = m_segmentMatchingToolTight->match(ctx, *entry1.segment, *entry2.segment);
230  } else {
231  match = m_segmentMatchingTool->match(ctx, *entry1.segment, *entry2.segment);
232  }
233  if (match) {
235  if (useTightCuts) ++m_goodSegmentMatchesTight;
236  }
237 
238  return match;
239  }
240 
241  bool MooCandidateMatchingTool::match(const EventContext& ctx, const Trk::Track& track, const MuonSegment& segment, bool useTightCuts) const {
242  ATH_MSG_DEBUG("Match track/segment: useTightCuts " << useTightCuts);
243  // convert segment and track
244  std::unique_ptr<Trk::Track> inTrack = std::make_unique<Trk::Track>(track);
245  std::unique_ptr<MuPatTrack> candidate = m_candidateTool->createCandidate(inTrack);
246  if (!candidate) {
247  ATH_MSG_VERBOSE("Failed to create track candidate");
248  return false;
249  }
250  std::unique_ptr<MuPatSegment> segInfo(m_candidateTool->createSegInfo(ctx, segment));
251  if (!segInfo) {
252  ATH_MSG_VERBOSE("Failed to create segment candidate");
253  return false;
254  }
255 
256  // call match
257  const bool ok = match(ctx, *candidate, *segInfo, useTightCuts);
258  ATH_MSG_DEBUG("Match track/segment: result " << ok);
259  // return result
260  return ok;
261  }
262 
263  bool MooCandidateMatchingTool::match(const EventContext& ctx, const MuPatTrack& entry1, const MuPatSegment& entry2, bool useTightCuts) const {
265  if (useTightCuts) ++m_segmentTrackMatchesTight;
266 
267  ATH_MSG_VERBOSE("Matching track: " << entry1.segmentNames() << " with segment: " << entry2.name);
268 
269  if (m_requireSameSide && !sameSide(entry1, entry2, m_requireSameSide)) {
270 
272  return false;
273  } else {
275  }
276 
277  // pre-matching using segment-segment matching
278  // 0=no segments match,1=any segment match,2=all segment match
279 
280  // First pass filtering: call segment matching tool for all segment on candidate
281  bool haveMatch = true;
283  bool haveAllMatch = true;
284  bool haveAnyMatch = false;
285  const std::vector<MuPatSegment*>& segments = entry1.segments();
286  for (const MuPatSegment* segment : segments) {
287  if (!match(ctx, *segment, entry2, false)) {
288  haveAllMatch = false;
289  } else {
290  haveAnyMatch = true;
291  }
292  }
294  haveMatch = haveAnyMatch;
295  } else if (m_trackSegmentPreMatchingStrategy == 2) {
296  haveMatch = haveAllMatch;
297  }
298 
299  if (!haveMatch) {
300  ATH_MSG_VERBOSE("track-segment match: -> Failed in comparing segments on track");
301 
303  return false;
304  }
305  }
306 
309  calculateTrackSegmentMatchResult(ctx, entry1, entry2, info);
310  TrackSegmentMatchCuts cuts = getMatchingCuts(entry1, entry2, useTightCuts);
311  haveMatch = applyTrackSegmentCuts(ctx, info, cuts);
312  // update counters
313  if (haveMatch) {
314  ++m_reasonsForMatchOk[info.reason];
315  } else {
316  ++m_reasonsForMatchNotOk[info.reason];
317  }
318  }
319 
320  if (haveMatch) {
322  if (useTightCuts) ++m_goodSegmentTrackMatchesTight;
323  }
324 
325  return haveMatch;
326  }
327 
329  bool useTightCuts) const {
331  cuts.useTightCuts = useTightCuts;
332  cuts.posXCut = m_matchPosXCut;
333  cuts.posYCut = m_matchPosYCut;
334  cuts.posXPullCut = m_matchPosPullCut;
335  cuts.posYPullCut = m_matchPosPullCut;
336  cuts.angleXCut = m_matchAngXCut;
337  cuts.angleYCut = m_matchAngYCut;
338  cuts.angleXPullCut = m_matchAngXPullCut;
339  cuts.angleYPullCut = m_matchAngYPullCut;
340  if (useTightCuts) {
341  cuts.matchChiSquaredCut = m_matchChiSquaredCutTight;
342  } else {
343  cuts.matchChiSquaredCut = m_matchChiSquaredCut;
344  }
345 
346  cuts.cutOnMatchChiSquared = true;
349  // CSC
350  cuts.cutOnPosX = true;
351  cuts.cutOnPosY = true;
352  cuts.cutOnPosXPull = true;
353  cuts.cutOnPosYPull = true;
354  cuts.cutOnAngleX = true;
355  cuts.cutOnAngleY = true;
356  cuts.cutOnAngleXPull = true;
357  cuts.cutOnAngleYPull = true;
358  } else { // ! containsChamber(CSS || CSL)
359  // MDT
360  cuts.cutOnPosX = false;
361  cuts.cutOnPosY = true;
362  cuts.cutOnPosXPull = false;
363  cuts.cutOnPosYPull = true;
364  cuts.cutOnAngleX = false;
365  cuts.cutOnAngleY = true;
366  cuts.cutOnAngleXPull = false;
367  cuts.cutOnAngleYPull = true;
368  }
369 
370  if (cuts.posXCut == 0.0) cuts.cutOnPosX = false;
371  if (cuts.posYCut == 0.0) cuts.cutOnPosY = false;
372  if (cuts.angleXCut == 0.0) cuts.cutOnAngleX = false;
373  if (cuts.angleYCut == 0.0) cuts.cutOnAngleY = false;
374  if (cuts.posXPullCut == 0.0) cuts.cutOnPosXPull = false;
375  if (cuts.posYPullCut == 0.0) cuts.cutOnPosYPull = false;
376  if (cuts.angleXPullCut == 0.0) cuts.cutOnAngleXPull = false;
377  if (cuts.angleYPullCut == 0.0) cuts.cutOnAngleYPull = false;
378  if (cuts.matchChiSquaredCut == 0.0) cuts.cutOnMatchChiSquared = false;
379 
380  return cuts;
381  }
382 
384  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << "track segment match:";
385 
387  // for tracks that have no momentum, but need a curved match
388  // fall-back to segment matching with the closest segment
389  MuPatSegment* closestSegment = nullptr;
390  double closestSegmentDist = 1E9;
391  std::vector<MuPatSegment*>::const_iterator itS = info.MCTBTrack->segments().begin(), itS_end = info.MCTBTrack->segments().end();
392  for (; itS != itS_end; ++itS) {
393  // calculate distance along the direction of the segment on the track
394  double dist =
395  (info.MCTBSegment->entryPars().position() - (*itS)->entryPars().position()).dot((*itS)->entryPars().momentum().unit());
396  // store closest distance
397  if (std::abs(dist) < std::abs(closestSegmentDist)) {
398  closestSegmentDist = dist;
399  closestSegment = *itS;
400  }
401  }
402 
403  if (!closestSegment) {
405  info.matchOK = true;
406  } else { // closestSegment
407  // call segment matching tool
408  if (cuts.useTightCuts) {
409  info.matchOK = m_segmentMatchingToolTight->match(ctx, *(closestSegment->segment), *(info.segment));
410  } else {
411  info.matchOK = m_segmentMatchingTool->match(ctx, *(closestSegment->segment), *(info.segment));
412  }
413  if (msgLvl(MSG::DEBUG)) {
414  if (info.matchOK) {
415  msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed";
416  } else {
417  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed";
418  }
419  msg(MSG::DEBUG) << " segment match between segment-on-track "
420  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.trackChamberId)) << " and segment "
421  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.segmentChamberId)) << endmsg;
422  }
424  info.trackChamberId = closestSegment->chid;
425  } // else closestSegment
426 
427  return info.matchOK;
428  } // if ( info.reason == TrackSegmentMatchResult::NoMomentumWithMagField )
429 
430  if (msgLvl(MSG::VERBOSE)) {
431  msg(MSG::DEBUG) << MSG::VERBOSE << std::fixed;
432  if (info.havePosXError) {
433  double diff = info.localPosXDiff;
434  double totErr = std::sqrt(info.posXTotalErr2);
435  double pull = totErr != 0.0 ? diff / totErr : 0.0;
436  msg(MSG::DEBUG) << std::endl
437  << std::setprecision(3) << "deltaPosX =" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
438  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull << std::setprecision(3)
439  << " (align=" << m_alignErrorPosX << " meas=" << std::sqrt(info.posXMeasErr2)
440  << " pred=" << std::sqrt(info.posXPredErr2) << ")";
441  }
442  if (info.havePosYError) {
443  double diff = info.localPosYDiff;
444  double totErr = std::sqrt(info.posYTotalErr2);
445  double pull = totErr != 0.0 ? diff / totErr : 0.0;
446  msg(MSG::DEBUG) << std::endl
447  << std::setprecision(3) << "deltaPosY =" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
448  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull
449  << " (align=" << m_alignErrorPosY << " meas=" << std::sqrt(info.posYMeasErr2)
450  << " pred=" << std::sqrt(info.posYPredErr2) << ")";
451  }
452  if (info.haveAngleXError) {
453  double diff = info.localAngleXDiff;
454  double totErr = std::sqrt(info.angleXTotalErr2);
455  double pull = totErr != 0.0 ? diff / totErr : 0.0;
456  msg(MSG::DEBUG) << std::endl
457  << std::setprecision(5) << "deltaAngleX=" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
458  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull << std::setprecision(5)
459  << " (align=" << m_alignErrorAngleX << " meas=" << std::sqrt(info.angleXMeasErr2)
460  << " pred=" << std::sqrt(info.angleXPredErr2) << ")";
461  }
462  if (info.haveAngleYError) {
463  double diff = info.localAngleYDiff;
464  double totErr = std::sqrt(info.angleYTotalErr2);
465  double pull = totErr != 0.0 ? diff / totErr : 0.0;
466  msg(MSG::DEBUG) << std::endl
467  << std::setprecision(5) << "deltaAngleY=" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
468  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull << std::setprecision(5)
469  << " (align=" << m_alignErrorAngleY << " meas=" << std::sqrt(info.angleYMeasErr2)
470  << " pred=" << std::sqrt(info.angleYPredErr2) << ")";
471  }
472 
473  msg(MSG::DEBUG) << std::endl << std::setprecision(5) << "Difference vector:" << info.diffVector;
474  msg(MSG::DEBUG) << printCovCorr(info.measuredCovariance, "Measured") << printCovCorr(info.predictionCovariance, "Predicted")
475  << printCovCorr(info.totalCovariance, "Total") << "Match chi-squared: " << info.matchChiSquared
476  << " sqrt=" << std::sqrt(info.matchChiSquared);
477 
478  // finish on new line
479  if (info.havePosXError || info.havePosYError || info.haveAngleXError || info.haveAngleYError) { msg(MSG::DEBUG) << std::endl; }
480  }
481 
482  //
483  // Start checking all cuts
484  //
485  info.resetCuts();
486  //
487  // apply cut on positions
488  //
489  double scaledPosXErr2 = cuts.posXPullCut * cuts.posXPullCut * info.posXTotalErr2;
490 
491  // cut on absolute X position
492  if (cuts.cutOnPosX && info.havePosX) {
493  double posXCut2 = cuts.posXCut * cuts.posXCut + scaledPosXErr2;
494  if (info.localPosXDiff * info.localPosXDiff > posXCut2) {
495  if (msgLvl(MSG::DEBUG)) {
496  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
497  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.segmentChamberId))
498  << " X position cut: " << info.localPosXDiff << " > " << std::sqrt(posXCut2) << endmsg;
499  }
501  } else {
503  }
504  }
505 
506  double scaledPosYErr2 = cuts.posYPullCut * cuts.posYPullCut * info.posYTotalErr2;
507 
508  // cut on absolute Y position
509  if (cuts.cutOnPosY && info.havePosY) {
510  double posYCut2 = cuts.posYCut * cuts.posYCut + scaledPosYErr2;
511  if (info.localPosYDiff * info.localPosYDiff > posYCut2) {
512  if (msgLvl(MSG::DEBUG)) {
513  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
514  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
515  << " Y position cut: " << info.localPosYDiff << " > " << std::sqrt(posYCut2) << endmsg;
516  }
518  } else {
520  }
521  }
522 
523  // cut on X position pull
524  if (cuts.cutOnPosXPull && info.havePosX && info.posXTotalErr2 > 0.0) {
525  if (info.localPosXDiff * info.localPosXDiff > scaledPosXErr2) {
526  if (msgLvl(MSG::DEBUG)) {
527  double pull = info.localPosXDiff / std::sqrt(info.posXTotalErr2);
528  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
529  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
530  << " X position pull cut: |" << pull << "| > " << cuts.posXPullCut << endmsg;
531  }
533  } else {
535  }
536  }
537 
538  // cut on Y position pull
539  if (cuts.cutOnPosYPull && info.havePosY && info.posYTotalErr2 > 0.0) {
540  if (info.localPosYDiff * info.localPosYDiff > scaledPosYErr2) {
541  if (msgLvl(MSG::DEBUG)) {
542  double pull = info.localPosYDiff / std::sqrt(info.posYTotalErr2);
543  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
544  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
545  << " Y position pull cut: |" << pull << "| > " << cuts.posYPullCut << endmsg;
546  }
548  } else {
550  }
551  }
552 
553  //
554  // apply cut on angles
555  //
556  double scaledAngleXErr2 = cuts.angleXPullCut * cuts.angleXPullCut * info.angleXTotalErr2;
557 
558  // cut on absolute X angle
559  if (cuts.cutOnAngleX && info.haveAngleX) {
560  double angleXCut2 = cuts.angleXCut * cuts.angleXCut + scaledAngleXErr2;
561  if (info.localAngleXDiff * info.localAngleXDiff > angleXCut2) {
562  if (msgLvl(MSG::DEBUG)) {
563  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
564  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.segmentChamberId))
565  << " X angle cut: " << info.localAngleXDiff << " > " << std::sqrt(angleXCut2) << endmsg;
566  }
568  } else {
570  }
571  }
572 
573  double scaledAngleYErr2 = cuts.angleYPullCut * cuts.angleYPullCut * info.angleYTotalErr2;
574 
575  // cut on absolute Y angle
576  if (cuts.cutOnAngleY && info.haveAngleY) {
577  double angleYCut2 = cuts.angleYCut * cuts.angleYCut + scaledAngleYErr2;
578  if (info.localAngleYDiff * info.localAngleYDiff > angleYCut2) {
579  if (msgLvl(MSG::DEBUG)) {
580  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
581  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
582  << " Y angle cut: " << info.localAngleYDiff << " > " << std::sqrt(angleYCut2) << endmsg;
583  }
585  } else {
587  }
588  }
589 
590  // cut on X angle pull
591  if (cuts.cutOnAngleXPull && info.haveAngleX && info.angleXTotalErr2 > 0.0) {
592  if (info.localAngleXDiff * info.localAngleXDiff > scaledAngleXErr2) {
593  if (msgLvl(MSG::DEBUG)) {
594  double pull = info.localAngleXDiff / std::sqrt(info.angleXTotalErr2);
595  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
596  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
597  << " X angle pull cut: |" << pull << "| > " << cuts.angleXPullCut << endmsg;
598  }
600  } else {
602  }
603  }
604 
605  if (cuts.cutOnAngleYPull && info.haveAngleY && info.angleYTotalErr2 > 0.0) {
606  // cut on Y angle pull
607  if (info.localAngleYDiff * info.localAngleYDiff > scaledAngleYErr2) {
608  if (msgLvl(MSG::DEBUG)) {
609  double pull = info.localAngleYDiff / std::sqrt(info.angleYTotalErr2);
610  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
611  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
612  << " Y angle pull cut: |" << pull << "| > " << cuts.angleYPullCut << endmsg;
613  }
615  } else {
617  }
618  }
619 
620  //
621  // Cut on total chiSquared
622  //
623  if (cuts.cutOnMatchChiSquared && info.haveMatchChiSquared) {
624  // cut on matching chi-squared
625  if (info.matchChiSquared > cuts.matchChiSquaredCut) {
626  if (msgLvl(MSG::DEBUG)) {
627  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
628  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
629  << " match chi-squared cut: " << info.matchChiSquared << " > " << cuts.matchChiSquaredCut << endmsg;
630  }
632  } else {
634  }
635  }
636 
637  //
638  // Based on all cuts, decide to accept or reject
639  //
640 
641  // match is OR of several matches
642  info.matchOK = false;
643  // if any cut was applied
644  if (info.appliedAnyCut()) {
645  if (info.passedAllCuts()) {
646  info.matchOK = true;
648  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed all cuts";
649  } else if (info.passedCut(TrackSegmentMatchResult::MatchChiSquaredCut)) {
650  info.matchOK = true;
652  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed match chi-quared cut";
653  } else if ((info.passedCut(TrackSegmentMatchResult::PosXCut) || info.passedCut(TrackSegmentMatchResult::PosXPullCut)) &&
657  info.matchOK = true;
659  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed cuts " << info.passedCutsString();
660  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed cuts " << info.failedCutsString();
661  } else {
663  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed cuts " << info.failedCutsString();
664  }
665  } else { // !info.appliedCuts
666  if (info.reason == TrackSegmentMatchResult::Unknown) {
668  if (msgLvl(MSG::DEBUG)) { msg(MSG::DEBUG) << MSG::DEBUG << ". No cuts applied"; } // if msgLvl(MSG::DEBUG)
669  } // if reason == Unknown
670  } // !appliedCuts
671 
672  if (msgLvl(MSG::DEBUG)) {
673  if (info.matchOK) {
674  msg(MSG::DEBUG) << MSG::DEBUG << " -> Accepted because " << info.reasonString() << endmsg;
675  } else {
676  msg(MSG::DEBUG) << MSG::DEBUG << " -> Rejected because " << info.reasonString() << endmsg;
677  }
678  }
679 
680  return info.matchOK;
681  } // applyTrackSegmentCuts()
682 
683  void MooCandidateMatchingTool::calculateTrackSegmentMatchResult(const EventContext& ctx, const MuPatTrack& entry1, const MuPatSegment& entry2,
685  info.clear();
686  info.MCTBTrack = &entry1;
687  info.MCTBSegment = &entry2;
688  info.track = &entry1.track();
689  info.segment = entry2.segment;
690  info.segmentChamberId = entry2.chid;
691  if (!entry2.segment) {
692  ATH_MSG_WARNING(__FUNCTION__ << " entry2 does not have segment pointer.");
694  return;
695  }
696  int sector2 = m_idHelperSvc->sector(info.segmentChamberId);
697  bool hasStereoAngle = false;
698 
699  // find closest track parameters
700  const Trk::TrackParameters* closestPars = nullptr;
701  double closestParsDist = 1E9;
702  const Trk::TrackParameters* closestMeasPars = nullptr;
703  double closestMeasParsDist = 1E9;
704  // const Trk::TrackStateOnSurface* closestTSOS = 0;
705  Identifier closestId;
706  double closestIdDist = 1E9;
707  bool trackHasPhi = true;
708 
709  MagField::AtlasFieldCache fieldCache;
710  // Get field cache object
712  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
713 
714  if (fieldCondObj == nullptr) {
715  ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
716  return;
717  }
718  fieldCondObj->getInitializedCache(fieldCache);
719 
720  // loop over TSOS
721  const Trk::TrackStates* tsoses = entry1.track().trackStateOnSurfaces();
723  Trk::TrackStates::const_iterator tit_end = tsoses->end();
724  for (; tit != tit_end; ++tit) {
725  const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
726 
727  // do not want to start from a pseudo-measurement
728  const Trk::PseudoMeasurementOnTrack* pseudo = dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas);
729  if (pseudo) {
730  trackHasPhi = false;
731  continue;
732  }
733 
734  // do not want to start from non-MS measurements
735  Identifier id;
736  if (meas) {
737  id = m_edmHelperSvc->getIdentifier(*meas);
738  if (id.is_valid()) {
739  if (!m_idHelperSvc->isMuon(id)) continue;
740  if (m_idHelperSvc->isMdt(id) && m_idHelperSvc->sector(id) != sector2) hasStereoAngle = true;
741  }
742  }
743 
744  const Trk::TrackParameters* pars = (*tit)->trackParameters();
745  if (!pars) { continue; }
746 
747  // calculate distance along the direction of the track
748  double dist = (entry2.entryPars().position() - pars->position()).dot(entry1.entryPars().momentum().unit());
749  // store closest distance
750  if (std::abs(dist) < std::abs(closestParsDist)) {
751  // closestTSOS = *tit;
752  closestParsDist = dist;
753  closestPars = pars;
754  if (pars->covariance()) {
755  closestMeasParsDist = dist;
756  closestMeasPars = pars;
757  }
758  }
759  // store closest MDT or CSC ID (for printout and performance analysis)
760  if (std::abs(dist) < std::abs(closestIdDist)) {
761  if (meas && id.is_valid() && m_idHelperSvc->isMuon(id) && (m_idHelperSvc->isMdt(id) || m_idHelperSvc->isCsc(id))) {
762  closestId = id;
763  closestIdDist = dist;
764  }
765  }
766  }
767 
768  // update trackHasPhi in the cases where we do have enough phi constraints
769  if (entry1.phiHits().size() > 1) {
770  // calculate difference between hits
771  const Amg::Vector3D& gposFirstPhi = entry1.phiHits().front()->globalPosition();
772  const Amg::Vector3D& gposLastPhi = entry1.phiHits().back()->globalPosition();
773  Amg::Vector3D globalDistance = gposLastPhi - gposFirstPhi;
774 
775  // calculate 'projective' distance
776  double distance = entry1.hasEndcap() ? fabs(globalDistance.z()) : globalDistance.perp();
777 
778  if (distance > 500) trackHasPhi = true;
779  }
780 
781  if (!closestPars) {
782  ATH_MSG_DEBUG("track-segment match: No closest track parameters found.");
784  return;
785  }
786 
787  // set the identification of the first entry (the track - taking the closest point)
788  if (closestPars && closestId.is_valid()) { info.trackChamberId = m_idHelperSvc->chamberId(closestId); }
789 
790  if (msgLvl(MSG::VERBOSE)) {
791  msg(MSG::DEBUG) << MSG::VERBOSE << "match Closest chamber: " << m_idHelperSvc->toStringChamber(info.trackChamberId)
792  << " Segment: " << m_idHelperSvc->toStringChamber(info.segmentChamberId);
793  const Trk::TrackParameters* tmpPars = nullptr;
794  if (closestMeasPars) tmpPars = closestMeasPars->covariance() ? closestMeasPars : nullptr;
795  if (tmpPars) {
796  msg(MSG::DEBUG) << std::endl
797  << "Closest measured track parameters: " << m_printer->print(*tmpPars) << std::endl
798  << Amg::toString(*tmpPars->covariance(), 10) << " distance=" << closestMeasParsDist;
799  }
800  if (!tmpPars || tmpPars != closestPars) {
801  msg(MSG::DEBUG) << std::endl
802  << "Closest track parameters : " << m_printer->print(*closestPars)
803  << " distance=" << closestParsDist;
804  }
805  msg(MSG::DEBUG) << endmsg;
806  }
807 
808  bool straightLineMatch = !fieldCache.toroidOn();
809  if (hasStereoAngle && !trackHasPhi && (straightLineMatch || entry1.hasMomentum())) {
810  // can not do any extrapolation (not reliable)
812  return;
813  }
814 
815  // if extrapolating within EM-EO, can use straight-line extrapolator even without momentum
816  if (!straightLineMatch && !entry1.hasMomentum() && info.trackChamberId.is_valid()) {
817  MuonStationIndex::StIndex trackStationIndex = m_idHelperSvc->stationIndex(info.trackChamberId);
818  MuonStationIndex::StIndex segmentStationIndex = entry2.stIndex;
819  if (((trackStationIndex == MuonStationIndex::StIndex::EM && segmentStationIndex == MuonStationIndex::StIndex::EO) ||
820  (trackStationIndex == MuonStationIndex::StIndex::EO && segmentStationIndex == MuonStationIndex::StIndex::EM)) &&
821  closestPars->position().z() * entry2.entryPars().position().z() > 0.0) {
822  straightLineMatch = true;
823  ATH_MSG_DEBUG("track in " << m_idHelperSvc->toStringStation(info.trackChamberId) << " and segment in "
824  << m_idHelperSvc->toStringStation(info.segmentChamberId)
825  << " => doing straight line extrapolation match");
826  }
827  }
828 
829  //
830  // for tracks that have a momentum or have straight line match
831  //
832  if (straightLineMatch || entry1.hasMomentum()) {
833  // extrapolate to segment surface
834  std::unique_ptr<const Trk::TrackParameters> exPars;
835  const Trk::TrackParameters* exMeasPars = nullptr;
836  if (closestMeasPars) {
837  const Trk::TrackParameters* tmpPars = closestMeasPars->covariance() ? closestMeasPars : nullptr;
838 
839  if (tmpPars) {
840  // Check sector+
841  if (!m_idHelperSvc->isMuon(info.trackChamberId)) {
843  return;
844  }
845  int trackSector = m_idHelperSvc->sector(info.trackChamberId);
846  int segmentSector = m_idHelperSvc->sector(info.segmentChamberId);
847  int sectorDiff = std::abs(trackSector - segmentSector);
848  if (sectorDiff > 1 && sectorDiff != 15) {
849  ATH_MSG_VERBOSE("track sector =" << trackSector << " segment sector =" << segmentSector
850  << " => not in neighbouring sectors ");
851 
853  return;
854  }
855  // Check sector-
856 
857  if (straightLineMatch && !entry1.hasMomentum()) {
858  exPars = m_atlasExtrapolator->extrapolateDirectly(ctx, *tmpPars, entry2.segment->associatedSurface(),
859  Trk::anyDirection, false, Trk::muon);
860  } else {
861  ATH_MSG_VERBOSE(" Extrapolating to other segment " << m_printer->print(*tmpPars) << std::endl
862  << Amg::toString(*tmpPars->covariance(), 10));
863  exPars = m_atlasExtrapolator->extrapolate(ctx, *tmpPars, entry2.segment->associatedSurface(), Trk::anyDirection,
864  false, Trk::muon);
865  }
866  }
867  if (!exPars) {
868  ATH_MSG_DEBUG("track-segment match: Failed to extrapolate measured track parameters\n"
869  << m_printer->print(*closestPars) << "\nfrom " << m_idHelperSvc->toStringChamber(info.trackChamberId)
870  << " to segment surface " << m_idHelperSvc->toStringChamber(info.segmentChamberId));
871  info.matchOK = false;
873  return;
874  }
875 
876  exMeasPars = exPars->covariance() ? exPars.get() : nullptr;
877  if (!exMeasPars) {
878  ATH_MSG_DEBUG("track-segment match: Did not get measured track parameters from extrapolation\n"
879  << "\nfrom " << m_idHelperSvc->toStringChamber(info.trackChamberId) << " to segment surface "
880  << m_idHelperSvc->toStringChamber(info.segmentChamberId));
882  return;
883  }
884  ATH_MSG_VERBOSE(" ExMeasParameters " << exMeasPars << " " << m_printer->print(*exMeasPars) << std::endl
885  << Amg::toString(*exMeasPars->covariance(), 10));
886 
887  } else {
888  // no closest measured parameters, take closest parameters
889 
890  if (straightLineMatch && !entry1.hasMomentum()) {
891  exPars = m_atlasExtrapolator->extrapolateDirectly(ctx, *closestPars, entry2.segment->associatedSurface(),
892  Trk::anyDirection, false, Trk::muon);
893  } else {
894  exPars = m_atlasExtrapolator->extrapolate(ctx, *closestPars, entry2.segment->associatedSurface(), Trk::anyDirection,
895  false, Trk::muon);
896  }
897  if (!exPars) {
898  ATH_MSG_DEBUG("track-segment match: Failed to extrapolate track parameters without errors\n"
899  << m_printer->print(*closestPars) << "\nfrom " << m_idHelperSvc->toStringChamber(info.trackChamberId)
900  << " to segment surface " << m_idHelperSvc->toStringChamber(info.segmentChamberId));
901  info.matchOK = false;
903  return;
904  }
905  }
906 
907  // get the available measured information by looking at the errors
908  // check measurement errors
909  const Amg::MatrixX& measErrors = entry2.segment->localCovariance();
910 
911  double posXMeasErr2 = measErrors(Trk::locX, Trk::locX);
912  if (posXMeasErr2 <= 999.0) {
913  info.havePosX = true;
914  info.havePosXError = true;
915  info.posXMeasErr2 = posXMeasErr2;
916  info.posXTotalErr2 += posXMeasErr2;
917  }
918 
919  double posYMeasErr2 = measErrors(Trk::locY, Trk::locY);
920  if (info.posYMeasErr2 <= 999.0) {
921  info.havePosY = true;
922  info.havePosYError = true;
923  info.posYMeasErr2 = posYMeasErr2;
924  info.posYTotalErr2 += posYMeasErr2;
925  }
926  double phiMeasErr2 = measErrors(Trk::phi, Trk::phi);
927  double thetaMeasErr2 = measErrors(Trk::theta, Trk::theta);
928  if (phiMeasErr2 <= 999.0) {
929  info.haveAngleX = true;
930  info.haveAngleXError = true;
931  info.angleXMeasErr2 = phiMeasErr2;
932  info.angleXTotalErr2 += phiMeasErr2;
933  }
934  if (thetaMeasErr2 <= 999.0) {
935  info.haveAngleY = true;
936  info.haveAngleYError = true;
937  info.angleYMeasErr2 = thetaMeasErr2;
938  info.angleYTotalErr2 += thetaMeasErr2;
939  }
940 
941  // require extrapolation errors to enable use of errors
942  if (!exMeasPars) {
943  info.haveAngleXError = false;
944  info.haveAngleYError = false;
945  info.havePosXError = false;
946  info.havePosYError = false;
947  }
948 
949  // calculate position difference
950  info.localPosXDiff = exPars->parameters()[Trk::locX] - entry2.segment->localParameters()[Trk::locX];
951  info.localPosYDiff = exPars->parameters()[Trk::locY] - entry2.segment->localParameters()[Trk::locY];
952 
953  // calculate angle difference
954  Trk::LocalDirection locDirEx;
955  entry2.segment->associatedSurface().globalToLocalDirection(exPars->momentum(), locDirEx);
956 
957  const Trk::LocalDirection& locDirSeg = entry2.segment->localDirection();
958 
959  // angular residuals
960  info.localAngleXDiff = phi_diff(locDirEx.angleXZ() - locDirSeg.angleXZ());
961  info.localAngleYDiff = theta_diff(locDirEx.angleYZ() - locDirSeg.angleYZ());
962 
963  AmgSymMatrix(5) localPredCovar;
964  localPredCovar.setIdentity();
965  // only calculate if needed
966  if (info.haveAngleXError || info.haveAngleYError || info.havePosXError || info.havePosYError) {
967  // Predicted angle errors are on global phi and theta. Need to convert to errors on local angles
968  Trk::JacobianPhiThetaLocalAngles globalToLocalPredAnglesJacobian(
969  exMeasPars->parameters()[Trk::phi], exMeasPars->parameters()[Trk::theta],
970  exMeasPars->associatedSurface().transform().rotation().inverse());
971 
972  // make the Jacobian to convert all in one go from global to local
973  // so that the correlations are calculated correctly
974  AmgSymMatrix(5) globalToLocalPredJacobian;
975  globalToLocalPredJacobian.setIdentity();
976  globalToLocalPredJacobian(Trk::locX, Trk::locX) = 1.0;
977  globalToLocalPredJacobian(Trk::locY, Trk::locY) = 1.0;
978  globalToLocalPredJacobian(Trk::phi, Trk::phi) = globalToLocalPredAnglesJacobian(0, 0);
979  globalToLocalPredJacobian(Trk::theta, Trk::theta) = globalToLocalPredAnglesJacobian(1, 1);
980  globalToLocalPredJacobian(Trk::theta, Trk::phi) =
981  globalToLocalPredAnglesJacobian(0, 1); // also fills (Trk::phi,Trk::theta)
982  globalToLocalPredJacobian(Trk::phi, Trk::theta) = globalToLocalPredJacobian(Trk::theta, Trk::phi);
983  globalToLocalPredJacobian(Trk::qOverP, Trk::qOverP) = 1.0;
984  const AmgSymMatrix(5)& globalPredCovar = *exMeasPars->covariance();
985  localPredCovar = globalPredCovar.similarity(globalToLocalPredJacobian);
986  }
987 
988  if (info.haveAngleXError && info.haveAngleYError && info.havePosXError && info.havePosYError) {
989  // Full 4D info available: CSC segments and MDT small-large overlap
990  info.measuredCovariance = measErrors.block<4, 4>(0, 0); // sub(1,4); hope this is ok ....
991  info.predictionCovariance = localPredCovar.block<4, 4>(0, 0); // sub(1,4); hope this is ok ....
992  info.totalCovariance = info.measuredCovariance + info.predictionCovariance;
993 
994  // add alignment errors
999 
1000  // fill difference vector
1001  Amg::VectorX diffVec(4);
1002  diffVec[Trk::locX] = exPars->parameters()[Trk::locX] - entry2.segment->localParameters()[Trk::locX];
1003  diffVec[Trk::locY] = exPars->parameters()[Trk::locY] - entry2.segment->localParameters()[Trk::locY];
1004  diffVec[Trk::phi] = exPars->parameters()[Trk::phi] - entry2.segment->localParameters()[Trk::phi];
1005  diffVec[Trk::theta] = exPars->parameters()[Trk::theta] - entry2.segment->localParameters()[Trk::theta];
1006  info.diffVector = diffVec;
1007 
1008  // finally calculate the match chi-squared
1009  Amg::MatrixX weightMatrix = info.totalCovariance.inverse();
1010  info.matchChiSquared = info.diffVector.transpose() * weightMatrix * info.diffVector;
1011  info.haveMatchChiSquared = true;
1012 
1013  // update separate angles (redunant with covar)
1014  info.posXPredErr2 = localPredCovar(Trk::locX, Trk::locX);
1015  info.posYPredErr2 = localPredCovar(Trk::locY, Trk::locY);
1016  info.angleXPredErr2 = localPredCovar(Trk::phi, Trk::phi);
1017  info.angleYPredErr2 = localPredCovar(Trk::theta, Trk::theta);
1018  // update total errors
1019  info.posXTotalErr2 += info.posXPredErr2;
1020  info.posYTotalErr2 += info.posYPredErr2;
1021  info.angleXTotalErr2 += info.angleXPredErr2;
1022  info.angleYTotalErr2 += info.angleYPredErr2;
1023  info.posXTotalErr2 += m_alignErrorPosX * m_alignErrorPosX;
1024  info.posYTotalErr2 += m_alignErrorPosY * m_alignErrorPosY;
1025  info.angleXTotalErr2 += m_alignErrorAngleX * m_alignErrorAngleX;
1026  info.angleYTotalErr2 += m_alignErrorAngleY * m_alignErrorAngleY;
1027 
1028  } else if (info.haveAngleYError && info.havePosYError) {
1029  // 2D Y info available:
1030  // normal (non-overlap) MDT segments have no X nor phi(angleXZ) measurement, and give error on local angleYZ
1031 
1032  // Y,angleYZ 2x2 sub-set of predicted covariance
1033  AmgSymMatrix(2) predCovar{AmgSymMatrix(2)::Zero()};
1034  predCovar(0, 0) = localPredCovar(Trk::locY, Trk::locY); // Y
1035  predCovar(1, 1) = localPredCovar(Trk::theta, Trk::theta); // angleYZ
1036  predCovar(1, 0) = localPredCovar(Trk::theta, Trk::locY); // also sets (0,1)
1037  predCovar(0, 1) = predCovar(1, 0);
1038  info.predictionCovariance = predCovar;
1039 
1040  // Y,angleYZ 2x2 sub-set of measured covariance
1041  AmgSymMatrix(2) measCovar{AmgSymMatrix(2)::Zero()};
1042  measCovar.setIdentity();
1043  measCovar(0, 0) = measErrors(Trk::locY, Trk::locY);
1044  measCovar(1, 1) = measErrors(Trk::theta, Trk::theta);
1045  measCovar(1, 0) = measErrors(Trk::theta, Trk::locY);
1046  measCovar(0, 1) = measCovar(1, 0);
1047 
1048  info.measuredCovariance = measCovar;
1049  info.totalCovariance = info.predictionCovariance + info.measuredCovariance;
1050  // add alignment errors
1051  info.totalCovariance(0, 0) += m_alignErrorPosY * m_alignErrorPosY;
1052  info.totalCovariance(1, 1) += m_alignErrorAngleY * m_alignErrorAngleY;
1053  if (std::abs(info.totalCovariance.determinant()) <
1054  std::numeric_limits<float>::epsilon()){
1056  return;
1057  }
1058  // now fill the difference vector
1059  Amg::VectorX diffVec(2);
1060  diffVec[0] = info.localPosYDiff;
1061  diffVec[1] = info.localAngleYDiff;
1062  info.diffVector = diffVec;
1063 
1064  // finally calculate the match chi-squared
1065  Amg::MatrixX weightMatrix = info.totalCovariance.inverse();
1066  info.matchChiSquared = info.diffVector.transpose() * weightMatrix * info.diffVector;
1067  info.haveMatchChiSquared = true;
1068 
1069  // fill all available information (redundant with covar)
1070  info.posXPredErr2 = localPredCovar(Trk::locX, Trk::locX);
1071  info.posYPredErr2 = localPredCovar(Trk::locY, Trk::locY);
1072  info.angleXPredErr2 = localPredCovar(Trk::phi, Trk::phi);
1073  info.angleYPredErr2 = localPredCovar(Trk::theta, Trk::theta);
1074  // only use Y/angleY
1075  info.posYTotalErr2 += info.posYPredErr2;
1076  info.angleYTotalErr2 += info.angleYPredErr2;
1077  info.posYTotalErr2 += m_alignErrorPosY * m_alignErrorPosY;
1078  info.angleYTotalErr2 += m_alignErrorAngleY * m_alignErrorAngleY;
1079 
1080  } else {
1082  }
1083 
1084  } else {
1086  //
1087  // Alternative method:
1088  // EM/EO -> EI
1089  // extrapolate (straight line) from EM/EO track and line to IP -> matching region
1090 
1091  } // else !straighLineMatch && !entry1.hasMomemtum()
1092 
1093  }
1094 
1095  bool MooCandidateMatchingTool::sameSide(const MuPatSegment& entry1, const MuPatSegment& entry2, bool sameSideOfPerigee) const {
1096  ATH_MSG_VERBOSE("sameSide: MuPatSegment, MuPatSegment");
1097  return sameSide(entry1.entryPars().momentum().unit(),
1098  entry1.entryPars().position(),
1099  entry2.entryPars().position(), sameSideOfPerigee);
1100  }
1101 
1102  bool MooCandidateMatchingTool::sameSide(const MuPatTrack& entry1, const MuPatSegment& entry2, bool sameSideOfPerigee) const {
1103  ATH_MSG_VERBOSE("sameSide: MuPatTrack, MuPatSegment");
1104  return sameSide(entry1.entryPars().momentum().unit(), entry1.entryPars().position(), entry2.entryPars().position(),
1105  sameSideOfPerigee);
1106  }
1107 
1108  bool MooCandidateMatchingTool::sameSide(const MuPatTrack& entry1, const MuPatTrack& entry2, bool sameSideOfPerigee) const {
1109  ATH_MSG_VERBOSE("sameSide: MuPatTrack, MuPatTrack");
1110  return sameSide(entry1.entryPars().momentum().unit(), entry1.entryPars().position(), entry2.entryPars().position(),
1111  sameSideOfPerigee);
1112  }
1114  bool requireSameSideOfPerigee) const {
1115  // check if segments are on same side of the Perigee in the xy plane
1116  Amg::Vector3D dirxy{dir.x(),dir.y(), 0.};
1117  dirxy = dirxy.unit();
1118  double distFromPerigee1 = pos1.dot(dirxy);
1119  double distFromPerigee2 = pos2.dot(dirxy);
1120  bool sameSideOfPerigee = (distFromPerigee1 * distFromPerigee2 > 0.);
1121  bool same = sameSideOfPerigee;
1122 
1123  // if one segment in each endcap, then consider on different side
1124  bool inOppositeEndcap = false;
1125  constexpr double etaEndcap = 1.1;
1126  double eta1 = pos1.eta();
1127  double eta2 = pos2.eta();
1128  if ((eta1 > +etaEndcap && eta2 < -etaEndcap) || (eta1 < -etaEndcap && eta2 > +etaEndcap)) {
1129  inOppositeEndcap = true;
1130  same = false;
1131  }
1132 
1133  if (msgLvl(MSG::VERBOSE)) {
1134  msg(MSG::DEBUG) << MSG::VERBOSE << "sameSide: Require same side of Perigee: " << requireSameSideOfPerigee;
1135  double sign1 = pos1.y() < 0 ? -1. : 1.;
1136  double sign2 = pos2.y() < 0 ? -1. : 1.;
1137  msg(MSG::DEBUG) << " Direction " << dir << std::fixed << std::setprecision(0) << std::endl
1138  << " pos1: dist " << std::setw(6) << distFromPerigee1 << " r " << std::setw(6) << pos1.perp() * sign1
1139  << " (x,y,z)=(" << std::setw(5) << pos1.x() << "," << std::setw(5) << pos1.y() << "," << std::setw(5)
1140  << pos1.z() << ")" << std::endl
1141  << " pos2: dist " << std::setw(6) << distFromPerigee2 << " r " << std::setw(6) << pos2.perp() * sign2
1142  << " (x,y,z)=(" << std::setw(5) << pos2.x() << "," << std::setw(5) << pos2.y() << "," << std::setw(5)
1143  << pos2.z() << ")" << std::setprecision(6); // back to default
1144 
1145  if (sameSideOfPerigee) {
1146  msg(MSG::DEBUG) << std::endl << " Same side of perigee.";
1147  } else {
1148  msg(MSG::DEBUG) << std::endl << " Other side of perigee.";
1149  }
1150  if (inOppositeEndcap) { msg(MSG::DEBUG) << " In opposite end-cap."; }
1151  }
1152 
1153  // if segments are on the same side of the Perigee, they are also on the same side of Calo, so can return
1154  if (same) {
1155  if (msgLvl(MSG::VERBOSE)) msg(MSG::DEBUG) << " => Accepted" << endmsg;
1156  return true;
1157  }
1158 
1159  // if requiring sameSideOfPerigee (stronger condition), then we are done here.
1160  if (requireSameSideOfPerigee) {
1161  if (msgLvl(MSG::VERBOSE)) msg(MSG::DEBUG) << " => Rejected" << endmsg;
1162  return false;
1163  }
1164  return true;
1165  }
1166 
1167  bool MooCandidateMatchingTool::match(const EventContext& ctx, const MuPatCandidateBase& entry1, const MuPatSegment& entry2, bool useTightCuts) const {
1168  const MuPatSegment* seg = dynamic_cast<const MuPatSegment*>(&entry1);
1169  if (seg) return match(ctx, *seg, entry2, useTightCuts);
1170 
1171  const MuPatTrack* track = dynamic_cast<const MuPatTrack*>(&entry1);
1172  if (track) return match(ctx, *track, entry2, useTightCuts);
1173 
1174  return false;
1175  }
1176 
1177  void MooCandidateMatchingTool::getIdentifierSet(const std::vector<const Trk::MeasurementBase*>& measurements,
1178  std::set<Identifier>& ids) {
1179  // loop over measurements and extract all identifiers
1180  std::vector<const Trk::MeasurementBase*>::const_iterator it = measurements.begin();
1181  std::vector<const Trk::MeasurementBase*>::const_iterator it_end = measurements.end();
1182  for (; it != it_end; ++it) {
1183  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*it);
1184  if (rot) {
1185  ids.insert(rot->identify());
1186  } else {
1187  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*it);
1188  if (crot) {
1189  const std::vector<const MuonClusterOnTrack*>& rots = crot->containedROTs();
1190  std::vector<const MuonClusterOnTrack*>::const_iterator rit = rots.begin();
1191  std::vector<const MuonClusterOnTrack*>::const_iterator rit_end = rots.end();
1192  for (; rit != rit_end; ++rit) ids.insert((*rit)->identify());
1193  }
1194  }
1195  }
1196  }
1197 
1199  // check whether one of the two entries has no phi hits in which case return true
1200  if (entry1.phiHits().empty() || entry2.phiHits().empty()) return true;
1201 
1202  std::set<Identifier> ids1;
1203  getIdentifierSet(entry1.phiHits(), ids1);
1204 
1205  std::set<Identifier> ids2;
1206  getIdentifierSet(entry2.phiHits(), ids2);
1207 
1208  std::vector<Identifier> intersection;
1209  std::set_intersection(ids1.begin(), ids1.end(), ids2.begin(), ids2.end(), std::back_inserter(intersection));
1210 
1211  unsigned int intersectionSize = intersection.size();
1212  // require a full overlap between the two entries or that one of the two is a subset of the other
1213  if (intersectionSize == ids1.size() || intersectionSize == ids2.size()) return true;
1214 
1215  // also accept if there is no overlap
1216  if (intersectionSize == 0) return true;
1217 
1218  return false;
1219  }
1220 
1222  DistanceToPars distToPars(&entry1.entryPars());
1223  double distance = distToPars(entry2.entryPars().position());
1224  if (std::abs(distance) > 5000.) {
1225  ATH_MSG_VERBOSE(" large distance between segments, not using segment " << distance);
1226  return false;
1227  }
1228  return true;
1229  }
1230 
1232  Identifier chid1 = seg1.chid;
1233  Identifier chid2 = seg2.chid;
1234  if (msgLvl(MSG::VERBOSE)) {
1235  msg(MSG::VERBOSE) << "check if chambers are neighbours: " << m_idHelperSvc->toStringChamber(chid1) << " and "
1236  << m_idHelperSvc->toStringChamber(chid2) << ": ";
1237  }
1238  // if in same chamber, then OK
1239  if (chid1 == chid2) {
1240  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "in same chamber" << endmsg;
1241  return true;
1242  }
1243  // check in r
1244  if (seg1.stIndex != seg2.stIndex) {
1245  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "not in same station" << endmsg;
1246  return false;
1247  }
1248 
1249  // check in phi
1250  int secDiff = std::abs(m_idHelperSvc->sector(chid1) - m_idHelperSvc->sector(chid2));
1251  if (secDiff > 1 && secDiff != 15) {
1252  if (msgLvl(MSG::VERBOSE))
1253  msg(MSG::VERBOSE) << "sec1=" << m_idHelperSvc->sector(chid1) << "sec2=" << m_idHelperSvc->sector(chid2)
1254  << " => not in neighbouring phi " << endmsg;
1255  return false;
1256  }
1257 
1258  // check in eta
1259  if (seg1.isEndcap && seg2.isEndcap) {
1260  // both in endcap
1261  // endcap: can compare eta indices
1262  if (std::abs(m_idHelperSvc->stationEta(chid1) - m_idHelperSvc->stationEta(chid2)) > 1) {
1263  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "not in neighbouring eta" << endmsg;
1264  return false;
1265  }
1266  } else if (!seg1.isEndcap && !seg2.isEndcap) {
1267  // both in barrel
1268  const std::string& stationName1 =
1269  m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(chid1));
1270  const std::string& stationName2 =
1271  m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(chid2));
1272  std::string exceptions("MRFG");
1273  if (exceptions.find(stationName1[2]) == std::string::npos && exceptions.find(stationName2[2]) == std::string::npos) {
1274  // the normal case
1275  if (std::abs(m_idHelperSvc->stationEta(chid1) - m_idHelperSvc->stationEta(chid2)) > 1) {
1276  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "not in neighbouring eta " << endmsg;
1277  return false;
1278  }
1279  } else {
1280  // the exceptions: use geometrical information
1281  const std::set<const MuonGM::MuonReadoutElement*> roEls1 = m_candidateTool->readoutElements(seg1);
1282  const std::set<const MuonGM::MuonReadoutElement*> roEls2 = m_candidateTool->readoutElements(seg2);
1283  for (const MuonGM::MuonReadoutElement* read_ele1 : roEls1) {
1284  for (const MuonGM::MuonReadoutElement* read_ele2 : roEls2) {
1285  double distZ = std::abs(read_ele1->center().z() - read_ele2->center().z());
1286  // subtract sizes
1287  distZ -= 0.5 * (read_ele1->getZsize() + read_ele2->getZsize());
1288  if (msgLvl(MSG::VERBOSE)) {
1289  msg(MSG::VERBOSE) << std::endl
1290  << read_ele1->getStationType() << ": z=" << read_ele1->center().z() << "+-"
1291  << 0.5 * read_ele1->getZsize() << " " << read_ele2->getStationType()
1292  << ": z=" << read_ele2->center().z() << "+-" << 0.5 * read_ele2->getZsize() << " "
1293  << "distZ=" << distZ;
1294  }
1295  // allow some distance
1296  if (distZ > 100.0) {
1297  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << " z-position too far apart" << endmsg;
1298  return false;
1299  }
1300  }
1301  }
1302  }
1303  } else {
1304  // don't mix barrel/endcap
1305  ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<< "endcap/barrel mix");
1306  return false;
1307  }
1308 
1309  ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<< " Yes!");
1310  return true;
1311  }
1312 } // namespace Muon
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
Muon::TrackSegmentMatchResult::PassedPosAngleCuts
@ PassedPosAngleCuts
Definition: MuonTrackSegmentMatchResult.h:54
Muon::MooCandidateMatchingTool::sameSide
bool sameSide(const MuPatSegment &entry1, const MuPatSegment &entry2, bool requireSameSideOfPerigee) const
check whether two segments are on the same side of the point of closest approach to the perigee of th...
Definition: MooCandidateMatchingTool.cxx:1095
Muon::MooCandidateMatchingTool::m_sameSideOfPerigeeTrk
std::atomic_ulong m_sameSideOfPerigeeTrk
Definition: MooCandidateMatchingTool.h:201
Muon::TrackSegmentMatchResult::NumberOfReasons
@ NumberOfReasons
Definition: MuonTrackSegmentMatchResult.h:72
Muon::MooCandidateMatchingTool::getMatchingCuts
TrackSegmentMatchCuts getMatchingCuts(const MuPatTrack &entry1, const MuPatSegment &entry2, bool useTightCuts) const
Definition: MooCandidateMatchingTool.cxx:328
Muon::MooCandidateMatchingTool::m_alignErrorPosY
double m_alignErrorPosY
Definition: MooCandidateMatchingTool.h:164
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
Amg::VectorX
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
Definition: EventPrimitives.h:30
Muon::TrackSegmentMatchResult::SegmentMatching
@ SegmentMatching
Definition: MuonTrackSegmentMatchResult.h:56
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
Muon::MuPatCandidateBase::phiHits
const MeasVec & phiHits() const
return all phi hits on the entry
Definition: MuPatCandidateBase.cxx:57
Muon::MooCandidateMatchingTool::checkSegmentDistance
bool checkSegmentDistance(const MuPatSegment &entry1, const MuPatSegment &entry2) const
evaluate distance between two segments, if too large return false (cut at 3000.).
Definition: MooCandidateMatchingTool.cxx:1221
Muon::TrackSegmentMatchResult::PassedAllCuts
@ PassedAllCuts
Definition: MuonTrackSegmentMatchResult.h:52
ParticleGun_SamplingFraction.eta2
eta2
Definition: ParticleGun_SamplingFraction.py:96
Muon::TrackSegmentMatchResult::NoClosestPars
@ NoClosestPars
Definition: MuonTrackSegmentMatchResult.h:59
Muon::TrackSegmentMatchResult::ExtrapolNoErrors
@ ExtrapolNoErrors
Definition: MuonTrackSegmentMatchResult.h:65
Muon::MuPatCandidateBase
track candidate entry object.
Definition: MuPatCandidateBase.h:46
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
Trk::locX
@ locX
Definition: ParamDefs.h:37
Muon::MooCandidateMatchingTool::checkPhiHitConsistency
static bool checkPhiHitConsistency(const MuPatCandidateBase &entry1, const MuPatCandidateBase &entry2)
evaluate overlap between phi hits of two entries.
Definition: MooCandidateMatchingTool.cxx:1198
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:38
Muon::MooCandidateMatchingTool::m_trackSegmentPreMatchingStrategy
Gaudi::Property< int > m_trackSegmentPreMatchingStrategy
Definition: MooCandidateMatchingTool.h:188
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
Muon::MooCandidateMatchingTool::MooTrackSegmentMatchResult
Class with matching return information.
Definition: MooCandidateMatchingTool.h:51
Muon::MuPatTrack::segmentNames
std::string segmentNames() const
string containing the names of the segments on the candidate
Definition: MuPatTrack.cxx:274
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Muon::MuonStationIndex::StIndex::EM
@ EM
Trk::Track::trackStateOnSurfaces
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
Muon::MooCandidateMatchingTool::m_matchChiSquaredCutTight
double m_matchChiSquaredCutTight
Definition: MooCandidateMatchingTool.h:168
Muon::MuPatCandidateBase::chambers
const std::set< MuonStationIndex::ChIndex > & chambers() const
returns set with contained chamberIndices
Definition: MuPatCandidateBase.cxx:31
EventPrimitivesHelpers.h
Muon::MooCandidateMatchingTool::m_matchAngYPullCut
double m_matchAngYPullCut
Definition: MooCandidateMatchingTool.h:159
Muon::MooCandidateMatchingTool::areInNeighbouringChambers
bool areInNeighbouringChambers(const MuPatSegment &seg1, const MuPatSegment &seg2) const
return whether the 2 segments are in neighbouring chambers
Definition: MooCandidateMatchingTool.cxx:1231
skel.it
it
Definition: skel.GENtoEVGEN.py:407
Muon::MooCandidateMatchingTool::m_otherSideOfPerigee
std::atomic_ulong m_otherSideOfPerigee
Definition: MooCandidateMatchingTool.h:200
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:200
CompetingMuonClustersOnTrack.h
Muon::TrackSegmentMatchResult::AngXPullCut
@ AngXPullCut
Definition: MuonTrackSegmentMatchResult.h:40
M_PI
#define M_PI
Definition: ActiveFraction.h:11
Muon::TrackSegmentMatchResult::PosYCut
@ PosYCut
Definition: MuonTrackSegmentMatchResult.h:35
Muon::MooCandidateMatchingTool::m_matchPosYCut
double m_matchPosYCut
Definition: MooCandidateMatchingTool.h:161
Muon::TrackSegmentMatchResult::FailedCuts
@ FailedCuts
Definition: MuonTrackSegmentMatchResult.h:55
mc.diff
diff
Definition: mc.SFGenPy8_MuMu_DD.py:14
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
Muon::MooCandidateMatchingTool::m_edmHelperSvc
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
Definition: MooCandidateMatchingTool.h:171
Muon::MooCandidateMatchingTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MooCandidateMatchingTool.h:170
MuPatCandidateBase.h
xAOD::eta1
setEt setPhi setE277 setWeta2 eta1
Definition: TrigEMCluster_v1.cxx:41
Muon::MooCandidateMatchingTool::m_segmentMatchingTool
ToolHandle< IMuonSegmentMatchingTool > m_segmentMatchingTool
Definition: MooCandidateMatchingTool.h:178
Muon::TrackSegmentMatchResult::NoCutsApplied
@ NoCutsApplied
Definition: MuonTrackSegmentMatchResult.h:51
Muon::MuPatSegment::name
std::string name
Definition: MuPatSegment.h:58
Trk::RIO_OnTrack
Definition: RIO_OnTrack.h:70
Muon::MooCandidateMatchingTool::m_matchPosXCut
double m_matchPosXCut
Definition: MooCandidateMatchingTool.h:160
Muon::TrackSegmentMatchResult::PassedMatchChiSquaredCut
@ PassedMatchChiSquaredCut
Definition: MuonTrackSegmentMatchResult.h:53
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon::CompetingMuonClustersOnTrack
Definition: CompetingMuonClustersOnTrack.h:54
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
MagField::AtlasFieldCache::toroidOn
bool toroidOn() const
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
Muon::MooCandidateMatchingTool::initialize
virtual StatusCode initialize() override
initialize method, method taken from bass-class AlgTool
Definition: MooCandidateMatchingTool.cxx:99
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
Muon::MuPatSegment::isMdt
bool isMdt
true for MDT, false for CSC
Definition: MuPatSegment.h:62
Muon::TrackSegmentMatchResult::NoSegmentPointer
@ NoSegmentPointer
Definition: MuonTrackSegmentMatchResult.h:57
python.TrigEgammaFastCaloHypoTool.same
def same(val, tool)
Definition: TrigEgammaFastCaloHypoTool.py:10
x
#define x
Muon::MooCandidateMatchingTool::calculateTrackSegmentMatchResult
void calculateTrackSegmentMatchResult(const EventContext &ctx, const MuPatTrack &entry1, const MuPatSegment &entry2, MooTrackSegmentMatchResult &info) const
calculate the info needed for the matching decision
Definition: MooCandidateMatchingTool.cxx:683
intersection
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Definition: compareFlatTrees.cxx:25
Identifier::is_valid
bool is_valid() const
Check if id is in a valid state.
AmgSymMatrix
#define AmgSymMatrix(dim)
Definition: EventPrimitives.h:50
MuPatSegment.h
Muon::TrackSegmentMatchCuts
Definition: MuonTrackSegmentMatchResult.h:174
Muon::MuonStationIndex::ChIndex::CSL
@ CSL
Muon::MooCandidateMatchingTool::applyTrackSegmentCuts
bool applyTrackSegmentCuts(const EventContext &ctx, MooTrackSegmentMatchResult &info, const TrackSegmentMatchCuts &cuts) const
Definition: MooCandidateMatchingTool.cxx:383
Muon::MooCandidateMatchingTool::m_alignErrorAngleX
double m_alignErrorAngleX
Definition: MooCandidateMatchingTool.h:165
MuonGM::MuonReadoutElement
Base class for the XxxReadoutElement, with Xxx = Mdt, Rpc, Tgc, Csc.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonReadoutElement.h:40
Trk::LocalDirection::angleYZ
double angleYZ() const
access method for angle of local YZ projection
Definition: LocalDirection.h:106
Muon::MooCandidateMatchingTool::m_printer
PublicToolHandle< MuonEDMPrinterTool > m_printer
Definition: MooCandidateMatchingTool.h:174
Muon::MooCandidateMatchingTool::m_matchChiSquaredCut
double m_matchChiSquaredCut
Definition: MooCandidateMatchingTool.h:167
Muon::MuPatSegment::chid
Identifier chid
Definition: MuPatSegment.h:57
Trk::PseudoMeasurementOnTrack
Class to handle pseudo-measurements in fitters and on track objects.
Definition: PseudoMeasurementOnTrack.h:44
Muon::TrackSegmentMatchResult::NoClosestSegment
@ NoClosestSegment
Definition: MuonTrackSegmentMatchResult.h:61
Muon::MuPatTrack::hasMomentum
bool hasMomentum() const
returns whether canditate has a momentum measurement
Definition: MuPatTrack.cxx:186
Muon::MuPatSegment::stIndex
StIdx stIndex
Definition: MuPatSegment.h:60
TileDCSDataPlotter.tit
tit
Definition: TileDCSDataPlotter.py:892
Muon::MooCandidateMatchingTool::~MooCandidateMatchingTool
virtual ~MooCandidateMatchingTool()
destructor
Muon::MooCandidateMatchingTool::m_doTrackSegmentMatching
Gaudi::Property< bool > m_doTrackSegmentMatching
Definition: MooCandidateMatchingTool.h:190
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
Muon::MooCandidateMatchingTool::m_minimumSideMatchRadius
double m_minimumSideMatchRadius
Definition: MooCandidateMatchingTool.h:155
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Muon::MuPatCandidateBase::chamberIds
const std::set< Identifier > & chamberIds() const
returns set with contained chamber ids
Definition: MuPatCandidateBase.cxx:33
Muon::MooCandidateMatchingTool::m_goodSegmentMatchesTight
std::atomic_ulong m_goodSegmentMatchesTight
Definition: MooCandidateMatchingTool.h:194
EventPrimitivesToStringConverter.h
Muon::MooCandidateMatchingTool::MooCandidateMatchingTool
MooCandidateMatchingTool(const std::string &, const std::string &, const IInterface *)
default AlgTool constructor
Definition: MooCandidateMatchingTool.cxx:61
Muon::MuPatSegment::entryPars
const Trk::TrackParameters & entryPars() const
returns first track parameters
Definition: MuPatSegment.h:84
Muon::MooCandidateMatchingTool::m_otherSideOfPerigeeTrk
std::atomic_ulong m_otherSideOfPerigeeTrk
Definition: MooCandidateMatchingTool.h:202
lumiFormat.i
int i
Definition: lumiFormat.py:85
Muon::MooCandidateMatchingTool::m_matchPosPullCut
double m_matchPosPullCut
Definition: MooCandidateMatchingTool.h:162
Muon::TrackSegmentMatchResult::AngYCut
@ AngYCut
Definition: MuonTrackSegmentMatchResult.h:39
Muon::TrackSegmentMatchResult::Unknown
@ Unknown
Definition: MuonTrackSegmentMatchResult.h:50
Muon::MooCandidateMatchingTool::m_caloMatchZ
double m_caloMatchZ
Z position of calo end-cap disks.
Definition: MooCandidateMatchingTool.h:208
beamspotman.n
n
Definition: beamspotman.py:729
Muon::MuPatSegment::isEndcap
bool isEndcap
Definition: MuPatSegment.h:61
Trk::theta
@ theta
Definition: ParamDefs.h:66
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Muon::MuonStationIndex::chName
const std::string & chName(ChIndex index)
convert ChIndex into a string
Definition: MuonStationIndex.cxx:119
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Definition: AthCommonDataStore.h:145
Muon::TrackSegmentMatchResult::AngYPullCut
@ AngYPullCut
Definition: MuonTrackSegmentMatchResult.h:41
Muon::MuonSegment::localDirection
const Trk::LocalDirection & localDirection() const
local direction
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:169
covarianceTool.title
title
Definition: covarianceTool.py:542
MuPatTrack.h
Muon::MuPatSegment::segment
const MuonSegment * segment
Definition: MuPatSegment.h:53
plotBeamSpotVert.cuts
string cuts
Definition: plotBeamSpotVert.py:92
PseudoMeasurementOnTrack.h
Muon::MooCandidateMatchingTool::m_reasonsForMatchNotOk
std::atomic_ulong m_reasonsForMatchNotOk[TrackSegmentMatchResult::NumberOfReasons]
Definition: MooCandidateMatchingTool.h:206
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:304
Muon::MuonStationIndex::ChIndex::CSS
@ CSS
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::PlaneSurface::globalToLocalDirection
void globalToLocalDirection(const Amg::Vector3D &glodir, Trk::LocalDirection &locdir) const
This method transforms the global direction to a local direction wrt the plane.
Definition: PlaneSurface.cxx:256
Muon::MooCandidateMatchingTool::m_matchAngXCut
double m_matchAngXCut
Definition: MooCandidateMatchingTool.h:156
Muon::MooCandidateMatchingTool::m_goodSegmentTrackMatchesTight
std::atomic_ulong m_goodSegmentTrackMatchesTight
Definition: MooCandidateMatchingTool.h:198
Trk::ParametersBase
Definition: ParametersBase.h:55
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
Trk::muon
@ muon
Definition: ParticleHypothesis.h:31
DataVector< const Trk::TrackStateOnSurface >
ParticleHypothesis.h
Trk::LocalDirection
represents the three-dimensional global direction with respect to a planar surface frame.
Definition: LocalDirection.h:81
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
Muon::MooCandidateMatchingTool::m_sameSideOfPerigee
std::atomic_ulong m_sameSideOfPerigee
Definition: MooCandidateMatchingTool.h:199
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
Muon::MooCandidateMatchingTool::finalize
virtual StatusCode finalize() override
finialize method, method taken from bass-class AlgTool
Definition: MooCandidateMatchingTool.cxx:112
beamspotman.dir
string dir
Definition: beamspotman.py:621
Muon::MuonStationIndex::StIndex
StIndex
enum to classify the different station layers in the muon spectrometer
Definition: MuonStationIndex.h:23
Muon::TrackSegmentMatchResult::MatchChiSquaredCut
@ MatchChiSquaredCut
Definition: MuonTrackSegmentMatchResult.h:42
Trk::MeasurementBase
Definition: MeasurementBase.h:58
Muon::MooCandidateMatchingTool::getIdentifierSet
static void getIdentifierSet(const std::vector< const Trk::MeasurementBase * > &measurements, std::set< Identifier > &ids)
extract Idenfitiers from a vector of measurements and copy them into a set
Definition: MooCandidateMatchingTool.cxx:1177
Muon::MooCandidateMatchingTool::MooTrackSegmentMatchResult::MooTrackSegmentMatchResult
MooTrackSegmentMatchResult()
Definition: MooCandidateMatchingTool.cxx:53
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
JacobianPhiThetaLocalAngles.h
python.subdetectors.mmg.ids
ids
Definition: mmg.py:8
Muon::MooCandidateMatchingTool::m_segmentTrackMatchesTight
std::atomic_ulong m_segmentTrackMatchesTight
Definition: MooCandidateMatchingTool.h:204
Muon::TrackSegmentMatchResult::PosXPullCut
@ PosXPullCut
Definition: MuonTrackSegmentMatchResult.h:36
Muon::MuPatCandidateBase::hasEndcap
bool hasEndcap() const
returns whether the entry contains endcap hits
Definition: MuPatCandidateBase.cxx:71
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Muon::TrackSegmentMatchResult::StereoAngleWithoutPhi
@ StereoAngleWithoutPhi
Definition: MuonTrackSegmentMatchResult.h:58
Muon::TrackSegmentMatchResult::SegmentMatch
@ SegmentMatch
Definition: MuonTrackSegmentMatchResult.h:62
Muon::CompetingMuonClustersOnTrack::containedROTs
const std::vector< const MuonClusterOnTrack * > & containedROTs() const
returns the vector of SCT_ClusterOnTrack objects .
Definition: CompetingMuonClustersOnTrack.h:184
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Muon::MooCandidateMatchingTool::m_goodSegmentMatches
std::atomic_ulong m_goodSegmentMatches
matching counters
Definition: MooCandidateMatchingTool.h:193
Muon::TrackSegmentMatchResult::NoMeasErrors
@ NoMeasErrors
Definition: MuonTrackSegmentMatchResult.h:66
Muon::MuPatSegment
segment candidate object.
Definition: MuPatSegment.h:43
Trk::MeasurementBase::localParameters
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
Definition: MeasurementBase.h:132
Muon::TrackSegmentMatchResult::ExtrapolFailed
@ ExtrapolFailed
Definition: MuonTrackSegmentMatchResult.h:64
Muon::MuPatTrack::entryPars
const Trk::TrackParameters & entryPars() const
returns first track parameters
Definition: MuPatTrack.h:177
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
Muon::MooCandidateMatchingTool::m_segmentMatchesTight
std::atomic_ulong m_segmentMatchesTight
Definition: MooCandidateMatchingTool.h:196
Muon::MooCandidateMatchingTool::m_segmentMatches
std::atomic_ulong m_segmentMatches
Definition: MooCandidateMatchingTool.h:195
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Muon::MooCandidateMatchingTool::m_atlasExtrapolator
ToolHandle< Trk::IExtrapolator > m_atlasExtrapolator
Definition: MooCandidateMatchingTool.h:176
Muon::MuPatCandidateBase::containsChamber
bool containsChamber(MuonStationIndex::ChIndex chIndex) const
returns whether the ChamberIndex is already contained in candidate
Definition: MuPatCandidateBase.cxx:75
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
Muon::MuPatTrack::track
Trk::Track & track() const
access to track
Definition: MuPatTrack.h:175
Base_Fragment.width
width
Definition: Sherpa_i/share/common/Base_Fragment.py:59
Trk::JacobianPhiThetaLocalAngles
Definition: JacobianPhiThetaLocalAngles.h:32
trigbs_pickEvents.cnt
cnt
Definition: trigbs_pickEvents.py:71
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.Constants.INFO
int INFO
Definition: Control/AthenaCommon/python/Constants.py:15
Muon::MooCandidateMatchingTool::MooTrackSegmentMatchResult::clear
virtual void clear()
Definition: MooCandidateMatchingTool.cxx:55
GeoPrimitivesHelpers.h
Muon::MuPatTrack
track candidate object.
Definition: MuPatTrack.h:37
Muon::MooCandidateMatchingTool::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: MooCandidateMatchingTool.h:185
MooCandidateMatchingTool.h
Trk::RIO_OnTrack::identify
Identifier identify() const
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:152
DEBUG
#define DEBUG
Definition: page_access.h:11
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
Muon::MooCandidateMatchingTool::m_matchAngYCut
double m_matchAngYCut
Definition: MooCandidateMatchingTool.h:157
Muon::TrackSegmentMatchResult::PosXCut
@ PosXCut
Definition: MuonTrackSegmentMatchResult.h:34
Muon::MooCandidateMatchingTool::m_goodSegmentTrackMatches
std::atomic_ulong m_goodSegmentTrackMatches
Definition: MooCandidateMatchingTool.h:197
Muon::TrackSegmentMatchResult::NoMomentumWithMagField
@ NoMomentumWithMagField
Definition: MuonTrackSegmentMatchResult.h:63
Muon::MooCandidateMatchingTool::m_alignErrorAngleY
double m_alignErrorAngleY
Definition: MooCandidateMatchingTool.h:166
Muon::MooCandidateMatchingTool::m_candidateTool
ToolHandle< MuPatCandidateTool > m_candidateTool
Definition: MooCandidateMatchingTool.h:182
Muon::MooCandidateMatchingTool::match
bool match(const EventContext &ctx, const MuPatSegment &entry1, const MuPatSegment &entry2, bool useTightCuts) const
match two segment entries
Definition: MooCandidateMatchingTool.cxx:171
Muon::MuonStationIndex::StIndex::EO
@ EO
Muon::TrackSegmentMatchResult::PosYPullCut
@ PosYPullCut
Definition: MuonTrackSegmentMatchResult.h:37
MuonSegment.h
Muon::MooCandidateMatchingTool::m_segmentTrackMatches
std::atomic_ulong m_segmentTrackMatches
Definition: MooCandidateMatchingTool.h:203
Muon::MooCandidateMatchingTool::m_segmentMatchingToolTight
ToolHandle< IMuonSegmentMatchingTool > m_segmentMatchingToolTight
Definition: MooCandidateMatchingTool.h:180
Trk::phi
@ phi
Definition: ParamDefs.h:75
jobOptions.prec
prec
Definition: jobOptions.Superchic_UPC_yyMuMu.py:20
LocalDirection.h
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
Muon::MuonSegment
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:45
AthAlgTool
Definition: AthAlgTool.h:26
Trk::LocalDirection::angleXZ
double angleXZ() const
access method for angle of local XZ projection
Definition: LocalDirection.h:103
Muon::MooCandidateMatchingTool::m_matchAngXPullCut
double m_matchAngXPullCut
Definition: MooCandidateMatchingTool.h:158
Muon::MooCandidateMatchingTool::m_reasonsForMatchOk
std::atomic_ulong m_reasonsForMatchOk[TrackSegmentMatchResult::NumberOfReasons]
Definition: MooCandidateMatchingTool.h:205
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:198
Muon::TrackSegmentMatchResult::Reason
Reason
Definition: MuonTrackSegmentMatchResult.h:49
set_intersection
Set * set_intersection(Set *set1, Set *set2)
Perform an intersection of two sets.
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Muon::TrackSegmentMatchResult::AngXCut
@ AngXCut
Definition: MuonTrackSegmentMatchResult.h:38
Muon::MuPatTrack::segments
const std::vector< MuPatSegment * > & segments() const
access to segments
Definition: MuPatTrack.h:167
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
Muon::MuPatCandidateBase::stations
const std::set< MuonStationIndex::StIndex > & stations() const
returns set with contained stationIndices
Definition: MuPatCandidateBase.cxx:29
Muon::DistanceToPars
Definition: SortMeasurementsByPosition.h:20
Muon::MooCandidateMatchingTool::m_requireSameSide
bool m_requireSameSide
require entries to be on the same side of the Perigee or Calorimeter
Definition: MooCandidateMatchingTool.h:211
Muon::TrackSegmentMatchResult::reasonString
std::string reasonString() const
Definition: MuonTrackSegmentMatchResult.cxx:150
Muon::TrackSegmentMatchResult::clear
virtual void clear()
Definition: MuonTrackSegmentMatchResult.cxx:34
Muon::MuonSegment::associatedSurface
virtual const Trk::PlaneSurface & associatedSurface() const override final
returns the surface for the local to global transformation
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:175
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
NSWL1::PadTriggerAdapter::segment
Muon::NSW_PadTriggerSegment segment(const NSWL1::PadTrigger &data)
Definition: PadTriggerAdapter.cxx:5
Muon::MooCandidateMatchingTool::m_alignErrorPosX
double m_alignErrorPosX
Definition: MooCandidateMatchingTool.h:163
Identifier
Definition: IdentifierFieldParser.cxx:14