ATLAS Offline Software
MuonSegmentPairMatchingTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
14 
15 namespace {
16 // limit angle difference to -pi < x <= pi
17 inline double
18 limit_angle_2pi(double x)
19 {
20  while (x <= -M_PI) x += 2.0 * M_PI;
21  while (x > +M_PI) x -= 2.0 * M_PI;
22  return x;
23 }
24 
25 inline double
26 robust_acos(double x)
27 {
28  if (x >= +1.0) return 0.0;
29  if (x <= -1.0) return M_PI;
30  return std::acos(x);
31 }
32 
33 } // unnamed namespace
34 
35 
36 namespace Muon {
37 
38 MuonSegmentPairMatchingTool::MuonSegmentPairMatchingTool(const std::string& ty, const std::string& na,
39  const IInterface* pa)
40  : AthAlgTool(ty, na, pa)
41 {
42  declareInterface<IMuonSegmentPairMatchingTool>(this);
43 }
44 
47 {
49 
50  ATH_CHECK(m_edmHelperSvc.retrieve());
51  ATH_CHECK(m_printer.retrieve());
52  ATH_CHECK(m_idHelperSvc.retrieve());
53 
54  return StatusCode::SUCCESS;
55 }
56 
59 {
61 
62  // get identifiers
63  // and the detector region from identifier
64  Identifier chid1 = m_edmHelperSvc->chamberId(seg1);
65  MuonStationIndex::StIndex station1 = m_idHelperSvc->stationIndex(chid1);
66 
67  Identifier chid2 = m_edmHelperSvc->chamberId(seg2);
68  MuonStationIndex::StIndex station2 = m_idHelperSvc->stationIndex(chid2);
69 
70  // Don't deal with overlap/merge of segments here
71  if (chid1 == chid2) return result;
72  if (station1 == station2) return result;
73 
74  // Don't know how to deal with these cases yet...
75  if (station1 == MuonStationIndex::StUnknown) return result;
76  if (station2 == MuonStationIndex::StUnknown) return result;
77  if (station1 >= MuonStationIndex::StIndexMax) return result;
78  if (station2 >= MuonStationIndex::StIndexMax) return result;
79 
80  // Here order matters, so sort segment by order a= inner, b= outer
81  // MuonStationIndex::StIndex station_a = station1;
82  // MuonStationIndex::StIndex station_b = station2;
83 
84  const MuonSegment* pSeg_a = nullptr;
85  const MuonSegment* pSeg_b = nullptr;
86 
87  // bool swapped = false;
88  if (station1 < station2) {
89  pSeg_a = &seg1;
90  pSeg_b = &seg2;
91 
92  } else {
93  // swapped = true;
94  pSeg_a = &seg2;
95  pSeg_b = &seg1;
96  // station_a = station2;
97  // station_b = station1;
98  }
99 
100  const MuonSegment& seg_a(*pSeg_a);
101  const MuonSegment& seg_b(*pSeg_b);
102 
103  Identifier chid_a = m_edmHelperSvc->chamberId(seg_a);
104  Identifier chid_b = m_edmHelperSvc->chamberId(seg_b);
105 
106  int phiSector_a = m_idHelperSvc->sector(chid_a);
107  int phiSector_b = m_idHelperSvc->sector(chid_b);
108 
109  result.chid_a = chid_a;
110  result.chid_b = chid_b;
111 
112  result.phiSector_a = phiSector_a;
113  result.phiSector_b = phiSector_b;
114 
115  const Amg::Vector3D& dir_a = seg_a.globalDirection();
116  const Amg::Vector3D& dir_b = seg_b.globalDirection();
117  const Amg::Vector3D& pos_a = seg_a.globalPosition();
118  const Amg::Vector3D& pos_b = seg_b.globalPosition();
119 
120  // Define direction between segment position
121  Amg::Vector3D vecAB = pos_b - pos_a;
122 
123  // compute angle between vector position a and b using dot product
124  double sizeA = dir_a.mag();
125  double sizeB = dir_b.mag();
126  double cosAB = dir_a.dot(dir_b) / (sizeA * sizeB);
127  double angleAB = robust_acos(cosAB);
128 
129  // compute angle between vector position a and b using dot product
130  double sizeC = vecAB.mag();
131  double cosAC = dir_a.dot(vecAB) / (sizeA * sizeC);
132  double angleAC = robust_acos(cosAC);
133 
134  // compute angle between vector position a and b using dot product
135  double cosBC = dir_b.dot(vecAB) / (sizeB * sizeC);
136  double angleBC = robust_acos(cosBC);
137 
138 
139  if (angleAB > M_PI / 2.) angleAB = fabs(angleAB - M_PI);
140  if (angleAC > M_PI / 2.) angleAC = fabs(angleAC - M_PI);
141  if (angleBC > M_PI / 2.) angleBC = fabs(angleBC - M_PI);
142 
143  result.angleAB = angleAB;
144  result.angleAC = angleAC;
145  result.angleBC = angleBC;
146 
147  // Compute local angles
148  // for some reason, vec12 gets the direction right far more often than vecAB
149  double dirTheta_a = seg_a.localDirection().angleYZ();
150  double dirTheta_b = seg_b.localDirection().angleYZ();
151  Trk::LocalDirection dirPred_a;
152  seg_a.associatedSurface().globalToLocalDirection(vecAB, dirPred_a);
153  Trk::LocalDirection dirPred_b;
154  seg_b.associatedSurface().globalToLocalDirection(vecAB, dirPred_b);
155  double deltaTheta_a = limit_angle_2pi(dirTheta_a - dirPred_a.angleYZ());
156  double deltaTheta_b = limit_angle_2pi(dirTheta_b - dirPred_b.angleYZ());
157 
158  // bool opposite = false;
159  // in case both segment directions are opposite to vecAB, try opposite direction
160  if (std::abs(deltaTheta_a) > 0.5 * M_PI && std::abs(deltaTheta_b) > 0.5 * M_PI) {
161  // opposite = true;
162  seg_a.associatedSurface().globalToLocalDirection(-vecAB, dirPred_a);
163  seg_b.associatedSurface().globalToLocalDirection(-vecAB, dirPred_b);
164  deltaTheta_a = limit_angle_2pi(dirTheta_a - dirPred_a.angleYZ());
165  deltaTheta_b = limit_angle_2pi(dirTheta_b - dirPred_b.angleYZ());
166  }
167 
168 
169  // look at the relative orientation of the local X axes to determine if YZ angles are flipped
170  bool flipped = false;
171  const Amg::Transform3D& trf_a = seg_a.associatedSurface().transform();
172  const Amg::Transform3D& trf_b = seg_b.associatedSurface().transform();
173  double xAxisDotProduct = trf_a(0, 0) * trf_b(0, 0) + trf_a(1, 0) * trf_b(1, 0) + trf_a(2, 0) * trf_b(2, 0);
174  if (xAxisDotProduct < 0.0) flipped = true;
175 
176  double deltaTheta = 0.0;
177  if (flipped) {
178  deltaTheta = std::abs(limit_angle_2pi(deltaTheta_a - deltaTheta_b));
179  } else {
180  deltaTheta = std::abs(limit_angle_2pi(deltaTheta_a + deltaTheta_b));
181  }
182 
183  result.deltaTheta_a = deltaTheta_a;
184  result.deltaTheta_b = deltaTheta_b;
185  result.deltaTheta = deltaTheta;
186 
187  // compute angular differences in second coordinate
188  result.deltaPhipos = fabs(seg_a.globalPosition().phi() - seg_b.globalPosition().phi());
189  result.deltaPhidir = fabs(seg_a.globalDirection().phi() - seg_b.globalDirection().phi());
190 
191  // check presence of phi hits on segment a
192  bool ContainPhiHits = false;
193  std::vector<const Trk::MeasurementBase*>::const_iterator hit = seg_a.containedMeasurements().begin();
194  std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = seg_a.containedMeasurements().end();
195  for (; hit != hit_end; ++hit) {
196  Identifier id;
197  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*hit);
198  if (rot)
199  id = rot->identify();
200  else {
201  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit);
202  if (crot) id = crot->containedROTs().front()->identify();
203  }
204  if (!id.is_valid()) continue;
205  if (m_idHelperSvc->measuresPhi(id)) {
206  ContainPhiHits = true;
207  break;
208  }
209  }
210 
211  if (ContainPhiHits) {
212  result.phiposerr_a = seg_a.localCovariance()(Trk::locX, Trk::locX);
213  result.phidirerr_a = seg_a.localCovariance()(Trk::phi, Trk::phi);
214  } else {
215  result.phiposerr_a = 99999.;
216  result.phidirerr_a = 99999.;
217  }
218 
219  // check presence of phi hits on segment b
220  ContainPhiHits = false;
221  hit = seg_b.containedMeasurements().begin();
222  hit_end = seg_b.containedMeasurements().end();
223  for (; hit != hit_end; ++hit) {
224  Identifier id;
225  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*hit);
226  if (rot)
227  id = rot->identify();
228  else {
229  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit);
230  if (crot) id = crot->containedROTs().front()->identify();
231  }
232  if (!id.is_valid()) continue;
233  if (m_idHelperSvc->measuresPhi(id)) {
234  ContainPhiHits = true;
235  break;
236  }
237  }
238 
239  if (ContainPhiHits) {
240  result.phiposerr_b = seg_b.localCovariance()(Trk::locX, Trk::locX);
241  result.phidirerr_b = seg_b.localCovariance()(Trk::phi, Trk::phi);
242  } else {
243  result.phiposerr_b = 99999.;
244  result.phidirerr_b = 99999.;
245  }
246 
247  result.shorttube_a = 99999.;
248  if (m_idHelperSvc->isMdt(chid_a)) {
249  // make shortest tube calculations
250  std::pair<Amg::Vector3D, Amg::Vector3D> stseg1 = getShortestTubePos(seg_a);
251  double shorttube_lx_a = stseg1.first.x();
252  double shorttube_ly_a = stseg1.first.y();
253  double shorttube_rx_a = stseg1.second.x();
254  double shorttube_ry_a = stseg1.second.y();
255 
256  double dist_x_la = seg_a.globalPosition().x() - shorttube_lx_a;
257  double dist_x_ra = seg_a.globalPosition().x() - shorttube_rx_a;
258 
259  double dist_y_la = seg_a.globalPosition().y() - shorttube_ly_a;
260  double dist_y_ra = seg_a.globalPosition().y() - shorttube_ry_a;
261 
262  double dist_la = sqrt(dist_x_la * dist_x_la + dist_y_la * dist_y_la);
263  double dist_ra = sqrt(dist_x_ra * dist_x_ra + dist_y_ra * dist_y_ra);
264 
265  if (dist_la >= dist_ra)
266  result.shorttube_a = dist_ra;
267  else
268  result.shorttube_a = dist_la;
269  }
270 
271  result.shorttube_b = 99999.;
272  if (m_idHelperSvc->isMdt(chid_b)) {
273  std::pair<Amg::Vector3D, Amg::Vector3D> stseg2 = getShortestTubePos(seg_b);
274  double shorttube_lx_b = stseg2.first.x();
275  double shorttube_ly_b = stseg2.first.y();
276  double shorttube_rx_b = stseg2.second.x();
277  double shorttube_ry_b = stseg2.second.y();
278 
279  double dist_x_lb = seg_b.globalPosition().x() - shorttube_lx_b;
280  double dist_x_rb = seg_b.globalPosition().x() - shorttube_rx_b;
281 
282  double dist_y_lb = seg_b.globalPosition().y() - shorttube_ly_b;
283  double dist_y_rb = seg_b.globalPosition().y() - shorttube_ry_b;
284 
285  double dist_lb = sqrt(dist_x_lb * dist_x_lb + dist_y_lb * dist_y_lb);
286  double dist_rb = sqrt(dist_x_rb * dist_x_rb + dist_y_rb * dist_y_rb);
287 
288  if (dist_lb >= dist_rb)
289  result.shorttube_b = dist_rb;
290  else
291  result.shorttube_b = dist_lb;
292  }
293  result.matchFlag = true;
294 
295  return result;
296 }
297 
298 std::pair<Amg::Vector3D, Amg::Vector3D>
300 {
301  const Muon::MdtDriftCircleOnTrack* shortestMdt = nullptr;
302  double storedLength = 999999;
303 
304  // loop over hits, cast each hit to drift circle
305 
306  const std::vector<const Trk::MeasurementBase*>& rioVec = seg.containedMeasurements();
307  std::vector<const Trk::MeasurementBase*>::const_iterator it = rioVec.begin();
308  std::vector<const Trk::MeasurementBase*>::const_iterator it_end = rioVec.end();
309 
310  for (; it != it_end; ++it) {
311  const Muon::MdtDriftCircleOnTrack* mdt = dynamic_cast<const Muon::MdtDriftCircleOnTrack*>(*it);
312  if (!mdt) continue;
313  const MuonGM::MdtReadoutElement* roe = mdt->detectorElement();
314  if (!roe) continue;
315 
316  // sanity check with getActiveTubeLength
317  int layer = m_idHelperSvc->mdtIdHelper().tubeLayer(mdt->identify());
318  int tube = m_idHelperSvc->mdtIdHelper().tube(mdt->identify());
319  double halfLength = 0.5 * roe->getActiveTubeLength(layer, tube);
320 
321  if (2 * halfLength > storedLength) continue;
322 
323  storedLength = halfLength;
324  shortestMdt = mdt;
325  }
326  std::pair<Amg::Vector3D, Amg::Vector3D> shortpos;
327  Amg::Vector2D lp(0, storedLength);
328  if (shortestMdt) shortestMdt->associatedSurface().localToGlobal(lp, Amg::Vector3D::UnitZ(), shortpos.first);
329  lp[1] = -storedLength;
330  if (shortestMdt) shortestMdt->associatedSurface().localToGlobal(lp, Amg::Vector3D::UnitZ(), shortpos.second);
331  return shortpos;
332 }
333 } // namespace Muon
Muon::MuonSegmentPairMatchingTool::m_printer
PublicToolHandle< MuonEDMPrinterTool > m_printer
EDM printer tool.
Definition: MuonSegmentPairMatchingTool.h:51
Muon::MuonStationIndex::StUnknown
@ StUnknown
Definition: MuonStationIndex.h:24
Muon::MuonSegmentPairMatchingTool::matchResult
SegmentMatchResult matchResult(const MuonSegment &seg1, const MuonSegment &seg2) const
performance match and return result
Definition: MuonSegmentPairMatchingTool.cxx:58
MdtReadoutElement.h
get_generator_info.result
result
Definition: get_generator_info.py:21
Muon::MuonSegmentPairMatchingTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonSegmentPairMatchingTool.h:39
Trk::locX
@ locX
Definition: ParamDefs.h:43
MuonEDMPrinterTool.h
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
Muon::MuonSegmentPairMatchingTool::getShortestTubePos
std::pair< Amg::Vector3D, Amg::Vector3D > getShortestTubePos(const Muon::MuonSegment &seg) const
Definition: MuonSegmentPairMatchingTool.cxx:299
initialize
void initialize()
Definition: run_EoverP.cxx:894
skel.it
it
Definition: skel.GENtoEVGEN.py:423
CompetingMuonClustersOnTrack.h
M_PI
#define M_PI
Definition: ActiveFraction.h:11
Trk::RIO_OnTrack
Definition: RIO_OnTrack.h:70
Muon::MdtDriftCircleOnTrack::detectorElement
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
Definition: MdtDriftCircleOnTrack.h:268
Muon::CompetingMuonClustersOnTrack
Definition: CompetingMuonClustersOnTrack.h:54
MdtDriftCircleOnTrack.h
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
x
#define x
Trk::LocalDirection::angleYZ
double angleYZ() const
access method for angle of local YZ projection
Definition: LocalDirection.h:106
Muon::MuonSegmentPairMatchingTool::m_edmHelperSvc
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
EDM Helper tool.
Definition: MuonSegmentPairMatchingTool.h:44
Muon::MuonSegmentPairMatchingTool::initialize
StatusCode initialize()
AlgTool initilize.
Definition: MuonSegmentPairMatchingTool.cxx:46
MuonGM::MdtReadoutElement
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:50
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
MuonGM::MdtReadoutElement::getActiveTubeLength
double getActiveTubeLength(const int tubeLayer, const int tube) const
Muon::MuonSegment::localDirection
const Trk::LocalDirection & localDirection() const
local direction
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:169
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::Segment::containedMeasurements
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
Definition: TrkEvent/TrkSegment/TrkSegment/Segment.h:166
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
Trk::LocalDirection
represents the three-dimensional global direction with respect to a planar surface frame.
Definition: LocalDirection.h:81
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
IMuonEDMHelperSvc.h
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:191
Muon::MuonStationIndex::StIndexMax
@ StIndexMax
Definition: MuonStationIndex.h:27
Muon::MdtDriftCircleOnTrack
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Definition: MdtDriftCircleOnTrack.h:37
Trk::StraightLineSurface::localToGlobal
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const override final
Specified for StraightLineSurface: LocalToGlobal method without dynamic memory allocation.
Definition: StraightLineSurface.cxx:139
Muon::IMuonSegmentPairMatchingTool::SegmentMatchResult
Definition: IMuonSegmentPairMatchingTool.h:21
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::MdtDriftCircleOnTrack::associatedSurface
virtual const Trk::StraightLineSurface & associatedSurface() const override final
Returns the surface on which this measurement was taken.
Definition: MdtDriftCircleOnTrack.h:271
Trk::RIO_OnTrack::identify
virtual Identifier identify() const final
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:155
MuonSegment.h
Muon::MuonStationIndex::StIndex
StIndex
enum to classify the different station layers in the muon spectrometer
Definition: MuonStationIndex.h:23
Trk::phi
@ phi
Definition: ParamDefs.h:81
Muon::MuonSegment::globalPosition
virtual const Amg::Vector3D & globalPosition() const override final
global position
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:157
LocalDirection.h
Muon::MuonSegment
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:45
MuonSegmentPairMatchingTool.h
AthAlgTool
Definition: AthAlgTool.h:26
Muon::MuonSegmentPairMatchingTool::MuonSegmentPairMatchingTool
MuonSegmentPairMatchingTool(const std::string &, const std::string &, const IInterface *)
constructor
Definition: MuonSegmentPairMatchingTool.cxx:38
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
calibdata.tube
tube
Definition: calibdata.py:31
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
Muon::MuonSegment::globalDirection
const Amg::Vector3D & globalDirection() const
global direction
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:163