Belle II Software development
CDCTrajectory3D.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectory3D.h>
9
10#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectory2D.h>
11#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectorySZ.h>
12
13#include <tracking/trackingUtilities/eventdata/trajectories/CDCBFieldUtil.h>
14
15#include <cdc/topology/CDCWireTopology.h>
16
17#include <tracking/trackingUtilities/geometry/UncertainHelix.h>
18#include <tracking/trackingUtilities/geometry/Helix.h>
19#include <tracking/trackingUtilities/geometry/HelixParameters.h>
20#include <tracking/trackingUtilities/geometry/UncertainPerigeeCircle.h>
21#include <tracking/trackingUtilities/geometry/UncertainSZLine.h>
22#include <tracking/trackingUtilities/geometry/PerigeeCircle.h>
23
24#include <tracking/trackingUtilities/geometry/VectorUtil.h>
25
26#include <tracking/trackingUtilities/numerics/ESign.h>
27#include <tracking/trackingUtilities/numerics/Quadratic.h>
28
29#include <tracking/trackingUtilities/numerics/CovarianceMatrixUtil.h>
30#include <tracking/trackingUtilities/numerics/JacobianMatrixUtil.h>
31#include <tracking/trackingUtilities/numerics/TMatrixConversion.h>
32
33#include <genfit/TrackCand.h>
34
35#include <mdst/dataobjects/MCParticle.h>
36
37#include <framework/gearbox/Const.h>
38#include <framework/geometry/VectorUtil.h>
39
40#include <TMatrixDSym.h>
41
42#include <ostream>
43
44using namespace Belle2;
45using namespace CDC;
46using namespace TrackingUtilities;
47
49 const CDCTrajectorySZ& trajectorySZ)
50 : m_localHelix(trajectory2D.getLocalCircle(), trajectorySZ.getSZLine())
51 , m_flightTime(trajectory2D.getFlightTime())
52{
53 const auto& tmp = trajectory2D.getLocalOrigin();
54 m_localOrigin = ROOT::Math::XYZVector(tmp.X(), tmp.Y(), 0.0);
55}
56
58 : CDCTrajectory3D(trajectory2D, CDCTrajectorySZ::basicAssumption())
59{
60}
61
62CDCTrajectory3D::CDCTrajectory3D(const ROOT::Math::XYZVector& pos3D,
63 const double time,
64 const ROOT::Math::XYZVector& mom3D,
65 const double charge,
66 const double bZ)
67 : m_localOrigin(pos3D)
68 , m_localHelix(CDCBFieldUtil::absMom2DToCurvature(mom3D.Rho(), charge, bZ),
69 VectorUtil::unit(VectorUtil::getXYVector(mom3D)),
70 0.0,
71 (mom3D.Z() / mom3D.Rho()), // double cotTheta() const { return z() / Rho(); }
72 0.0)
73 , m_flightTime(time)
74{
75}
76
77CDCTrajectory3D::CDCTrajectory3D(const ROOT::Math::XYZVector& pos3D,
78 const double time,
79 const ROOT::Math::XYZVector& mom3D,
80 const double charge)
81 : CDCTrajectory3D(pos3D, time, mom3D, charge, CDCBFieldUtil::getBFieldZ(pos3D))
82{
83}
84
85CDCTrajectory3D::CDCTrajectory3D(const MCParticle& mcParticle, const double bZ)
86 : CDCTrajectory3D(ROOT::Math::XYZVector{mcParticle.getProductionVertex()},
87 mcParticle.getProductionTime(),
88 ROOT::Math::XYZVector{mcParticle.getMomentum()},
89 mcParticle.getCharge(),
90 bZ)
91{
92}
93
95 : CDCTrajectory3D(ROOT::Math::XYZVector{mcParticle.getProductionVertex()},
96 mcParticle.getProductionTime(),
97 ROOT::Math::XYZVector{mcParticle.getMomentum()},
98 mcParticle.getCharge())
99{
100}
101
102CDCTrajectory3D::CDCTrajectory3D(const genfit::TrackCand& gfTrackCand, const double bZ)
103 : CDCTrajectory3D(ROOT::Math::XYZVector{gfTrackCand.getPosSeed()},
104 gfTrackCand.getTimeSeed(),
105 ROOT::Math::XYZVector{gfTrackCand.getMomSeed()},
106 gfTrackCand.getChargeSeed(),
107 bZ)
108{
109 // Maybe push these out of this function:
110 // Indices of the cartesian coordinates
111 const int iX = 0;
112 const int iY = 1;
113 const int iZ = 2;
114 const int iPx = 3;
115 const int iPy = 4;
116 const int iPz = 5;
117
118 const TMatrixDSym& seedCov = gfTrackCand.getCovSeed();
119 CovarianceMatrix<6> cov6 = TMatrixConversion::fromTMatrix<6>(seedCov);
120
121 // 1. Rotate to a system where phi0 = 0
122 JacobianMatrix<6, 6> jacobianRot = JacobianMatrixUtil::zero<6, 6>();
123
124 const double px = gfTrackCand.getStateSeed()[iPx];
125 const double py = gfTrackCand.getStateSeed()[iPy];
126 const double pt = hypot2(px, py);
127
128 const double cosPhi0 = px / pt;
129 const double sinPhi0 = py / pt;
130
131 // Passive rotation matrix by phi0:
132 jacobianRot(iX, iX) = cosPhi0;
133 jacobianRot(iX, iY) = sinPhi0;
134 jacobianRot(iY, iX) = -sinPhi0;
135 jacobianRot(iY, iY) = cosPhi0;
136 jacobianRot(iZ, iZ) = 1.0;
137
138 jacobianRot(iPx, iPx) = cosPhi0;
139 jacobianRot(iPx, iPy) = sinPhi0;
140 jacobianRot(iPy, iPx) = -sinPhi0;
141 jacobianRot(iPy, iPy) = cosPhi0;
142 jacobianRot(iPz, iPz) = 1.0;
143
144 // Apply transformation inplace
145 CovarianceMatrixUtil::transport(jacobianRot, cov6);
146
147 // 2. Translate to perigee parameters
148 JacobianMatrix<5, 6> jacobianReduce = JacobianMatrixUtil::zero<5, 6>();
149
150 const double invPt = 1 / pt;
151 const double invPtSquared = invPt * invPt;
152 const double pz = gfTrackCand.getStateSeed()[iPz];
153 const double alpha = CDCBFieldUtil::getAlphaFromBField(bZ);
154 const double charge = gfTrackCand.getChargeSeed();
155
156 using namespace NHelixParameterIndices;
157 jacobianReduce(c_Curv, iPx) = charge * invPtSquared / alpha ;
158 jacobianReduce(c_Phi0, iPy) = invPt;
159 jacobianReduce(c_I, iY) = 1;
160 jacobianReduce(c_TanL, iPx) = - pz * invPtSquared;
161 jacobianReduce(c_TanL, iPz) = invPt;
162 jacobianReduce(c_Z0, iZ) = 1;
163 // Note the column corresponding to iX is completely zero as expectable.
164
165 CovarianceMatrix<5> cov5 = CovarianceMatrixUtil::transported(jacobianReduce, cov6);
166 const HelixCovariance& helixCovariance = cov5;
167
168 // The covariance should now be the correct 5x5 covariance matrix.
169 m_localHelix.setHelixCovariance(helixCovariance);
170}
171
172CDCTrajectory3D::CDCTrajectory3D(const genfit::TrackCand& gfTrackCand)
173 : CDCTrajectory3D(gfTrackCand, CDCBFieldUtil::getBFieldZ(ROOT::Math::XYZVector{gfTrackCand.getPosSeed()}))
174{
175}
176
177namespace {
178 CovarianceMatrix<6> calculateCovarianceMatrix(const UncertainHelix& localHelix,
179 const ROOT::Math::XYZVector& momentum,
180 const ESign charge,
181 const double bZ)
182 {
183 const double impactXY = localHelix->impactXY();
184 const ROOT::Math::XYVector& phi0Vec = localHelix->phi0Vec();
185
186 const double cosPhi0 = phi0Vec.x();
187 const double sinPhi0 = phi0Vec.y();
188
189 const double curvatureXY = localHelix->curvatureXY();
190 const double tanLambda = localHelix->tanLambda();
191
192 // 0. Define indices
193 // Maybe push these out of this function:
194 // Indices of the cartesian coordinates
195 const int iX = 0;
196 const int iY = 1;
197 const int iZ = 2;
198 const int iPx = 3;
199 const int iPy = 4;
200 const int iPz = 5;
201
202 CovarianceMatrix<5> cov5 = localHelix.helixCovariance();
203
204 // 1. Inflat the perigee covariance to a cartesian covariance where phi0 = 0 is assumed
205 // Jacobian matrix for the translation
206 JacobianMatrix<6, 5> jacobianInflate = JacobianMatrixUtil::zero<6, 5>();
207
208 const double alpha = CDCBFieldUtil::getAlphaFromBField(bZ);
209 const double chargeAlphaCurv = static_cast<double>(charge) * alpha * curvatureXY;
210 const double chargeAlphaCurv2 = static_cast<double>(charge) * alpha * std::pow(curvatureXY, 2);
211
212 const double invChargeAlphaCurv = 1.0 / chargeAlphaCurv;
213 const double invChargeAlphaCurv2 = 1.0 / chargeAlphaCurv2;
214
215 using namespace NHelixParameterIndices;
216 // Position
217 jacobianInflate(iX, c_Phi0) = -impactXY;
218 jacobianInflate(iY, c_I) = 1.0;
219 jacobianInflate(iZ, c_Z0) = 1.0;
220
221 // Momentum
222 if (bZ == 0) {
223 jacobianInflate(iPx, c_Curv) = 0;
224 jacobianInflate(iPy, c_Phi0) = momentum.Rho();
225 jacobianInflate(iPz, c_Curv) = 0;
226 jacobianInflate(iPz, c_TanL) = momentum.Rho();
227 } else {
228 jacobianInflate(iPx, c_Curv) = invChargeAlphaCurv2;
229 jacobianInflate(iPy, c_Phi0) = - invChargeAlphaCurv;
230 jacobianInflate(iPz, c_Curv) = tanLambda * invChargeAlphaCurv2;
231 jacobianInflate(iPz, c_TanL) = - invChargeAlphaCurv;
232 }
233
234 // Transform
235 CovarianceMatrix<6> cov6 = CovarianceMatrixUtil::transported(jacobianInflate, cov5);
236
238 JacobianMatrix<6, 6> jacobianRot = JacobianMatrixUtil::zero<6, 6>();
239
240 // Active rotation matrix by phi0:
241 jacobianRot(iX, iX) = cosPhi0;
242 jacobianRot(iX, iY) = -sinPhi0;
243 jacobianRot(iY, iX) = sinPhi0;
244 jacobianRot(iY, iY) = cosPhi0;
245 jacobianRot(iZ, iZ) = 1.0;
246
247 jacobianRot(iPx, iPx) = cosPhi0;
248 jacobianRot(iPx, iPy) = -sinPhi0;
249 jacobianRot(iPy, iPx) = sinPhi0;
250 jacobianRot(iPy, iPy) = cosPhi0;
251 jacobianRot(iPz, iPz) = 1.0;
252
253 // Apply transformation inplace
254 CovarianceMatrixUtil::transport(jacobianRot, cov6);
255
256 // 3. Forward the covariance matrix.
257 return cov6;
258 }
259}
260
261
262bool CDCTrajectory3D::fillInto(genfit::TrackCand& trackCand) const
263{
264 ROOT::Math::XYZVector position = getSupport();
265 return fillInto(trackCand, CDCBFieldUtil::getBFieldZ(position));
266}
267
268bool CDCTrajectory3D::fillInto(genfit::TrackCand& gfTrackCand, const double bZ) const
269{
270 // Set the start parameters
271 ROOT::Math::XYZVector position = getSupport();
272 ROOT::Math::XYZVector momentum = bZ == 0 ? getFlightDirection3DAtSupport() : getMom3DAtSupport(bZ);
273 ESign charge = getChargeSign();
274
275 // Do not propagate invalid fits, signal that the fit is invalid to the caller.
276 if (not ESignUtil::isValid(charge) or VectorUtil::hasNAN(momentum) or VectorUtil::hasNAN(position)) {
277 return false;
278 }
279
280 gfTrackCand.setPosMomSeed(XYZToTVector(position), XYZToTVector(momentum), charge);
281
282 const CovarianceMatrix<6> cov6 = calculateCovarianceMatrix(getLocalHelix(), momentum, charge, bZ);
283 TMatrixDSym covSeed = TMatrixConversion::toTMatrix(cov6);
284
285 gfTrackCand.setCovSeed(covSeed);
286
287 return true;
288}
289
290CovarianceMatrix<6> CDCTrajectory3D::getCartesianCovariance(double bZ) const
291{
292 // Set the start parameters
293 ROOT::Math::XYZVector momentum = bZ == 0 ? getFlightDirection3DAtSupport() : getMom3DAtSupport(bZ);
294 ESign charge = getChargeSign();
295 return calculateCovarianceMatrix(getLocalHelix(), momentum, charge, bZ);
296}
297
298bool CDCTrajectory3D::isCurler(double factor) const
299{
301 return getMaximalCylindricalR() < factor * topology.getOuterCylindricalR();
302}
303
305{
306 return CDCBFieldUtil::ccwInfoToChargeSign(getLocalHelix()->circleXY().orientation());
307}
308
309double CDCTrajectory3D::getAbsMom3D(const double bZ) const
310{
311 double tanLambda = getLocalHelix()->tanLambda();
312 double factor2DTo3D = hypot2(1, tanLambda);
313 double curvatureXY = getLocalHelix()->curvatureXY();
314 double absMom2D = CDCBFieldUtil::curvatureToAbsMom2D(curvatureXY, bZ);
315 return factor2DTo3D * absMom2D;
316}
317
319{
320 ROOT::Math::XYZVector position = getSupport();
321 double tanLambda = getLocalHelix()->tanLambda();
322 double factor2DTo3D = hypot2(1, tanLambda);
323 double curvatureXY = getLocalHelix()->curvatureXY();
324 double absMom2D = CDCBFieldUtil::curvatureToAbsMom2D(curvatureXY, position);
325 return factor2DTo3D * absMom2D;
326}
327
329{
330 double arcLength2D = m_localHelix.shiftPeriod(nPeriods);
331 m_flightTime += arcLength2D / Const::speedOfLight;
332 return arcLength2D;
333}
334
336{
337 return CDCTrajectory2D(VectorUtil::getXYVector(getLocalOrigin()),
338 getLocalHelix().uncertainCircleXY(),
339 getFlightTime());
340}
341
343{
345 globalSZLine.passiveMoveBy(ROOT::Math::XYVector(0, -getLocalOrigin().z()));
346 return CDCTrajectorySZ(globalSZLine);
347}
348
349
351{
352 // Down cast since we do not necessarily won't the covariance matrix transformed as well
353 PerigeeCircle result(getLocalHelix()->circleXY());
354 result.passiveMoveBy(-VectorUtil::getXYVector(getLocalOrigin()));
355 return result;
356}
357
362
367
368double CDCTrajectory3D::setLocalOrigin(const ROOT::Math::XYZVector& localOrigin)
369{
370 double arcLength2D = calcArcLength2D(localOrigin);
371 double factor2DTo3D = hypot2(1, getTanLambda());
372 double arcLength3D = arcLength2D * factor2DTo3D;
373 m_flightTime += arcLength3D / Const::speedOfLight;
374 m_localHelix.passiveMoveBy(localOrigin - m_localOrigin);
375 m_localOrigin = localOrigin;
376 return arcLength2D;
377}
378
379std::ostream& TrackingUtilities::operator<<(std::ostream& output, const CDCTrajectory3D& trajectory3D)
380{
381 return output << "Local origin : " << trajectory3D.getLocalOrigin() << ", "
382 << "local helix : " << trajectory3D.getLocalHelix();
383}
Class representing the sense wire arrangement in the whole of the central drift chamber.
static CDCWireTopology & getInstance()
Getter for the singleton instance of the wire topology.
double getOuterCylindricalR() const
Getter for the outer radius of the outer most wire layer.
static const double speedOfLight
[cm/ns]
Definition Const.h:695
A Class to store the Monte Carlo particle information.
Definition MCParticle.h:32
Helper functions to interact with the magnetic field.
static double curvatureToAbsMom2D(double curvature, double bZ)
Conversion helper for two dimensional curvature to momenta.
static ESign ccwInfoToChargeSign(ERotation ccwInfo)
Conversion helper from clockwise or counterclockwise travel to the charge sign.
static double getBFieldZ()
Getter for the signed magnetic field strength in z direction at the origin ( in Tesla )
static double getAlphaFromBField(double bField)
Translator from magnetic field strength in Tesla to the alpha value.
Particle trajectory as it is seen in xy projection represented as a circle.
const ROOT::Math::XYVector & getLocalOrigin() const
Getter for the origin of the local coordinate system.
Particle full three dimensional trajectory.
UncertainPerigeeCircle getLocalCircle() const
Getter for the circle in local coordinates.
double setLocalOrigin(const ROOT::Math::XYZVector &localOrigin)
Setter for the origin of the local coordinate system.
double getMaximalCylindricalR() const
Getter for the maximal distance from the origin.
bool fillInto(genfit::TrackCand &trackCand) const
Copies the trajectory information to the Genfit track candidate.
double getAbsMom3D() const
Get the estimation for the absolute value of the transvers momentum.
CovarianceMatrix< 6 > getCartesianCovariance(double bZ) const
Convert the helix parameters to the cartesian coordinates x,y,z,px,py,pz.
PerigeeCircle getGlobalCircle() const
Getter for the circle in global coordinates.
ROOT::Math::XYZVector getMom3DAtSupport() const
Get the momentum at the start point of the trajectory.
double getFlightTime() const
Getter for the time when the particle reached the support point position.
CDCTrajectory2D getTrajectory2D() const
Getter for the two dimensional trajectory.
ESign getChargeSign() const
Gets the charge sign of the trajectory.
double shiftPeriod(int nPeriods)
Adjusts the z0 to the one that lies n periods forward.
bool isCurler(double factor=1) const
Checks if the trajectory leaves the outer radius of the CDC times the given tolerance factor.
UncertainSZLine getLocalSZLine() const
Getter for the sz line starting from the local origin.
CDCTrajectory3D()
Default constructor for ROOT compatibility.
CDCTrajectorySZ getTrajectorySZ() const
Getter for the sz trajectory.
const UncertainHelix & getLocalHelix() const
Getter for the helix in local coordinates.
double getTanLambda() const
Getter for the slope of z over the transverse travel distance s.
ROOT::Math::XYZVector m_localOrigin
Memory for local coordinate origin of the circle representing the trajectory in global coordinates.
UncertainHelix m_localHelix
Memory for the generalized circle describing the trajectory in coordinates from the local origin.
const ROOT::Math::XYZVector & getLocalOrigin() const
Getter for the origin of the local coordinate system.
double calcArcLength2D(const ROOT::Math::XYZVector &point) const
Calculate the travel distance from the start position of the trajectory.
ROOT::Math::XYZVector getFlightDirection3DAtSupport() const
Get the unit momentum at the start point of the trajectory.
ROOT::Math::XYZVector getSupport() const
Getter for the support point of the trajectory in global coordinates, where arcLength2D = 0.
double m_flightTime
Memory for the estimation of the time at which the particle arrived at the support point.
double impactXY() const
Getter for the signed distance to the z axes at the perigee point.
Definition Helix.h:214
double tanLambda() const
Getter for the proportinality factor from arc length in xy space to z.
Definition Helix.h:245
double curvatureXY() const
Getter for the signed curvature in the xy projection.
Definition Helix.h:208
const ROOT::Math::XYVector & phi0Vec() const
Getter for the direction vector in the xy projection at the perigee of the helix.
Definition Helix.h:301
Extension of the generalized circle also caching the perigee coordinates.
A general helix class including a covariance matrix.
const HelixCovariance & helixCovariance() const
Getter for the whole covariance matrix of the perigee parameters.
UncertainSZLine uncertainSZLine() const
Reduces the helix to an sz line carrying over the relevant parts of the convariance matrix.
UncertainPerigeeCircle uncertainCircleXY() const
Projects the helix into the xy plain carrying over the relevant parts of the convariance matrix.
Adds an uncertainty matrix to the circle in perigee parameterisation.
A line in sz where s is the transverse travel distance as seen in the xy projection with uncertaintie...
void passiveMoveBy(const ROOT::Math::XYVector &bySZ)
Moves the coordinate system by the vector by and calculates the new sz line and its covariance matrix...
static constexpr auto XYZToTVector
Helper function to convert XYZVector to TVector3.
Definition VectorUtil.h:26
bool isValid(ESign s)
Returns true if sign is ESign::c_Plus, ESign::c_Minus or ESign::c_Zero.
Definition ESign.h:46
Namespace to hide the contained enum constants.
Abstract base class for different kinds of events.
static CovarianceMatrix< M > transported(const JacobianMatrix< M, N > &jacobian, const CovarianceMatrix< N > &cov)
Return a copy of the covariance matrix transported with the given jacobian matrix.
static void transport(const JacobianMatrix< N, N > &jacobian, CovarianceMatrix< N > &cov)
Transport the covariance matrix inplace with the given jacobian matrix.
static JacobianMatrix< M, N > zero()
Construct a zero matrix.
static CovarianceMatrix< N > fromTMatrix(const TMatrixDSym &tCov)
Create a covariance matrix from a TMatrix representation.
static TMatrixDSym toTMatrix(const CovarianceMatrix< N > &cov)
Translate the covariance matrix to the TMatrix representation.