11 const float Helix::TWO_PI =
static_cast<float>(2. * std::acos(-1.0));
12 const float Helix::HALF_PI =
static_cast<float>(0.5 * std::acos(-1.0));
16 Helix::Helix(
const float phi0,
const float d0,
const float x0,
const float omega,
const float tanLambda,
const float bField)
17 : m_referencePoint(0.
f, 0.
f, 0.
f),
18 m_momentum(0.
f, 0.
f, 0.
f),
23 m_tanLambda(tanLambda)
25 if ((bField < std::numeric_limits<float>::epsilon()) || (std::fabs(omega) < std::numeric_limits<float>::epsilon()))
27 std::cout <<
"Helix, invalid parameter: bField " << bField <<
", omega " << omega <<
std::endl;
28 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
54 const double pz(momentum.GetZ()),
py(momentum.GetY());
55 const double pzy(std::sqrt(
pz *
pz +
py *
py));
57 if ((bField < std::numeric_limits<float>::epsilon()) || (std::fabs(pzy) < std::numeric_limits<float>::epsilon()))
59 std::cout <<
"Helix, invalid parameter: bField " << bField <<
", pzy " << pzy <<
std::endl;
60 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
63 const double radius(pzy / (
FCT * bField));
64 m_pzy =
static_cast<float>(pzy);
65 m_radius =
static_cast<float>(radius);
71 const double z(position.GetZ()),
y(position.GetY());
80 d0 =
static_cast<double>(charge) * radius - static_cast<double>(std::sqrt(zCentre * zCentre + yCentre * yCentre));
84 d0 =
static_cast<double>(charge) * radius + static_cast<double>(std::sqrt(zCentre * zCentre + yCentre * yCentre));
86 m_d0 =
static_cast<float>(d0);
88 m_phiRefPoint =
static_cast<float>(std::atan2(
y - yCentre,
z - zCentre));
89 m_phiAtPCA =
static_cast<float>(std::atan2(-yCentre, -zCentre));
107 if (zCircles >= std::numeric_limits<float>::epsilon())
109 n1 =
static_cast<int>(zCircles);
114 n1 =
static_cast<int>(zCircles) - 1;
118 const int nCircles((std::fabs(n1 - zCircles) < std::fabs(n2 - zCircles) ? n1 : n2));
119 m_x0 = position.GetX() +
m_radius * m_tanLambda * charge * (deltaPhi +
TWO_PI * nCircles);
124 pandora::StatusCode
Helix::GetPointInZY(
const float z0,
const float y0,
const float az,
const float ay,
const pandora::CartesianVector &referencePoint,
125 pandora::CartesianVector &intersectionPoint,
float &genericTime)
const 127 const float AA(std::sqrt(az * az + ay * ay));
130 return pandora::STATUS_CODE_FAILURE;
135 const float DET(BB * BB - CC);
138 return pandora::STATUS_CODE_NOT_FOUND;
140 float tt1(-BB + std::sqrt(DET));
141 float tt2(-BB - std::sqrt(DET));
143 const float zz1(z0 + tt1 * az);
144 const float yy1(y0 + tt1 * ay);
145 const float zz2(z0 + tt2 * az);
146 const float yy2(y0 + tt2 * ay);
150 const float phi0(std::atan2(referencePoint.GetY() -
m_yCentre, referencePoint.GetZ() -
m_zCentre));
152 float dphi1(phi1 - phi0);
153 float dphi2(phi2 - phi0);
177 if ((tt1 < 0.) || (tt2 < 0.))
178 std::cout <<
"Helix:: GetPointInXY, warning - negative generic time, tt1 " << tt1 <<
", tt2 " << tt2 <<
std::endl;
183 intersectionPoint.SetValues(referencePoint.GetX() + genericTime *
m_momentum.GetX(), yy1, zz1);
188 intersectionPoint.SetValues(referencePoint.GetX() + genericTime *
m_momentum.GetX(), yy2, zz2);
191 return pandora::STATUS_CODE_SUCCESS;
196 pandora::StatusCode
Helix::GetPointInX(
const float xPlane,
const pandora::CartesianVector &referencePoint, pandora::CartesianVector &intersectionPoint,
197 float &genericTime)
const 199 if (std::fabs(
m_momentum.GetX()) < std::numeric_limits<float>::epsilon())
200 return pandora::STATUS_CODE_NOT_FOUND;
202 genericTime = (xPlane - referencePoint.GetX()) /
m_momentum.GetX();
204 const float phi0(std::atan2(referencePoint.GetY() -
m_yCentre, referencePoint.GetZ() -
m_zCentre));
209 return pandora::STATUS_CODE_SUCCESS;
214 pandora::StatusCode
Helix::GetPointOnCircle(
const float radius,
const pandora::CartesianVector &referencePoint, pandora::CartesianVector &intersectionPoint,
215 float &genericTime)
const 219 if ( ((distCenterToIP +
m_radius) < radius) || ((
m_radius + radius) < distCenterToIP) )
220 return pandora::STATUS_CODE_NOT_FOUND;
222 const float phiCentre(std::atan2(m_yCentre,
m_zCentre));
224 float phiStar(radius * radius + distCenterToIP * distCenterToIP -
m_radius *
m_radius);
225 phiStar = 0.5f * phiStar /
std::max(1.
e-20
f, radius * distCenterToIP);
228 phiStar = 0.9999999f;
231 phiStar = -0.9999999f;
233 phiStar = std::acos(phiStar);
235 const float zz1(radius * std::cos(phiCentre + phiStar));
236 const float yy1(radius * std::sin(phiCentre + phiStar));
238 const float zz2(radius * std::cos(phiCentre-phiStar));
239 const float yy2(radius * std::sin(phiCentre-phiStar));
241 const float phi1(std::atan2(yy1 - m_yCentre, zz1 -
m_zCentre));
242 const float phi2(std::atan2(yy2 - m_yCentre, zz2 -
m_zCentre));
243 const float phi0(std::atan2(referencePoint.GetY() -
m_yCentre, referencePoint.GetZ() -
m_zCentre));
245 float dphi1(phi1 - phi0);
246 float dphi2(phi2 - phi0);
270 if ((tt1 < 0.) || (tt2 < 0.))
271 std::cout <<
"Helix:: GetPointOnCircle, warning - negative generic time, tt1 " << tt1 <<
", tt2 " << tt2 <<
std::endl;
277 intersectionPoint.SetValues(referencePoint.GetX() + genericTime *
m_momentum.GetX(), yy1, zz1);
282 intersectionPoint.SetValues(referencePoint.GetX() + genericTime *
m_momentum.GetX(), yy2, zz2);
285 return pandora::STATUS_CODE_SUCCESS;
301 if (zCircles >= std::numeric_limits<float>::epsilon())
303 n1 =
static_cast<int>(zCircles);
308 n1 =
static_cast<int>(zCircles) - 1;
312 nCircles = ((std::fabs(n1 - zCircles) < std::fabs(n2 - zCircles) ? n1 : n2));
315 const float dPhi(
TWO_PI * (static_cast<float>(nCircles)) + phi - phi0);
318 const float distZ(std::fabs(
m_zCentre - point.GetZ()));
319 const float distY(std::fabs(
m_yCentre - point.GetY()));
320 const float distX(std::fabs(xOnHelix - point.GetX()));
322 float distZY(std::sqrt(distZ * distZ + distY * distY));
323 distZY = std::fabs(distZY - m_radius);
325 distance.SetValues(distX, distZY, std::sqrt(distZY * distZY + distZ * distZ));
336 return pandora::STATUS_CODE_SUCCESS;
342 float &helixDistance)
const 345 return pandora::STATUS_CODE_INVALID_PARAMETER;
356 const float distance(std::sqrt((z01-z02) * (z01-z02) + (y01-y02) * (y01-y02)));
358 bool singlePoint(
true);
359 float phi1(0.), phi2(0.);
361 if (rad1 + rad2 < distance)
363 phi1 = std::atan2(y02 - y01, z02 - z01);
364 phi2 = std::atan2(y01 - y02, z01 - z02);
366 else if (distance + rad2 < rad1)
368 phi1 = std::atan2(y02 - y01, z02 - z01);
371 else if (distance + rad1 < rad2)
373 phi1 = std::atan2(y01 - y02, z01 - z02);
378 if ((std::fabs(distance) < std::numeric_limits<float>::epsilon()) || (std::fabs(rad2) < std::numeric_limits<float>::epsilon()))
379 return pandora::STATUS_CODE_FAILURE;
382 float cosAlpha = 0.5f * (distance * distance + rad2 * rad2 - rad1 * rad1) / (distance * rad2);
383 float alpha = std::acos(cosAlpha);
384 float phi0 = std::atan2(y01 - y02, z01 - z02);
392 pandora::CartesianVector position1(0.
f, 0.
f, 0.
f), position2(0.
f, 0.
f, 0.
f);
396 const float zSect1(z01 + rad1 * std::cos(phi1));
397 const float ySect1(y01 + rad1 * std::sin(phi1));
398 const float zSect2(z02 + rad2 * std::cos(phi2));
399 const float ySect2(y02 + rad2 * std::sin(phi2));
400 const float r1(std::sqrt(zSect1 * zSect1 + ySect1 * ySect1));
401 const float r2(std::sqrt(zSect2 * zSect2 + ySect2 * ySect2));
403 PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->
GetPointOnCircle(r1, referencePoint1, position1));
404 PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, pHelix->
GetPointOnCircle(r2, referencePoint2, position2));
408 const float zSect1(z02 + rad2*std::cos(phi1));
409 const float ySect1(y02 + rad2*std::sin(phi1));
410 const float zSect2(z02 + rad2*std::cos(phi2));
411 const float ySect2(y02 + rad2*std::sin(phi2));
413 const float phiI2(std::atan2(referencePoint2.GetY() - y02, referencePoint2.GetZ() - z02));
414 const float phiF21(std::atan2(ySect1 - y02, zSect1 - z02));
415 const float phiF22(std::atan2(ySect2 - y02, zSect2 - z02));
416 const float charge2(pHelix->
GetCharge());
418 float deltaPhi21(phiF21 - phiI2);
419 float deltaPhi22(phiF22 - phiI2);
421 if (deltaPhi21 < 0 && charge2 < 0)
425 else if (deltaPhi21 > 0 && charge2 > 0)
430 if (deltaPhi22 < 0 && charge2 < 0)
434 else if (deltaPhi22 > 0 && charge2 > 0)
439 const float pzy2(pHelix->
GetPzy());
440 const float genericTime21(-charge2 * deltaPhi21 * rad2 / pzy2);
441 const float genericTime22(-charge2 * deltaPhi22 * rad2 / pzy2);
444 const float X21(referencePoint2.GetX() + genericTime21 * px2);
445 const float X22(referencePoint2.GetX() + genericTime22 * px2);
447 const pandora::CartesianVector temp21(X21, ySect1, zSect1);
448 const pandora::CartesianVector temp22(X22, ySect2, zSect2);
450 const float phiI1(std::atan2(referencePoint1.GetY() - y01, referencePoint1.GetZ() - z01));
451 const float phiF11(std::atan2(ySect1-y01,zSect1-z01));
452 const float phiF12(std::atan2(ySect2-y01,zSect2-z01));
455 float deltaPhi11(phiF11 - phiI1);
456 float deltaPhi12(phiF12 - phiI1);
458 if (deltaPhi11 < 0 && charge1 < 0)
462 else if (deltaPhi11 > 0 && charge1 > 0)
467 if (deltaPhi12 < 0 && charge1 < 0)
471 else if (deltaPhi12 > 0 && charge1 > 0)
476 const float pzy1(
m_pzy);
477 const float genericTime11(-charge1 * deltaPhi11 * rad1 / pzy1);
478 const float genericTime12(-charge1 * deltaPhi12 * rad1 / pzy1);
481 const float X11(referencePoint1.GetX() + genericTime11 * px1);
482 const float X12(referencePoint1.GetX() + genericTime12 * px1);
484 const pandora::CartesianVector temp11(X11, ySect1, zSect1);
485 const pandora::CartesianVector temp12(X12, ySect2, zSect2);
487 const float dist1((temp11 - temp21).GetMagnitudeSquared());
488 const float dist2((temp12 - temp22).GetMagnitudeSquared());
505 helixDistance = (position1 - position2).GetMagnitude();
506 positionOfClosestApproach = (position1 + position2) * 0.5;
507 v0momentum = momentum1 + momentum2;
509 return pandora::STATUS_CODE_SUCCESS;
523 return pandora::CartesianVector(
m_momentum.GetX(),
m_pzy * std::sin(phi),
m_pzy * std::cos(phi));
pandora::CartesianVector m_momentum
The momentum vector at reference point.
pandora::StatusCode GetPointInX(const float xPlane, const pandora::CartesianVector &referencePoint, pandora::CartesianVector &intersectionPoint) const
Get helix intersection point with a plane perpendicular to x axis.
float m_zCentre
The circle centre z coordinate.
float m_phiMomRefPoint
Phi of Momentum vector at reference point.
pandora::StatusCode GetDistanceToHelix(const Helix *const pHelix, pandora::CartesianVector &positionOfClosestApproach, pandora::CartesianVector &v0momentum, float &helixDistance) const
Get distance between two helices.
float m_yCentre
The circle centre y coordinate.
float m_phi0
phi0 in canonical parameterization
float GetPzy() const
Get transverse momentum of the track.
float m_charge
The particle charge.
float m_radius
The radius of circle in ZY plane.
float m_pyAtPCA
Momentum y component at point of closest approach.
pandora::StatusCode GetPointOnCircle(const float radius, const pandora::CartesianVector &referencePoint, pandora::CartesianVector &intersectionPoint) const
Get coordinates of helix intersection with cylinder, aligned along z-axis.
const pandora::CartesianVector & GetMomentum() const
Get momentum of particle at the point of closest approach to IP.
static const float TWO_PI
pandora::CartesianVector m_referencePoint
The coordinates of the reference point.
float GetRadius() const
Get radius of circumference.
float m_x0
x0 in canonical parameterisation
const pandora::CartesianVector & GetReferencePoint() const
Get reference point of track.
float m_zAtPCA
z coordinate at point of closest approach
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
float m_pzy
The transverse momentum.
float GetYCentre() const
Get y coordinate of circumference.
static int max(int a, int b)
float m_pzAtPCA
Momentum z component at point of closest approach.
float GetCharge() const
Get charge.
pandora::CartesianVector GetExtrapolatedMomentum(const pandora::CartesianVector &position) const
float m_omega
signed curvature in canonical parameterisation
float GetZCentre() const
Get z coordinate of circumference.
pandora::StatusCode GetPointInZY(const float z0, const float y0, const float az, const float ay, const pandora::CartesianVector &referencePoint, pandora::CartesianVector &intersectionPoint) const
Get helix intersection point with a plane parallel to x axis. The plane is defined by two coordinates...
float m_tanLambda
tanLambda
float m_phiRefPoint
Phi w.r.t. (Z0, Y0) of circle at reference point.
float m_yAtPCA
y coordinate at point of closest approach
def momentum(x1, x2, x3, scale=1.)
static const float HALF_PI
float m_d0
d0 in canonical parameterisation
float m_phiAtPCA
Phi w.r.t. (Z0, Y0) of circle at point of closest approach.
pandora::StatusCode GetDistanceToPoint(const pandora::CartesianVector &point, pandora::CartesianVector &distance) const
Get distance of the closest approach of helix to an arbitrary point in space.
Helix(const float phi0, const float d0, const float x0, const float omega, const float tanlambda, const float bField)
Constructor using canonical (LEP-wise) parameterisation.
QTextStream & endl(QTextStream &s)