ATLAS Offline Software
Loading...
Searching...
No Matches
MuonHoughMathUtils.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 <cfloat>
8
9#include <cassert>
10#include <iostream>
11#include <sstream>
12
14#include "CxxUtils/sincos.h"
15#include "GaudiKernel/MsgStream.h"
18
19int MuonHoughMathUtils::sgn(double d) { return d >= 0 ? 1 : -1; }
20
21int MuonHoughMathUtils::step(double d, double x0) {
22 if (d == x0) {
23 MsgStream log(Athena::getMessageSvc(), "MuonHoughMathUtils::step");
24 if (log.level() <= MSG::WARNING) log << MSG::WARNING << "WARNING: Possible mistake in Step function" << endmsg;
25 }
26 if (d <= x0) { return 0; }
27 if (d > x0) { return 1; }
28 return -1;
29}
30
32 double x0, double y0, double r0,
33 double phi) // distance from (x0,y0) to the line (r0,phi) , phi in [-Pi,Pi] ,different phi than in calculateangle() (==angle(2))
34{
35 CxxUtils::sincos scphi(phi);
36 double distance = scphi.apply(x0, -y0) - r0;
37 return distance;
38}
39
40double MuonHoughMathUtils::distanceToLine(double x0, double y0, double r0, double phi) {
41 return std::abs(signedDistanceToLine(x0, y0, r0, phi));
42}
43
44double MuonHoughMathUtils::incrementTillAbove0(double x, double inc, double zero) {
45 while (x > inc + zero) { x -= inc; }
46 while (x < zero) { x += inc; }
47 return x;
48}
49
51
53
55
57
59 std::string s;
60 std::stringstream ss;
61 ss << i;
62 ss >> s;
63
64 return s;
65}
66
67double MuonHoughMathUtils::distanceToLine2D(double x0, double y0, double r0, double phi)
68 // distance from (x0,y0) to line (r,phi) // from mathworld.wolfram.com/Point-LineDistance2-Dimensional.html // better to use
69 // distancetoline()
70{
71 // need two points on line:
72
73 CxxUtils::sincos scphi(phi);
74
75 double x1 = -r0 * scphi.sn; // point closest to origin
76 double y1 = r0 * scphi.cs;
77
78 Amg::Vector3D v{x1 - x0, y1 - y0, 0}; // (p1 - p0)
79
80 Amg::Vector3D r{x1, y1, 0}; // vector perpendicular to line
81 double distance = r.dot(v) / r.mag();
82
83 return distance;
84}
85
87 const Amg::Vector3D& point, const Amg::Vector3D& l_trans, double phi,
88 double theta) // from wolfram: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
89{
90 Amg::Vector3D x1 = l_trans - point; // x1-x0
91
92 CxxUtils::sincos scphi(phi);
93 CxxUtils::sincos sctheta(theta);
94
96 const Amg::Vector3D dir{scphi.cs * sctheta.sn, scphi.sn * sctheta.sn, sctheta.cs};
97
98 // sqrt(x3^2) == 1; !
99
100 double distance;
101 const Amg::Vector3D x4 = dir.cross(x1);
102
103 distance = x4.mag();
104
105 return distance;
106}
107
108double MuonHoughMathUtils::distanceOfLineToOrigin2D(double a, double b) { return std::abs(b / (std::sqrt(a * a + 1))); }
109
111 CxxUtils::sincos scphi(phi);
112 return scphi.apply(x, -y);
113}
114
116 const Amg::Vector3D& vec, double phi, double theta) // actually this is the 3d-point closest to origin in xy-plane
117{
119
120 CxxUtils::sincos scphi(phi);
121
122 double x0 = r0 * scphi.sn;
123 double y0 = -r0 * scphi.cs;
124
125 const double d_x = vec[Amg::x] - x0;
126 const double d_y = vec[Amg::y] - y0;
127 double radius = std::hypot(d_x, d_y);
128
129 if (std::abs(d_y - scphi.sn * radius) > std::abs(d_y + scphi.cs * radius)) // also possible for x
130 {
131 radius = -radius;
132 }
133
134 double z0 = vec[Amg::z] - radius / std::tan(theta);
135
136 return {x0, y0, z0};
137}
138
140 const Amg::Vector3D& line_trans, double phi,
141 double theta) // from wolfram: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
142{
143 // origin:
144 static const Amg::Vector3D origin{0., 0., 0.};
145
146 const Amg::Vector3D x1 = line_trans - origin;
147
148 CxxUtils::sincos scphi(phi);
149 CxxUtils::sincos sctheta(theta);
150 const Amg::Vector3D dir{scphi.cs * sctheta.sn, scphi.sn * sctheta.sn, sctheta.cs};
151
152 double time = 0;
153 double x5 = 0;
154 x5 = x1.dot(dir);
155 time = -x5;
156
157 Amg::Vector3D short_point = x1 + time * dir;
158 return short_point;
159}
160
161bool MuonHoughMathUtils::lineThroughCylinder(const Amg::Vector3D& line_trans, double phi, double theta, double r_cyl, double z_cyl) {
162 // if there is one, then track will be split
163 assert(r_cyl >= 0);
164
165 CxxUtils::sincos scphi(phi);
166 CxxUtils::sincos sctheta(theta);
167
168 // 1 -- check if there is an intersection at z0=+-c0
169 double p_1 = line_trans[Amg::z] - z_cyl;
170 double p_2 = line_trans[Amg::z] + z_cyl;
171 double tantheta = sctheta.sn / sctheta.cs;
172
173 double x_1 = line_trans[Amg::x] - p_1 * scphi.cs * tantheta;
174 double y_1 = line_trans[Amg::y] - p_1 * scphi.sn * tantheta;
175 double r_1 = std::hypot(x_1, y_1);
176 if (r_1 < r_cyl) { return true; }
177
178 double x_2 = line_trans[Amg::x] - p_2 * scphi.cs * tantheta;
179 double y_2 = line_trans[Amg::y] - p_2 * scphi.sn * tantheta;
180 double r_2 = std::hypot(x_2, y_2);
181 if (r_2 < r_cyl) { return true; }
182
183 // 2 -- check if there is an intersection with the circle x^2 + y^2 = r_cyl^2 and the line y=px+q, p = tan(phi), q = y_0 - x_0 tan(phi)
184 // <--> r_cyl^2 = (px+q)^2 + x^2
185 double r_0 = scphi.apply(-line_trans[Amg::x], line_trans[Amg::y]);
186
187 if (std::abs(r_0) > r_cyl) return false;
188
189 // 3 -- check if the intersection is cylinder: for -z_cyl<z<z_cyl
190 double s_1 = -scphi.sn * r_0;
191 double s_2 = scphi.cs * std::sqrt(r_cyl * r_cyl - r_0 * r_0);
192
193 x_1 = s_1 + s_2;
194
195 double inv_angle = 1 / (scphi.cs * tantheta);
196
197 double z_1 = line_trans[Amg::z] + (x_1 - line_trans[Amg::x]) * inv_angle;
198
199 if (std::abs(z_1) < z_cyl) return true;
200
201 x_2 = s_1 - s_2;
202 double z_2 = line_trans[Amg::z] + (x_2 - line_trans[Amg::x]) * inv_angle;
203
204 return std::abs(z_2) < z_cyl;
205}
206
207double MuonHoughMathUtils::signedDistanceCurvedToHit(double z0, double theta, double invcurvature, const Amg::Vector3D& hit) {
208 double hitr = hit.perp();
209
210 CxxUtils::sincos sctheta(theta);
211
212 double sdistance = FLT_MAX;
213 // if angle rotation larger than Pi/2 then return large distance (formulas don't work for flip in z!)
214 if (sctheta.apply(hitr, hit[Amg::z]) < 0) return sdistance; // hitr*sctheta.sn + hitz*sctheta.cs < 0
215
216 const int sign = hit[Amg::z] < 0 ? -1 : 1;
217
218 if (std::abs(hitr / hit[Amg::z]) > MuonHough::tan_barrel) {
219 // Barrel Extrapolation
220 if (std::abs(sctheta.sn) > 1e-7) {
221 double diffr = hitr - MuonHough::radius_cylinder;
222 double zext = z0 + (hitr * sctheta.cs + diffr * diffr * invcurvature) / sctheta.sn;
223 sdistance = (zext - hit[Amg::z]);
224 }
225
226 } else {
227 if (std::abs(sctheta.sn) > 1e-7) {
228 double rext = 0.;
229 if (std::abs(hit[Amg::z]) < MuonHough::z_end) {
230 // Forward in Toroid
231 double diffz = hit[Amg::z] - sign * MuonHough::z_cylinder;
232 rext = ((hit[Amg::z] - z0) * sctheta.sn - diffz * diffz * invcurvature) / sctheta.cs;
233
234 } else {
235 // Forward OutSide EC Toroid
236 rext = ((hit[Amg::z] - z0) * sctheta.sn +
238 sctheta.cs;
239 }
240 sdistance = (rext - hitr);
241 }
242 }
243 return sdistance;
244}
245
246double MuonHoughMathUtils::thetaForCurvedHit(double invcurvature, MuonHoughHit* hit) {
247 double ratio = hit->getMagneticTrackRatio() * invcurvature;
248 if (std::abs(ratio) < 1.)
249 return hit->getTheta() + std::asin(ratio);
250 else
251 return -1;
252}
253
254void MuonHoughMathUtils::thetasForCurvedHit(double ratio, MuonHoughHit* hit, double& theta1, double& theta2) {
256
257 if (std::abs(ratio) < 1.) {
258 double asin_ratio = std::asin(ratio);
259 theta1 = hit->getTheta() + asin_ratio;
260 theta2 = hit->getTheta() - asin_ratio;
261 }
262}
263
265 Amg::Vector3D& roadpose, Amg::Vector3D& roaddire) {
272
273 // m_log<< MSG::VERBOSE << "Extrapolate the road to the segment (hit)" <<endmsg;
274
275 const double theta = roadmom.theta();
276 const double phi = roadmom.phi();
277
278 CxxUtils::sincos scphi(phi);
279 CxxUtils::sincos sctheta(theta);
280
281 double tantheta = sctheta.sn / sctheta.cs;
282
283 double r0 = scphi.apply(roadpos.x(), -roadpos.y());
284 double charge = 1.;
285 if (r0 < 0) charge = -1.;
286 double invcurvature = charge / roadmom.mag();
287 // No momentum estimate
288 if (roadmom.mag() < 2) invcurvature = 0.;
289
290 double posr = std::sqrt(pos.x() * pos.x() + pos.y() * pos.y());
291 double thetan = theta;
292
293 int sign = 1;
294 if (pos.z() < 0) sign = -1;
295
296 double xe = pos.x();
297 double ye = pos.y();
298 double ze = pos.z();
299 double rotationangle = 0.;
300
301 if (std::abs(posr / pos.z()) > MuonHough::tan_barrel) {
302 // Barrel Extrapolation
303 if ((posr * posr - r0 * r0) > 0) {
304 double lenr = std::sqrt(posr * posr - r0 * r0);
305 double len = posr - fabs(r0);
306 double diffr = posr - MuonHough::radius_cylinder;
307 rotationangle = diffr * invcurvature / sctheta.sn;
308 xe = roadpos.x() + lenr * scphi.cs;
309 ye = roadpos.y() + lenr * scphi.sn;
310 ze = roadpos.z() + len / tantheta + diffr * rotationangle;
311 thetan = std::atan2(1., 1 / tantheta + 2 * rotationangle);
312 }
313 } else {
314 double lext = 0., rotationangle = 0.;
315 if (std::abs(pos.z()) < MuonHough::z_end) {
316 // Forward in Toroid
317 double diffz = pos.z() - sign * MuonHough::z_cylinder;
318 rotationangle = diffz * invcurvature / sctheta.cs;
319 lext = (pos.z() - roadpos.z()) * tantheta - diffz * rotationangle;
320 } else {
321 // Forward OutSide EC Toroid
322 double effcurv = invcurvature / sctheta.cs;
323 rotationangle = sign * (MuonHough::z_end - MuonHough::z_cylinder) * effcurv;
324 lext = (pos.z() - roadpos.z()) * tantheta +
326 }
327 xe = roadpos.x() + lext * scphi.cs;
328 ye = roadpos.y() + lext * scphi.sn;
329 double dx = tantheta - 2 * rotationangle;
330 if (dx != 0) thetan = std::atan2(1., 1 / dx);
331 }
332
333 // In case direction theta is rotated for low momenta: flip direction vector
334 CxxUtils::sincos scthetan(thetan);
335 if (sctheta.cs * scthetan.cs + sctheta.sn * scthetan.sn < 0) {
336 roaddire = Amg::Vector3D(scthetan.sn * scphi.cs, scthetan.sn * scphi.sn, -scthetan.cs);
337 } else {
338 roaddire = Amg::Vector3D(scthetan.sn * scphi.cs, scthetan.sn * scphi.sn, scthetan.cs);
339 }
340 roadpose = Amg::Vector3D(xe, ye, ze);
341}
#define M_PI
Scalar phi() const
phi method
Scalar theta() const
theta method
#define endmsg
double charge(const T &p)
Definition AtlasPID.h:997
std::vector< size_t > vec
static Double_t a
static Double_t ss
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
int sign(int a)
#define y
#define x
double getMagneticTrackRatio() const
ratio of the tracklength of the particle to which hit might belong would have traversed in magnetic f...
double getTheta() const
returns theta
static std::string intToString(int i)
converts integer to string
static int step(double d, double x0=0)
step function at place x0
static double incrementTillAbove0(double x, double inc, double zero=0)
increments x with inc till above x
static double distanceOfLineToOrigin2D(double a, double b)
distance of line y = ax + b to origin
static double angleFrom0ToPi(double angle)
computes angle in rad between 0 and Pi
static void thetasForCurvedHit(double ratio, MuonHoughHit *hit, double &theta1, double &theta2)
calculates theta at (x,y,z) for curved track model, for positive and negative curvature
static double angleFrom0To360(double angle)
computes angle in degrees between 0 and 360
static bool lineThroughCylinder(const Amg::Vector3D &vec, double phi, double theta, double r_0, double z_0)
calculates if line (x,y,z,phi,theta) crosses cylinder (r_0,z_0) around origin
static double signedDistanceOfLineToOrigin2D(double x, double y, double phi)
signed distance of line with point (x,y) and angle phi to origin
static double angleFromMinusPiToPi(double angle)
computes angle in rad between -Pi and Pi
static Amg::Vector3D shortestPointOfLineToOrigin3D(const Amg::Vector3D &vec, double phi, double theta)
calculates the 3d-point closest to origin in xy-plane
static double thetaForCurvedHit(double invcurvature, MuonHoughHit *hit)
calculates theta at (x,y,z) for curved track model
MuonHoughMathUtils()
default constructor
static Amg::Vector3D shortestPointOfLineToOrigin(const Amg::Vector3D &vec, double phi, double theta)
calculates the 3d-point closest to origin
static int sgn(double d)
sign (-1 or 1) of a double
static double distanceToLine2D(double x0, double y0, double r, double phi)
distance from (x0,y0) to line (r,phi)
static double signedDistanceCurvedToHit(double z0, double theta, double invcurvature, const Amg::Vector3D &hit)
calculates distance of point (x,y,z) to curved track with z0, theta and invcurvature for curved track...
static double distanceToLine(double x0, double y0, double r0, double phi)
distance from (x0,y0) to the line (r0,phi), phi in rad
static double angleFrom0To180(double angle)
computes angle in degrees between 0 and 180
static double signedDistanceToLine(double x0, double y0, double r0, double phi)
distance from (x0,y0) to the line (r0,phi), phi in rad
static void extrapolateCurvedRoad(const Amg::Vector3D &roadpos, const Amg::Vector3D &roadmom, const Amg::Vector3D &pos, Amg::Vector3D &roadpose, Amg::Vector3D &roaddire)
extrapolates road to global position
static double distanceToLine3D(const Amg::Vector3D &point, const Amg::Vector3D &l_trans, double phi, double theta)
distance from (x0,y0,z0) to line (x,y,z,phi,theta)
void zero(TH2 *h)
zero the contents of a 2d histogram
singleton-like access to IMessageSvc via open function and helper
int r
Definition globals.cxx:22
Eigen::Matrix< double, 3, 1 > Vector3D
IMessageSvc * getMessageSvc(bool quiet=false)
constexpr double tan_barrel
relation for transition between endcap and barrel 11.43 m (r) / 14m (z)
constexpr double radius_cylinder
radius of cylinder
constexpr double z_cylinder
length of cylinder
constexpr double z_magnetic_range_squared
range where hit is curved in endcap region ('squared')
constexpr double z_end
z value whereafter no magnetic field / curvature
constexpr double z_magnetic_range
range where hit is curved in endcap region
Helper to simultaneously calculate sin and cos of the same angle.
Helper to simultaneously calculate sin and cos of the same angle.
Definition sincos.h:39
double apply(double a, double b) const
Definition sincos.h:57