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;
348  // CSC
349  cuts.cutOnPosX = true;
350  cuts.cutOnPosY = true;
351  cuts.cutOnPosXPull = true;
352  cuts.cutOnPosYPull = true;
353  cuts.cutOnAngleX = true;
354  cuts.cutOnAngleY = true;
355  cuts.cutOnAngleXPull = true;
356  cuts.cutOnAngleYPull = true;
357  } else { // ! containsChamber(CSS || CSL)
358  // MDT
359  cuts.cutOnPosX = false;
360  cuts.cutOnPosY = true;
361  cuts.cutOnPosXPull = false;
362  cuts.cutOnPosYPull = true;
363  cuts.cutOnAngleX = false;
364  cuts.cutOnAngleY = true;
365  cuts.cutOnAngleXPull = false;
366  cuts.cutOnAngleYPull = true;
367  }
368 
369  if (cuts.posXCut == 0.0) cuts.cutOnPosX = false;
370  if (cuts.posYCut == 0.0) cuts.cutOnPosY = false;
371  if (cuts.angleXCut == 0.0) cuts.cutOnAngleX = false;
372  if (cuts.angleYCut == 0.0) cuts.cutOnAngleY = false;
373  if (cuts.posXPullCut == 0.0) cuts.cutOnPosXPull = false;
374  if (cuts.posYPullCut == 0.0) cuts.cutOnPosYPull = false;
375  if (cuts.angleXPullCut == 0.0) cuts.cutOnAngleXPull = false;
376  if (cuts.angleYPullCut == 0.0) cuts.cutOnAngleYPull = false;
377  if (cuts.matchChiSquaredCut == 0.0) cuts.cutOnMatchChiSquared = false;
378 
379  return cuts;
380  }
381 
383  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << "track segment match:";
384 
386  // for tracks that have no momentum, but need a curved match
387  // fall-back to segment matching with the closest segment
388  MuPatSegment* closestSegment = nullptr;
389  double closestSegmentDist = 1E9;
390  std::vector<MuPatSegment*>::const_iterator itS = info.MCTBTrack->segments().begin(), itS_end = info.MCTBTrack->segments().end();
391  for (; itS != itS_end; ++itS) {
392  // calculate distance along the direction of the segment on the track
393  double dist =
394  (info.MCTBSegment->entryPars().position() - (*itS)->entryPars().position()).dot((*itS)->entryPars().momentum().unit());
395  // store closest distance
396  if (std::abs(dist) < std::abs(closestSegmentDist)) {
397  closestSegmentDist = dist;
398  closestSegment = *itS;
399  }
400  }
401 
402  if (!closestSegment) {
404  info.matchOK = true;
405  } else { // closestSegment
406  // call segment matching tool
407  if (cuts.useTightCuts) {
408  info.matchOK = m_segmentMatchingToolTight->match(ctx, *(closestSegment->segment), *(info.segment));
409  } else {
410  info.matchOK = m_segmentMatchingTool->match(ctx, *(closestSegment->segment), *(info.segment));
411  }
412  if (msgLvl(MSG::DEBUG)) {
413  if (info.matchOK) {
414  msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed";
415  } else {
416  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed";
417  }
418  msg(MSG::DEBUG) << " segment match between segment-on-track "
419  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.trackChamberId)) << " and segment "
420  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.segmentChamberId)) << endmsg;
421  }
423  info.trackChamberId = closestSegment->chid;
424  } // else closestSegment
425 
426  return info.matchOK;
427  } // if ( info.reason == TrackSegmentMatchResult::NoMomentumWithMagField )
428 
429  if (msgLvl(MSG::VERBOSE)) {
430  msg(MSG::DEBUG) << MSG::VERBOSE << std::fixed;
431  if (info.havePosXError) {
432  double diff = info.localPosXDiff;
433  double totErr = std::sqrt(info.posXTotalErr2);
434  double pull = totErr != 0.0 ? diff / totErr : 0.0;
435  msg(MSG::DEBUG) << std::endl
436  << std::setprecision(3) << "deltaPosX =" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
437  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull << std::setprecision(3)
438  << " (align=" << m_alignErrorPosX << " meas=" << std::sqrt(info.posXMeasErr2)
439  << " pred=" << std::sqrt(info.posXPredErr2) << ")";
440  }
441  if (info.havePosYError) {
442  double diff = info.localPosYDiff;
443  double totErr = std::sqrt(info.posYTotalErr2);
444  double pull = totErr != 0.0 ? diff / totErr : 0.0;
445  msg(MSG::DEBUG) << std::endl
446  << std::setprecision(3) << "deltaPosY =" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
447  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull
448  << " (align=" << m_alignErrorPosY << " meas=" << std::sqrt(info.posYMeasErr2)
449  << " pred=" << std::sqrt(info.posYPredErr2) << ")";
450  }
451  if (info.haveAngleXError) {
452  double diff = info.localAngleXDiff;
453  double totErr = std::sqrt(info.angleXTotalErr2);
454  double pull = totErr != 0.0 ? diff / totErr : 0.0;
455  msg(MSG::DEBUG) << std::endl
456  << std::setprecision(5) << "deltaAngleX=" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
457  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull << std::setprecision(5)
458  << " (align=" << m_alignErrorAngleX << " meas=" << std::sqrt(info.angleXMeasErr2)
459  << " pred=" << std::sqrt(info.angleXPredErr2) << ")";
460  }
461  if (info.haveAngleYError) {
462  double diff = info.localAngleYDiff;
463  double totErr = std::sqrt(info.angleYTotalErr2);
464  double pull = totErr != 0.0 ? diff / totErr : 0.0;
465  msg(MSG::DEBUG) << std::endl
466  << std::setprecision(5) << "deltaAngleY=" << std::setw(8) << diff << " +- " << std::left << std::setw(8)
467  << totErr << std::right << std::setprecision(2) << " pull=" << std::setw(5) << pull << std::setprecision(5)
468  << " (align=" << m_alignErrorAngleY << " meas=" << std::sqrt(info.angleYMeasErr2)
469  << " pred=" << std::sqrt(info.angleYPredErr2) << ")";
470  }
471 
472  msg(MSG::DEBUG) << std::endl << std::setprecision(5) << "Difference vector:" << info.diffVector;
473  msg(MSG::DEBUG) << printCovCorr(info.measuredCovariance, "Measured") << printCovCorr(info.predictionCovariance, "Predicted")
474  << printCovCorr(info.totalCovariance, "Total") << "Match chi-squared: " << info.matchChiSquared
475  << " sqrt=" << std::sqrt(info.matchChiSquared);
476 
477  // finish on new line
478  if (info.havePosXError || info.havePosYError || info.haveAngleXError || info.haveAngleYError) { msg(MSG::DEBUG) << std::endl; }
479  }
480 
481  //
482  // Start checking all cuts
483  //
484  info.resetCuts();
485  //
486  // apply cut on positions
487  //
488  double scaledPosXErr2 = cuts.posXPullCut * cuts.posXPullCut * info.posXTotalErr2;
489 
490  // cut on absolute X position
491  if (cuts.cutOnPosX && info.havePosX) {
492  double posXCut2 = cuts.posXCut * cuts.posXCut + scaledPosXErr2;
493  if (info.localPosXDiff * info.localPosXDiff > posXCut2) {
494  if (msgLvl(MSG::DEBUG)) {
495  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
496  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.segmentChamberId))
497  << " X position cut: " << info.localPosXDiff << " > " << std::sqrt(posXCut2) << endmsg;
498  }
500  } else {
502  }
503  }
504 
505  double scaledPosYErr2 = cuts.posYPullCut * cuts.posYPullCut * info.posYTotalErr2;
506 
507  // cut on absolute Y position
508  if (cuts.cutOnPosY && info.havePosY) {
509  double posYCut2 = cuts.posYCut * cuts.posYCut + scaledPosYErr2;
510  if (info.localPosYDiff * info.localPosYDiff > posYCut2) {
511  if (msgLvl(MSG::DEBUG)) {
512  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
513  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
514  << " Y position cut: " << info.localPosYDiff << " > " << std::sqrt(posYCut2) << endmsg;
515  }
517  } else {
519  }
520  }
521 
522  // cut on X position pull
523  if (cuts.cutOnPosXPull && info.havePosX && info.posXTotalErr2 > 0.0) {
524  if (info.localPosXDiff * info.localPosXDiff > scaledPosXErr2) {
525  if (msgLvl(MSG::DEBUG)) {
526  double pull = info.localPosXDiff / std::sqrt(info.posXTotalErr2);
527  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
528  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
529  << " X position pull cut: |" << pull << "| > " << cuts.posXPullCut << endmsg;
530  }
532  } else {
534  }
535  }
536 
537  // cut on Y position pull
538  if (cuts.cutOnPosYPull && info.havePosY && info.posYTotalErr2 > 0.0) {
539  if (info.localPosYDiff * info.localPosYDiff > scaledPosYErr2) {
540  if (msgLvl(MSG::DEBUG)) {
541  double pull = info.localPosYDiff / std::sqrt(info.posYTotalErr2);
542  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
543  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
544  << " Y position pull cut: |" << pull << "| > " << cuts.posYPullCut << endmsg;
545  }
547  } else {
549  }
550  }
551 
552  //
553  // apply cut on angles
554  //
555  double scaledAngleXErr2 = cuts.angleXPullCut * cuts.angleXPullCut * info.angleXTotalErr2;
556 
557  // cut on absolute X angle
558  if (cuts.cutOnAngleX && info.haveAngleX) {
559  double angleXCut2 = cuts.angleXCut * cuts.angleXCut + scaledAngleXErr2;
560  if (info.localAngleXDiff * info.localAngleXDiff > angleXCut2) {
561  if (msgLvl(MSG::DEBUG)) {
562  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
563  << MuonStationIndex::chName(m_idHelperSvc->chamberIndex(info.segmentChamberId))
564  << " X angle cut: " << info.localAngleXDiff << " > " << std::sqrt(angleXCut2) << endmsg;
565  }
567  } else {
569  }
570  }
571 
572  double scaledAngleYErr2 = cuts.angleYPullCut * cuts.angleYPullCut * info.angleYTotalErr2;
573 
574  // cut on absolute Y angle
575  if (cuts.cutOnAngleY && info.haveAngleY) {
576  double angleYCut2 = cuts.angleYCut * cuts.angleYCut + scaledAngleYErr2;
577  if (info.localAngleYDiff * info.localAngleYDiff > angleYCut2) {
578  if (msgLvl(MSG::DEBUG)) {
579  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
580  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
581  << " Y angle cut: " << info.localAngleYDiff << " > " << std::sqrt(angleYCut2) << endmsg;
582  }
584  } else {
586  }
587  }
588 
589  // cut on X angle pull
590  if (cuts.cutOnAngleXPull && info.haveAngleX && info.angleXTotalErr2 > 0.0) {
591  if (info.localAngleXDiff * info.localAngleXDiff > scaledAngleXErr2) {
592  if (msgLvl(MSG::DEBUG)) {
593  double pull = info.localAngleXDiff / std::sqrt(info.angleXTotalErr2);
594  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
595  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
596  << " X angle pull cut: |" << pull << "| > " << cuts.angleXPullCut << endmsg;
597  }
599  } else {
601  }
602  }
603 
604  if (cuts.cutOnAngleYPull && info.haveAngleY && info.angleYTotalErr2 > 0.0) {
605  // cut on Y angle pull
606  if (info.localAngleYDiff * info.localAngleYDiff > scaledAngleYErr2) {
607  if (msgLvl(MSG::DEBUG)) {
608  double pull = info.localAngleYDiff / std::sqrt(info.angleYTotalErr2);
609  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
610  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
611  << " Y angle pull cut: |" << pull << "| > " << cuts.angleYPullCut << endmsg;
612  }
614  } else {
616  }
617  }
618 
619  //
620  // Cut on total chiSquared
621  //
622  if (cuts.cutOnMatchChiSquared && info.haveMatchChiSquared) {
623  // cut on matching chi-squared
624  if (info.matchChiSquared > cuts.matchChiSquaredCut) {
625  if (msgLvl(MSG::DEBUG)) {
626  msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed "
627  << MuonStationIndex::chName((m_idHelperSvc->chamberIndex(info.segmentChamberId)))
628  << " match chi-squared cut: " << info.matchChiSquared << " > " << cuts.matchChiSquaredCut << endmsg;
629  }
631  } else {
633  }
634  }
635 
636  //
637  // Based on all cuts, decide to accept or reject
638  //
639 
640  // match is OR of several matches
641  info.matchOK = false;
642  // if any cut was applied
643  if (info.appliedAnyCut()) {
644  if (info.passedAllCuts()) {
645  info.matchOK = true;
647  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed all cuts";
648  } else if (info.passedCut(TrackSegmentMatchResult::MatchChiSquaredCut)) {
649  info.matchOK = true;
651  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed match chi-quared cut";
652  } else if ((info.passedCut(TrackSegmentMatchResult::PosXCut) || info.passedCut(TrackSegmentMatchResult::PosXPullCut)) &&
656  info.matchOK = true;
658  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Passed cuts " << info.passedCutsString();
659  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed cuts " << info.failedCutsString();
660  } else {
662  if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << MSG::DEBUG << " -> Failed cuts " << info.failedCutsString();
663  }
664  } else { // !info.appliedCuts
665  if (info.reason == TrackSegmentMatchResult::Unknown) {
667  if (msgLvl(MSG::DEBUG)) { msg(MSG::DEBUG) << MSG::DEBUG << ". No cuts applied"; } // if msgLvl(MSG::DEBUG)
668  } // if reason == Unknown
669  } // !appliedCuts
670 
671  if (msgLvl(MSG::DEBUG)) {
672  if (info.matchOK) {
673  msg(MSG::DEBUG) << MSG::DEBUG << " -> Accepted because " << info.reasonString() << endmsg;
674  } else {
675  msg(MSG::DEBUG) << MSG::DEBUG << " -> Rejected because " << info.reasonString() << endmsg;
676  }
677  }
678 
679  return info.matchOK;
680  } // applyTrackSegmentCuts()
681 
682  void MooCandidateMatchingTool::calculateTrackSegmentMatchResult(const EventContext& ctx, const MuPatTrack& entry1, const MuPatSegment& entry2,
684  info.clear();
685  info.MCTBTrack = &entry1;
686  info.MCTBSegment = &entry2;
687  info.track = &entry1.track();
688  info.segment = entry2.segment;
689  info.segmentChamberId = entry2.chid;
690  if (!entry2.segment) {
691  ATH_MSG_WARNING(__FUNCTION__ << " entry2 does not have segment pointer.");
693  return;
694  }
695  int sector2 = m_idHelperSvc->sector(info.segmentChamberId);
696  bool hasStereoAngle = false;
697 
698  // find closest track parameters
699  const Trk::TrackParameters* closestPars = nullptr;
700  double closestParsDist = 1E9;
701  const Trk::TrackParameters* closestMeasPars = nullptr;
702  double closestMeasParsDist = 1E9;
703  // const Trk::TrackStateOnSurface* closestTSOS = 0;
704  Identifier closestId;
705  double closestIdDist = 1E9;
706  bool trackHasPhi = true;
707 
708  MagField::AtlasFieldCache fieldCache;
709  // Get field cache object
711  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
712 
713  if (fieldCondObj == nullptr) {
714  ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
715  return;
716  }
717  fieldCondObj->getInitializedCache(fieldCache);
718 
719  // loop over TSOS
720  const Trk::TrackStates* tsoses = entry1.track().trackStateOnSurfaces();
722  Trk::TrackStates::const_iterator tit_end = tsoses->end();
723  for (; tit != tit_end; ++tit) {
724  const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
725 
726  // do not want to start from a pseudo-measurement
727  const Trk::PseudoMeasurementOnTrack* pseudo = dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas);
728  if (pseudo) {
729  trackHasPhi = false;
730  continue;
731  }
732 
733  // do not want to start from non-MS measurements
734  Identifier id;
735  if (meas) {
736  id = m_edmHelperSvc->getIdentifier(*meas);
737  if (id.is_valid()) {
738  if (!m_idHelperSvc->isMuon(id)) continue;
739  if (m_idHelperSvc->isMdt(id) && m_idHelperSvc->sector(id) != sector2) hasStereoAngle = true;
740  }
741  }
742 
743  const Trk::TrackParameters* pars = (*tit)->trackParameters();
744  if (!pars) { continue; }
745 
746  // calculate distance along the direction of the track
747  double dist = (entry2.entryPars().position() - pars->position()).dot(entry1.entryPars().momentum().unit());
748  // store closest distance
749  if (std::abs(dist) < std::abs(closestParsDist)) {
750  // closestTSOS = *tit;
751  closestParsDist = dist;
752  closestPars = pars;
753  if (pars->covariance()) {
754  closestMeasParsDist = dist;
755  closestMeasPars = pars;
756  }
757  }
758  // store closest MDT or CSC ID (for printout and performance analysis)
759  if (std::abs(dist) < std::abs(closestIdDist)) {
760  if (meas && id.is_valid() && m_idHelperSvc->isMuon(id) && (m_idHelperSvc->isMdt(id) || m_idHelperSvc->isCsc(id))) {
761  closestId = id;
762  closestIdDist = dist;
763  }
764  }
765  }
766 
767  // update trackHasPhi in the cases where we do have enough phi constraints
768  if (entry1.phiHits().size() > 1) {
769  // calculate difference between hits
770  const Amg::Vector3D& gposFirstPhi = entry1.phiHits().front()->globalPosition();
771  const Amg::Vector3D& gposLastPhi = entry1.phiHits().back()->globalPosition();
772  Amg::Vector3D globalDistance = gposLastPhi - gposFirstPhi;
773 
774  // calculate 'projective' distance
775  double distance = entry1.hasEndcap() ? fabs(globalDistance.z()) : globalDistance.perp();
776 
777  if (distance > 500) trackHasPhi = true;
778  }
779 
780  if (!closestPars) {
781  ATH_MSG_DEBUG("track-segment match: No closest track parameters found.");
783  return;
784  }
785 
786  // set the identification of the first entry (the track - taking the closest point)
787  if (closestPars && closestId.is_valid()) { info.trackChamberId = m_idHelperSvc->chamberId(closestId); }
788 
789  if (msgLvl(MSG::VERBOSE)) {
790  msg(MSG::DEBUG) << MSG::VERBOSE << "match Closest chamber: " << m_idHelperSvc->toStringChamber(info.trackChamberId)
791  << " Segment: " << m_idHelperSvc->toStringChamber(info.segmentChamberId);
792  const Trk::TrackParameters* tmpPars = nullptr;
793  if (closestMeasPars) tmpPars = closestMeasPars->covariance() ? closestMeasPars : nullptr;
794  if (tmpPars) {
795  msg(MSG::DEBUG) << std::endl
796  << "Closest measured track parameters: " << m_printer->print(*tmpPars) << std::endl
797  << Amg::toString(*tmpPars->covariance(), 10) << " distance=" << closestMeasParsDist;
798  }
799  if (!tmpPars || tmpPars != closestPars) {
800  msg(MSG::DEBUG) << std::endl
801  << "Closest track parameters : " << m_printer->print(*closestPars)
802  << " distance=" << closestParsDist;
803  }
804  msg(MSG::DEBUG) << endmsg;
805  }
806 
807  bool straightLineMatch = !fieldCache.toroidOn();
808  if (hasStereoAngle && !trackHasPhi && (straightLineMatch || entry1.hasMomentum())) {
809  // can not do any extrapolation (not reliable)
811  return;
812  }
813 
814  // if extrapolating within EM-EO, can use straight-line extrapolator even without momentum
815  if (!straightLineMatch && !entry1.hasMomentum() && info.trackChamberId.is_valid()) {
816  MuonStationIndex::StIndex trackStationIndex = m_idHelperSvc->stationIndex(info.trackChamberId);
817  MuonStationIndex::StIndex segmentStationIndex = entry2.stIndex;
818  if (((trackStationIndex == MuonStationIndex::EM && segmentStationIndex == MuonStationIndex::EO) ||
819  (trackStationIndex == MuonStationIndex::EO && segmentStationIndex == MuonStationIndex::EM)) &&
820  closestPars->position().z() * entry2.entryPars().position().z() > 0.0) {
821  straightLineMatch = true;
822  ATH_MSG_DEBUG("track in " << m_idHelperSvc->toStringStation(info.trackChamberId) << " and segment in "
823  << m_idHelperSvc->toStringStation(info.segmentChamberId)
824  << " => doing straight line extrapolation match");
825  }
826  }
827 
828  //
829  // for tracks that have a momentum or have straight line match
830  //
831  if (straightLineMatch || entry1.hasMomentum()) {
832  // extrapolate to segment surface
833  std::unique_ptr<const Trk::TrackParameters> exPars;
834  const Trk::TrackParameters* exMeasPars = nullptr;
835  if (closestMeasPars) {
836  const Trk::TrackParameters* tmpPars = closestMeasPars->covariance() ? closestMeasPars : nullptr;
837 
838  if (tmpPars) {
839  // Check sector+
840  if (!m_idHelperSvc->isMuon(info.trackChamberId)) {
842  return;
843  }
844  int trackSector = m_idHelperSvc->sector(info.trackChamberId);
845  int segmentSector = m_idHelperSvc->sector(info.segmentChamberId);
846  int sectorDiff = std::abs(trackSector - segmentSector);
847  if (sectorDiff > 1 && sectorDiff != 15) {
848  ATH_MSG_VERBOSE("track sector =" << trackSector << " segment sector =" << segmentSector
849  << " => not in neighbouring sectors ");
850 
852  return;
853  }
854  // Check sector-
855 
856  if (straightLineMatch && !entry1.hasMomentum()) {
857  exPars = m_atlasExtrapolator->extrapolateDirectly(ctx, *tmpPars, entry2.segment->associatedSurface(),
858  Trk::anyDirection, false, Trk::muon);
859  } else {
860  ATH_MSG_VERBOSE(" Extrapolating to other segment " << m_printer->print(*tmpPars) << std::endl
861  << Amg::toString(*tmpPars->covariance(), 10));
862  exPars = m_atlasExtrapolator->extrapolate(ctx, *tmpPars, entry2.segment->associatedSurface(), Trk::anyDirection,
863  false, Trk::muon);
864  }
865  }
866  if (!exPars) {
867  ATH_MSG_DEBUG("track-segment match: Failed to extrapolate measured track parameters\n"
868  << m_printer->print(*closestPars) << "\nfrom " << m_idHelperSvc->toStringChamber(info.trackChamberId)
869  << " to segment surface " << m_idHelperSvc->toStringChamber(info.segmentChamberId));
870  info.matchOK = false;
872  return;
873  }
874 
875  exMeasPars = exPars->covariance() ? exPars.get() : nullptr;
876  if (!exMeasPars) {
877  ATH_MSG_DEBUG("track-segment match: Did not get measured track parameters from extrapolation\n"
878  << "\nfrom " << m_idHelperSvc->toStringChamber(info.trackChamberId) << " to segment surface "
879  << m_idHelperSvc->toStringChamber(info.segmentChamberId));
881  return;
882  }
883  ATH_MSG_VERBOSE(" ExMeasParameters " << exMeasPars << " " << m_printer->print(*exMeasPars) << std::endl
884  << Amg::toString(*exMeasPars->covariance(), 10));
885 
886  } else {
887  // no closest measured parameters, take closest parameters
888 
889  if (straightLineMatch && !entry1.hasMomentum()) {
890  exPars = m_atlasExtrapolator->extrapolateDirectly(ctx, *closestPars, entry2.segment->associatedSurface(),
891  Trk::anyDirection, false, Trk::muon);
892  } else {
893  exPars = m_atlasExtrapolator->extrapolate(ctx, *closestPars, entry2.segment->associatedSurface(), Trk::anyDirection,
894  false, Trk::muon);
895  }
896  if (!exPars) {
897  ATH_MSG_DEBUG("track-segment match: Failed to extrapolate track parameters without errors\n"
898  << m_printer->print(*closestPars) << "\nfrom " << m_idHelperSvc->toStringChamber(info.trackChamberId)
899  << " to segment surface " << m_idHelperSvc->toStringChamber(info.segmentChamberId));
900  info.matchOK = false;
902  return;
903  }
904  }
905 
906  // get the available measured information by looking at the errors
907  // check measurement errors
908  const Amg::MatrixX& measErrors = entry2.segment->localCovariance();
909 
910  double posXMeasErr2 = measErrors(Trk::locX, Trk::locX);
911  if (posXMeasErr2 <= 999.0) {
912  info.havePosX = true;
913  info.havePosXError = true;
914  info.posXMeasErr2 = posXMeasErr2;
915  info.posXTotalErr2 += posXMeasErr2;
916  }
917 
918  double posYMeasErr2 = measErrors(Trk::locY, Trk::locY);
919  if (info.posYMeasErr2 <= 999.0) {
920  info.havePosY = true;
921  info.havePosYError = true;
922  info.posYMeasErr2 = posYMeasErr2;
923  info.posYTotalErr2 += posYMeasErr2;
924  }
925  double phiMeasErr2 = measErrors(Trk::phi, Trk::phi);
926  double thetaMeasErr2 = measErrors(Trk::theta, Trk::theta);
927  if (phiMeasErr2 <= 999.0) {
928  info.haveAngleX = true;
929  info.haveAngleXError = true;
930  info.angleXMeasErr2 = phiMeasErr2;
931  info.angleXTotalErr2 += phiMeasErr2;
932  }
933  if (thetaMeasErr2 <= 999.0) {
934  info.haveAngleY = true;
935  info.haveAngleYError = true;
936  info.angleYMeasErr2 = thetaMeasErr2;
937  info.angleYTotalErr2 += thetaMeasErr2;
938  }
939 
940  // require extrapolation errors to enable use of errors
941  if (!exMeasPars) {
942  info.haveAngleXError = false;
943  info.haveAngleYError = false;
944  info.havePosXError = false;
945  info.havePosYError = false;
946  }
947 
948  // calculate position difference
949  info.localPosXDiff = exPars->parameters()[Trk::locX] - entry2.segment->localParameters()[Trk::locX];
950  info.localPosYDiff = exPars->parameters()[Trk::locY] - entry2.segment->localParameters()[Trk::locY];
951 
952  // calculate angle difference
953  Trk::LocalDirection locDirEx;
954  entry2.segment->associatedSurface().globalToLocalDirection(exPars->momentum(), locDirEx);
955 
956  const Trk::LocalDirection& locDirSeg = entry2.segment->localDirection();
957 
958  // angular residuals
959  info.localAngleXDiff = phi_diff(locDirEx.angleXZ() - locDirSeg.angleXZ());
960  info.localAngleYDiff = theta_diff(locDirEx.angleYZ() - locDirSeg.angleYZ());
961 
962  AmgSymMatrix(5) localPredCovar;
963  localPredCovar.setIdentity();
964  // only calculate if needed
965  if (info.haveAngleXError || info.haveAngleYError || info.havePosXError || info.havePosYError) {
966  // Predicted angle errors are on global phi and theta. Need to convert to errors on local angles
967  Trk::JacobianPhiThetaLocalAngles globalToLocalPredAnglesJacobian(
968  exMeasPars->parameters()[Trk::phi], exMeasPars->parameters()[Trk::theta],
969  exMeasPars->associatedSurface().transform().rotation().inverse());
970 
971  // make the Jacobian to convert all in one go from global to local
972  // so that the correlations are calculated correctly
973  AmgSymMatrix(5) globalToLocalPredJacobian;
974  globalToLocalPredJacobian.setIdentity();
975  globalToLocalPredJacobian(Trk::locX, Trk::locX) = 1.0;
976  globalToLocalPredJacobian(Trk::locY, Trk::locY) = 1.0;
977  globalToLocalPredJacobian(Trk::phi, Trk::phi) = globalToLocalPredAnglesJacobian(0, 0);
978  globalToLocalPredJacobian(Trk::theta, Trk::theta) = globalToLocalPredAnglesJacobian(1, 1);
979  globalToLocalPredJacobian(Trk::theta, Trk::phi) =
980  globalToLocalPredAnglesJacobian(0, 1); // also fills (Trk::phi,Trk::theta)
981  globalToLocalPredJacobian(Trk::phi, Trk::theta) = globalToLocalPredJacobian(Trk::theta, Trk::phi);
982  globalToLocalPredJacobian(Trk::qOverP, Trk::qOverP) = 1.0;
983  const AmgSymMatrix(5)& globalPredCovar = *exMeasPars->covariance();
984  localPredCovar = globalPredCovar.similarity(globalToLocalPredJacobian);
985  }
986 
987  if (info.haveAngleXError && info.haveAngleYError && info.havePosXError && info.havePosYError) {
988  // Full 4D info available: CSC segments and MDT small-large overlap
989  info.measuredCovariance = measErrors.block<4, 4>(0, 0); // sub(1,4); hope this is ok ....
990  info.predictionCovariance = localPredCovar.block<4, 4>(0, 0); // sub(1,4); hope this is ok ....
991  info.totalCovariance = info.measuredCovariance + info.predictionCovariance;
992 
993  // add alignment errors
998 
999  // fill difference vector
1000  Amg::VectorX diffVec(4);
1001  diffVec[Trk::locX] = exPars->parameters()[Trk::locX] - entry2.segment->localParameters()[Trk::locX];
1002  diffVec[Trk::locY] = exPars->parameters()[Trk::locY] - entry2.segment->localParameters()[Trk::locY];
1003  diffVec[Trk::phi] = exPars->parameters()[Trk::phi] - entry2.segment->localParameters()[Trk::phi];
1004  diffVec[Trk::theta] = exPars->parameters()[Trk::theta] - entry2.segment->localParameters()[Trk::theta];
1005  info.diffVector = diffVec;
1006 
1007  // finally calculate the match chi-squared
1008  Amg::MatrixX weightMatrix = info.totalCovariance.inverse();
1009  info.matchChiSquared = info.diffVector.transpose() * weightMatrix * info.diffVector;
1010  info.haveMatchChiSquared = true;
1011 
1012  // update separate angles (redunant with covar)
1013  info.posXPredErr2 = localPredCovar(Trk::locX, Trk::locX);
1014  info.posYPredErr2 = localPredCovar(Trk::locY, Trk::locY);
1015  info.angleXPredErr2 = localPredCovar(Trk::phi, Trk::phi);
1016  info.angleYPredErr2 = localPredCovar(Trk::theta, Trk::theta);
1017  // update total errors
1018  info.posXTotalErr2 += info.posXPredErr2;
1019  info.posYTotalErr2 += info.posYPredErr2;
1020  info.angleXTotalErr2 += info.angleXPredErr2;
1021  info.angleYTotalErr2 += info.angleYPredErr2;
1022  info.posXTotalErr2 += m_alignErrorPosX * m_alignErrorPosX;
1023  info.posYTotalErr2 += m_alignErrorPosY * m_alignErrorPosY;
1024  info.angleXTotalErr2 += m_alignErrorAngleX * m_alignErrorAngleX;
1025  info.angleYTotalErr2 += m_alignErrorAngleY * m_alignErrorAngleY;
1026 
1027  } else if (info.haveAngleYError && info.havePosYError) {
1028  // 2D Y info available:
1029  // normal (non-overlap) MDT segments have no X nor phi(angleXZ) measurement, and give error on local angleYZ
1030 
1031  // Y,angleYZ 2x2 sub-set of predicted covariance
1032  AmgSymMatrix(2) predCovar{AmgSymMatrix(2)::Zero()};
1033  predCovar(0, 0) = localPredCovar(Trk::locY, Trk::locY); // Y
1034  predCovar(1, 1) = localPredCovar(Trk::theta, Trk::theta); // angleYZ
1035  predCovar(1, 0) = localPredCovar(Trk::theta, Trk::locY); // also sets (0,1)
1036  predCovar(0, 1) = predCovar(1, 0);
1037  info.predictionCovariance = predCovar;
1038 
1039  // Y,angleYZ 2x2 sub-set of measured covariance
1040  AmgSymMatrix(2) measCovar{AmgSymMatrix(2)::Zero()};
1041  measCovar.setIdentity();
1042  measCovar(0, 0) = measErrors(Trk::locY, Trk::locY);
1043  measCovar(1, 1) = measErrors(Trk::theta, Trk::theta);
1044  measCovar(1, 0) = measErrors(Trk::theta, Trk::locY);
1045  measCovar(0, 1) = measCovar(1, 0);
1046 
1047  info.measuredCovariance = measCovar;
1048  info.totalCovariance = info.predictionCovariance + info.measuredCovariance;
1049  // add alignment errors
1050  info.totalCovariance(0, 0) += m_alignErrorPosY * m_alignErrorPosY;
1051  info.totalCovariance(1, 1) += m_alignErrorAngleY * m_alignErrorAngleY;
1052  if (std::abs(info.totalCovariance.determinant()) <
1053  std::numeric_limits<float>::epsilon()){
1055  return;
1056  }
1057  // now fill the difference vector
1058  Amg::VectorX diffVec(2);
1059  diffVec[0] = info.localPosYDiff;
1060  diffVec[1] = info.localAngleYDiff;
1061  info.diffVector = diffVec;
1062 
1063  // finally calculate the match chi-squared
1064  Amg::MatrixX weightMatrix = info.totalCovariance.inverse();
1065  info.matchChiSquared = info.diffVector.transpose() * weightMatrix * info.diffVector;
1066  info.haveMatchChiSquared = true;
1067 
1068  // fill all available information (redundant with covar)
1069  info.posXPredErr2 = localPredCovar(Trk::locX, Trk::locX);
1070  info.posYPredErr2 = localPredCovar(Trk::locY, Trk::locY);
1071  info.angleXPredErr2 = localPredCovar(Trk::phi, Trk::phi);
1072  info.angleYPredErr2 = localPredCovar(Trk::theta, Trk::theta);
1073  // only use Y/angleY
1074  info.posYTotalErr2 += info.posYPredErr2;
1075  info.angleYTotalErr2 += info.angleYPredErr2;
1076  info.posYTotalErr2 += m_alignErrorPosY * m_alignErrorPosY;
1077  info.angleYTotalErr2 += m_alignErrorAngleY * m_alignErrorAngleY;
1078 
1079  } else {
1081  }
1082 
1083  } else {
1085  //
1086  // Alternative method:
1087  // EM/EO -> EI
1088  // extrapolate (straight line) from EM/EO track and line to IP -> matching region
1089 
1090  } // else !straighLineMatch && !entry1.hasMomemtum()
1091 
1092  }
1093 
1094  bool MooCandidateMatchingTool::sameSide(const MuPatSegment& entry1, const MuPatSegment& entry2, bool sameSideOfPerigee) const {
1095  ATH_MSG_VERBOSE("sameSide: MuPatSegment, MuPatSegment");
1096  return sameSide(entry1.entryPars().momentum().unit(),
1097  entry1.entryPars().position(),
1098  entry2.entryPars().position(), sameSideOfPerigee);
1099  }
1100 
1101  bool MooCandidateMatchingTool::sameSide(const MuPatTrack& entry1, const MuPatSegment& entry2, bool sameSideOfPerigee) const {
1102  ATH_MSG_VERBOSE("sameSide: MuPatTrack, MuPatSegment");
1103  return sameSide(entry1.entryPars().momentum().unit(), entry1.entryPars().position(), entry2.entryPars().position(),
1104  sameSideOfPerigee);
1105  }
1106 
1107  bool MooCandidateMatchingTool::sameSide(const MuPatTrack& entry1, const MuPatTrack& entry2, bool sameSideOfPerigee) const {
1108  ATH_MSG_VERBOSE("sameSide: MuPatTrack, MuPatTrack");
1109  return sameSide(entry1.entryPars().momentum().unit(), entry1.entryPars().position(), entry2.entryPars().position(),
1110  sameSideOfPerigee);
1111  }
1113  bool requireSameSideOfPerigee) const {
1114  // check if segments are on same side of the Perigee in the xy plane
1115  Amg::Vector3D dirxy{dir.x(),dir.y(), 0.};
1116  dirxy = dirxy.unit();
1117  double distFromPerigee1 = pos1.dot(dirxy);
1118  double distFromPerigee2 = pos2.dot(dirxy);
1119  bool sameSideOfPerigee = (distFromPerigee1 * distFromPerigee2 > 0.);
1120  bool same = sameSideOfPerigee;
1121 
1122  // if one segment in each endcap, then consider on different side
1123  bool inOppositeEndcap = false;
1124  constexpr double etaEndcap = 1.1;
1125  double eta1 = pos1.eta();
1126  double eta2 = pos2.eta();
1127  if ((eta1 > +etaEndcap && eta2 < -etaEndcap) || (eta1 < -etaEndcap && eta2 > +etaEndcap)) {
1128  inOppositeEndcap = true;
1129  same = false;
1130  }
1131 
1132  if (msgLvl(MSG::VERBOSE)) {
1133  msg(MSG::DEBUG) << MSG::VERBOSE << "sameSide: Require same side of Perigee: " << requireSameSideOfPerigee;
1134  double sign1 = pos1.y() < 0 ? -1. : 1.;
1135  double sign2 = pos2.y() < 0 ? -1. : 1.;
1136  msg(MSG::DEBUG) << " Direction " << dir << std::fixed << std::setprecision(0) << std::endl
1137  << " pos1: dist " << std::setw(6) << distFromPerigee1 << " r " << std::setw(6) << pos1.perp() * sign1
1138  << " (x,y,z)=(" << std::setw(5) << pos1.x() << "," << std::setw(5) << pos1.y() << "," << std::setw(5)
1139  << pos1.z() << ")" << std::endl
1140  << " pos2: dist " << std::setw(6) << distFromPerigee2 << " r " << std::setw(6) << pos2.perp() * sign2
1141  << " (x,y,z)=(" << std::setw(5) << pos2.x() << "," << std::setw(5) << pos2.y() << "," << std::setw(5)
1142  << pos2.z() << ")" << std::setprecision(6); // back to default
1143 
1144  if (sameSideOfPerigee) {
1145  msg(MSG::DEBUG) << std::endl << " Same side of perigee.";
1146  } else {
1147  msg(MSG::DEBUG) << std::endl << " Other side of perigee.";
1148  }
1149  if (inOppositeEndcap) { msg(MSG::DEBUG) << " In opposite end-cap."; }
1150  }
1151 
1152  // if segments are on the same side of the Perigee, they are also on the same side of Calo, so can return
1153  if (same) {
1154  if (msgLvl(MSG::VERBOSE)) msg(MSG::DEBUG) << " => Accepted" << endmsg;
1155  return true;
1156  }
1157 
1158  // if requiring sameSideOfPerigee (stronger condition), then we are done here.
1159  if (requireSameSideOfPerigee) {
1160  if (msgLvl(MSG::VERBOSE)) msg(MSG::DEBUG) << " => Rejected" << endmsg;
1161  return false;
1162  }
1163  return true;
1164  }
1165 
1166  bool MooCandidateMatchingTool::match(const EventContext& ctx, const MuPatCandidateBase& entry1, const MuPatSegment& entry2, bool useTightCuts) const {
1167  const MuPatSegment* seg = dynamic_cast<const MuPatSegment*>(&entry1);
1168  if (seg) return match(ctx, *seg, entry2, useTightCuts);
1169 
1170  const MuPatTrack* track = dynamic_cast<const MuPatTrack*>(&entry1);
1171  if (track) return match(ctx, *track, entry2, useTightCuts);
1172 
1173  return false;
1174  }
1175 
1176  void MooCandidateMatchingTool::getIdentifierSet(const std::vector<const Trk::MeasurementBase*>& measurements,
1177  std::set<Identifier>& ids) {
1178  // loop over measurements and extract all identifiers
1179  std::vector<const Trk::MeasurementBase*>::const_iterator it = measurements.begin();
1180  std::vector<const Trk::MeasurementBase*>::const_iterator it_end = measurements.end();
1181  for (; it != it_end; ++it) {
1182  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*it);
1183  if (rot) {
1184  ids.insert(rot->identify());
1185  } else {
1186  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*it);
1187  if (crot) {
1188  const std::vector<const MuonClusterOnTrack*>& rots = crot->containedROTs();
1189  std::vector<const MuonClusterOnTrack*>::const_iterator rit = rots.begin();
1190  std::vector<const MuonClusterOnTrack*>::const_iterator rit_end = rots.end();
1191  for (; rit != rit_end; ++rit) ids.insert((*rit)->identify());
1192  }
1193  }
1194  }
1195  }
1196 
1198  // check whether one of the two entries has no phi hits in which case return true
1199  if (entry1.phiHits().empty() || entry2.phiHits().empty()) return true;
1200 
1201  std::set<Identifier> ids1;
1202  getIdentifierSet(entry1.phiHits(), ids1);
1203 
1204  std::set<Identifier> ids2;
1205  getIdentifierSet(entry2.phiHits(), ids2);
1206 
1207  std::vector<Identifier> intersection;
1208  std::set_intersection(ids1.begin(), ids1.end(), ids2.begin(), ids2.end(), std::back_inserter(intersection));
1209 
1210  unsigned int intersectionSize = intersection.size();
1211  // require a full overlap between the two entries or that one of the two is a subset of the other
1212  if (intersectionSize == ids1.size() || intersectionSize == ids2.size()) return true;
1213 
1214  // also accept if there is no overlap
1215  if (intersectionSize == 0) return true;
1216 
1217  return false;
1218  }
1219 
1221  DistanceToPars distToPars(&entry1.entryPars());
1222  double distance = distToPars(entry2.entryPars().position());
1223  if (std::abs(distance) > 5000.) {
1224  ATH_MSG_VERBOSE(" large distance between segments, not using segment " << distance);
1225  return false;
1226  }
1227  return true;
1228  }
1229 
1231  Identifier chid1 = seg1.chid;
1232  Identifier chid2 = seg2.chid;
1233  if (msgLvl(MSG::VERBOSE)) {
1234  msg(MSG::VERBOSE) << "check if chambers are neighbours: " << m_idHelperSvc->toStringChamber(chid1) << " and "
1235  << m_idHelperSvc->toStringChamber(chid2) << ": ";
1236  }
1237  // if in same chamber, then OK
1238  if (chid1 == chid2) {
1239  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "in same chamber" << endmsg;
1240  return true;
1241  }
1242  // check in r
1243  if (seg1.stIndex != seg2.stIndex) {
1244  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "not in same station" << endmsg;
1245  return false;
1246  }
1247 
1248  // check in phi
1249  int secDiff = std::abs(m_idHelperSvc->sector(chid1) - m_idHelperSvc->sector(chid2));
1250  if (secDiff > 1 && secDiff != 15) {
1251  if (msgLvl(MSG::VERBOSE))
1252  msg(MSG::VERBOSE) << "sec1=" << m_idHelperSvc->sector(chid1) << "sec2=" << m_idHelperSvc->sector(chid2)
1253  << " => not in neighbouring phi " << endmsg;
1254  return false;
1255  }
1256 
1257  // check in eta
1258  if (seg1.isEndcap && seg2.isEndcap) {
1259  // both in endcap
1260  // endcap: can compare eta indices
1261  if (std::abs(m_idHelperSvc->stationEta(chid1) - m_idHelperSvc->stationEta(chid2)) > 1) {
1262  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "not in neighbouring eta" << endmsg;
1263  return false;
1264  }
1265  } else if (!seg1.isEndcap && !seg2.isEndcap) {
1266  // both in barrel
1267  const std::string& stationName1 =
1268  m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(chid1));
1269  const std::string& stationName2 =
1270  m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(chid2));
1271  std::string exceptions("MRFG");
1272  if (exceptions.find(stationName1[2]) == std::string::npos && exceptions.find(stationName2[2]) == std::string::npos) {
1273  // the normal case
1274  if (std::abs(m_idHelperSvc->stationEta(chid1) - m_idHelperSvc->stationEta(chid2)) > 1) {
1275  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "not in neighbouring eta " << endmsg;
1276  return false;
1277  }
1278  } else {
1279  // the exceptions: use geometrical information
1280  const std::set<const MuonGM::MuonReadoutElement*> roEls1 = m_candidateTool->readoutElements(seg1);
1281  const std::set<const MuonGM::MuonReadoutElement*> roEls2 = m_candidateTool->readoutElements(seg2);
1282  for (const MuonGM::MuonReadoutElement* read_ele1 : roEls1) {
1283  for (const MuonGM::MuonReadoutElement* read_ele2 : roEls2) {
1284  double distZ = std::abs(read_ele1->center().z() - read_ele2->center().z());
1285  // subtract sizes
1286  distZ -= 0.5 * (read_ele1->getZsize() + read_ele2->getZsize());
1287  if (msgLvl(MSG::VERBOSE)) {
1288  msg(MSG::VERBOSE) << std::endl
1289  << read_ele1->getStationType() << ": z=" << read_ele1->center().z() << "+-"
1290  << 0.5 * read_ele1->getZsize() << " " << read_ele2->getStationType()
1291  << ": z=" << read_ele2->center().z() << "+-" << 0.5 * read_ele2->getZsize() << " "
1292  << "distZ=" << distZ;
1293  }
1294  // allow some distance
1295  if (distZ > 100.0) {
1296  if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << " z-position too far apart" << endmsg;
1297  return false;
1298  }
1299  }
1300  }
1301  }
1302  } else {
1303  // don't mix barrel/endcap
1304  ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<< "endcap/barrel mix");
1305  return false;
1306  }
1307 
1308  ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<< " Yes!");
1309  return true;
1310  }
1311 } // namespace Muon
grepfile.info
info
Definition: grepfile.py:38
Muon::MuonStationIndex::chName
static const std::string & chName(ChIndex index)
convert ChIndex into a string
Definition: MuonStationIndex.cxx:157
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:1094
Muon::MooCandidateMatchingTool::m_sameSideOfPerigeeTrk
std::atomic_ulong m_sameSideOfPerigeeTrk
Definition: MooCandidateMatchingTool.h:201
Muon::TrackSegmentMatchResult::NumberOfReasons
@ NumberOfReasons
Definition: MuonTrackSegmentMatchResult.h:72
Muon::MuonStationIndex::CSS
@ CSS
Definition: MuonStationIndex.h:18
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:32
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:29
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:1220
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
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:43
Muon::MooCandidateMatchingTool::checkPhiHitConsistency
static bool checkPhiHitConsistency(const MuPatCandidateBase &entry1, const MuPatCandidateBase &entry2)
evaluate overlap between phi hits of two entries.
Definition: MooCandidateMatchingTool.cxx:1197
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:44
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
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
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.
Muon::MuonStationIndex::EO
@ EO
Definition: MuonStationIndex.h:26
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
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:1230
skel.it
it
Definition: skel.GENtoEVGEN.py:423
Muon::MooCandidateMatchingTool::m_otherSideOfPerigee
std::atomic_ulong m_otherSideOfPerigee
Definition: MooCandidateMatchingTool.h:200
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:201
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:57
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
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
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::stIndex
MuonStationIndex::StIndex stIndex
Definition: MuPatSegment.h:59
Muon::MuPatSegment::isMdt
bool isMdt
true for MDT, false for CSC
Definition: MuPatSegment.h:61
Muon::TrackSegmentMatchResult::NoSegmentPointer
@ NoSegmentPointer
Definition: MuonTrackSegmentMatchResult.h:57
python.TrigEgammaFastCaloHypoTool.same
def same(val, tool)
Definition: TrigEgammaFastCaloHypoTool.py:12
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:682
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:52
MuPatSegment.h
Muon::TrackSegmentMatchCuts
Definition: MuonTrackSegmentMatchResult.h:174
Muon::MooCandidateMatchingTool::applyTrackSegmentCuts
bool applyTrackSegmentCuts(const EventContext &ctx, MooTrackSegmentMatchResult &info, const TrackSegmentMatchCuts &cuts) const
Definition: MooCandidateMatchingTool.cxx:382
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:56
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
TileDCSDataPlotter.tit
tit
Definition: TileDCSDataPlotter.py:890
Muon::MooCandidateMatchingTool::~MooCandidateMatchingTool
virtual ~MooCandidateMatchingTool()
destructor
Muon::MooCandidateMatchingTool::m_doTrackSegmentMatching
Gaudi::Property< bool > m_doTrackSegmentMatching
Definition: MooCandidateMatchingTool.h:190
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:83
Muon::MooCandidateMatchingTool::m_otherSideOfPerigeeTrk
std::atomic_ulong m_otherSideOfPerigeeTrk
Definition: MooCandidateMatchingTool.h:202
lumiFormat.i
int i
Definition: lumiFormat.py:92
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
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
beamspotman.n
n
Definition: beamspotman.py:731
Muon::MuPatSegment::isEndcap
bool isEndcap
Definition: MuPatSegment.h:60
Trk::theta
@ theta
Definition: ParamDefs.h:72
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
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
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:52
plotBeamSpotVert.cuts
string cuts
Definition: plotBeamSpotVert.py:93
PseudoMeasurementOnTrack.h
Muon::MooCandidateMatchingTool::m_reasonsForMatchNotOk
std::atomic_ulong m_reasonsForMatchNotOk[TrackSegmentMatchResult::NumberOfReasons]
Definition: MooCandidateMatchingTool.h:206
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:264
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:260
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:28
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:623
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:1176
Muon::MooCandidateMatchingTool::MooTrackSegmentMatchResult::MooTrackSegmentMatchResult
MooTrackSegmentMatchResult()
Definition: MooCandidateMatchingTool.cxx:53
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:191
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
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
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
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:73
Trk::RIO_OnTrack::identify
virtual Identifier identify() const final
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:155
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::TrackSegmentMatchResult::PosYPullCut
@ PosYPullCut
Definition: MuonTrackSegmentMatchResult.h:37
MuonSegment.h
Muon::MuonStationIndex::StIndex
StIndex
enum to classify the different station layers in the muon spectrometer
Definition: MuonStationIndex.h:23
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:81
jobOptions.prec
prec
Definition: jobOptions.Superchic_UPC_yyMuMu.py:20
LocalDirection.h
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
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:200
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
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::MuonStationIndex::EM
@ EM
Definition: MuonStationIndex.h:26
Muon::TrackSegmentMatchResult::clear
virtual void clear()
Definition: MuonTrackSegmentMatchResult.cxx:34
Muon::MuonStationIndex::CSL
@ CSL
Definition: MuonStationIndex.h:18
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