ATLAS Offline Software
Loading...
Searching...
No Matches
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
15namespace {
16// limit angle difference to -pi < x <= pi
17inline double
18limit_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
25inline double
26robust_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
36namespace Muon {
37
38MuonSegmentPairMatchingTool::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
45StatusCode
47{
48 ATH_CHECK(AthAlgTool::initialize());
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 using namespace MuonStationIndex;
62 // get identifiers
63 // and the detector region from identifier
64 Identifier chid1 = m_edmHelperSvc->chamberId(seg1);
65 StIndex station1 = m_idHelperSvc->stationIndex(chid1);
66
67 Identifier chid2 = m_edmHelperSvc->chamberId(seg2);
68 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 == StIndex::StUnknown) return result;
76 if (station2 == StIndex::StUnknown) return result;
77 if (station1 >= StIndex::StIndexMax) return result;
78 if (station2 >= StIndex::StIndexMax) return result;
79
80 // Here order matters, so sort segment by order a= inner, b= outer
81 // StIndex::StIndex station_a = station1;
82 // StIndex::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
298std::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
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define x
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
double getActiveTubeLength(const int tubeLayer, const int tube) const
Class for competing MuonClusters, it extends the Trk::CompetingRIOsOnTrack base class.
const std::vector< const MuonClusterOnTrack * > & containedROTs() const
returns the vector of SCT_ClusterOnTrack objects .
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
virtual const Trk::StraightLineSurface & associatedSurface() const override final
Returns the surface on which this measurement was taken.
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
std::pair< Amg::Vector3D, Amg::Vector3D > getShortestTubePos(const Muon::MuonSegment &seg) const
MuonSegmentPairMatchingTool(const std::string &, const std::string &, const IInterface *)
constructor
PublicToolHandle< MuonEDMPrinterTool > m_printer
EDM printer tool.
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
EDM Helper tool.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SegmentMatchResult matchResult(const MuonSegment &seg1, const MuonSegment &seg2) const
performance match and return result
This is the common class for 3D segments used in the muon spectrometer.
virtual const Amg::Vector3D & globalPosition() const override final
global position
virtual const Trk::PlaneSurface & associatedSurface() const override final
returns the surface for the local to global transformation
represents the three-dimensional global direction with respect to a planar surface frame.
double angleYZ() const
access method for angle of local YZ projection
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
void globalToLocalDirection(const Amg::Vector3D &glodir, Trk::LocalDirection &locdir) const
This method transforms the global direction to a local direction wrt the plane.
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
Definition RIO_OnTrack.h:70
Identifier identify() const
return the identifier -extends MeasurementBase
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
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.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
StIndex
enum to classify the different station layers in the muon spectrometer
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
@ locX
Definition ParamDefs.h:37
@ phi
Definition ParamDefs.h:75