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/Vector3D.h>
25#include <tracking/trackingUtilities/geometry/Vector2D.h>
26
27#include <tracking/trackingUtilities/numerics/ESign.h>
28#include <tracking/trackingUtilities/numerics/Quadratic.h>
29
30#include <tracking/trackingUtilities/numerics/CovarianceMatrixUtil.h>
31#include <tracking/trackingUtilities/numerics/JacobianMatrixUtil.h>
32#include <tracking/trackingUtilities/numerics/TMatrixConversion.h>
33
34#include <genfit/TrackCand.h>
35
36#include <mdst/dataobjects/MCParticle.h>
37
38#include <framework/gearbox/Const.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_localOrigin(trajectory2D.getLocalOrigin())
51 , m_localHelix(trajectory2D.getLocalCircle(), trajectorySZ.getSZLine())
52 , m_flightTime(trajectory2D.getFlightTime())
53{
54}
55
57 : CDCTrajectory3D(trajectory2D, CDCTrajectorySZ::basicAssumption())
58{
59}
60
62 const double time,
63 const Vector3D& mom3D,
64 const double charge,
65 const double bZ)
66 : m_localOrigin(pos3D)
67 , m_localHelix(CDCBFieldUtil::absMom2DToCurvature(mom3D.xy().norm(), charge, bZ),
68 mom3D.xy().unit(),
69 0.0,
70 mom3D.cotTheta(),
71 0.0)
72 , m_flightTime(time)
73{
74}
75
77 const double time,
78 const Vector3D& mom3D,
79 const double charge)
80 : CDCTrajectory3D(pos3D, time, mom3D, charge, CDCBFieldUtil::getBFieldZ(pos3D))
81{
82}
83
84CDCTrajectory3D::CDCTrajectory3D(const MCParticle& mcParticle, const double bZ)
85 : CDCTrajectory3D(Vector3D{mcParticle.getProductionVertex()},
86 mcParticle.getProductionTime(),
87 Vector3D{mcParticle.getMomentum()},
88 mcParticle.getCharge(),
89 bZ)
90{
91}
92
94 : CDCTrajectory3D(Vector3D{mcParticle.getProductionVertex()},
95 mcParticle.getProductionTime(),
96 Vector3D{mcParticle.getMomentum()},
97 mcParticle.getCharge())
98{
99}
100
101CDCTrajectory3D::CDCTrajectory3D(const genfit::TrackCand& gfTrackCand, const double bZ)
102 : CDCTrajectory3D(Vector3D{gfTrackCand.getPosSeed()},
103 gfTrackCand.getTimeSeed(),
104 Vector3D{gfTrackCand.getMomSeed()},
105 gfTrackCand.getChargeSeed(),
106 bZ)
107{
108 // Maybe push these out of this function:
109 // Indices of the cartesian coordinates
110 const int iX = 0;
111 const int iY = 1;
112 const int iZ = 2;
113 const int iPx = 3;
114 const int iPy = 4;
115 const int iPz = 5;
116
117 const TMatrixDSym& seedCov = gfTrackCand.getCovSeed();
118 CovarianceMatrix<6> cov6 = TMatrixConversion::fromTMatrix<6>(seedCov);
119
120 // 1. Rotate to a system where phi0 = 0
121 JacobianMatrix<6, 6> jacobianRot = JacobianMatrixUtil::zero<6, 6>();
122
123 const double px = gfTrackCand.getStateSeed()[iPx];
124 const double py = gfTrackCand.getStateSeed()[iPy];
125 const double pt = hypot2(px, py);
126
127 const double cosPhi0 = px / pt;
128 const double sinPhi0 = py / pt;
129
130 // Passive rotation matrix by phi0:
131 jacobianRot(iX, iX) = cosPhi0;
132 jacobianRot(iX, iY) = sinPhi0;
133 jacobianRot(iY, iX) = -sinPhi0;
134 jacobianRot(iY, iY) = cosPhi0;
135 jacobianRot(iZ, iZ) = 1.0;
136
137 jacobianRot(iPx, iPx) = cosPhi0;
138 jacobianRot(iPx, iPy) = sinPhi0;
139 jacobianRot(iPy, iPx) = -sinPhi0;
140 jacobianRot(iPy, iPy) = cosPhi0;
141 jacobianRot(iPz, iPz) = 1.0;
142
143 // Apply transformation inplace
144 CovarianceMatrixUtil::transport(jacobianRot, cov6);
145
146 // 2. Translate to perigee parameters
147 JacobianMatrix<5, 6> jacobianReduce = JacobianMatrixUtil::zero<5, 6>();
148
149 const double invPt = 1 / pt;
150 const double invPtSquared = invPt * invPt;
151 const double pz = gfTrackCand.getStateSeed()[iPz];
152 const double alpha = CDCBFieldUtil::getAlphaFromBField(bZ);
153 const double charge = gfTrackCand.getChargeSeed();
154
155 using namespace NHelixParameterIndices;
156 jacobianReduce(c_Curv, iPx) = charge * invPtSquared / alpha ;
157 jacobianReduce(c_Phi0, iPy) = invPt;
158 jacobianReduce(c_I, iY) = 1;
159 jacobianReduce(c_TanL, iPx) = - pz * invPtSquared;
160 jacobianReduce(c_TanL, iPz) = invPt;
161 jacobianReduce(c_Z0, iZ) = 1;
162 // Note the column corresponding to iX is completely zero as expectable.
163
164 CovarianceMatrix<5> cov5 = CovarianceMatrixUtil::transported(jacobianReduce, cov6);
165 const HelixCovariance& helixCovariance = cov5;
166
167 // The covariance should now be the correct 5x5 covariance matrix.
168 m_localHelix.setHelixCovariance(helixCovariance);
169}
170
171CDCTrajectory3D::CDCTrajectory3D(const genfit::TrackCand& gfTrackCand)
172 : CDCTrajectory3D(gfTrackCand, CDCBFieldUtil::getBFieldZ(Vector3D{gfTrackCand.getPosSeed()}))
173{
174}
175
176namespace {
177 CovarianceMatrix<6> calculateCovarianceMatrix(const UncertainHelix& localHelix,
178 const Vector3D& momentum,
179 const ESign charge,
180 const double bZ)
181 {
182 const double impactXY = localHelix->impactXY();
183 const Vector2D& phi0Vec = localHelix->phi0Vec();
184
185 const double cosPhi0 = phi0Vec.x();
186 const double sinPhi0 = phi0Vec.y();
187
188 const double curvatureXY = localHelix->curvatureXY();
189 const double tanLambda = localHelix->tanLambda();
190
191 // 0. Define indices
192 // Maybe push these out of this function:
193 // Indices of the cartesian coordinates
194 const int iX = 0;
195 const int iY = 1;
196 const int iZ = 2;
197 const int iPx = 3;
198 const int iPy = 4;
199 const int iPz = 5;
200
201 CovarianceMatrix<5> cov5 = localHelix.helixCovariance();
202
203 // 1. Inflat the perigee covariance to a cartesian covariance where phi0 = 0 is assumed
204 // Jacobian matrix for the translation
205 JacobianMatrix<6, 5> jacobianInflate = JacobianMatrixUtil::zero<6, 5>();
206
207 const double alpha = CDCBFieldUtil::getAlphaFromBField(bZ);
208 const double chargeAlphaCurv = static_cast<double>(charge) * alpha * curvatureXY;
209 const double chargeAlphaCurv2 = static_cast<double>(charge) * alpha * std::pow(curvatureXY, 2);
210
211 const double invChargeAlphaCurv = 1.0 / chargeAlphaCurv;
212 const double invChargeAlphaCurv2 = 1.0 / chargeAlphaCurv2;
213
214 using namespace NHelixParameterIndices;
215 // Position
216 jacobianInflate(iX, c_Phi0) = -impactXY;
217 jacobianInflate(iY, c_I) = 1.0;
218 jacobianInflate(iZ, c_Z0) = 1.0;
219
220 // Momentum
221 if (bZ == 0) {
222 jacobianInflate(iPx, c_Curv) = 0;
223 jacobianInflate(iPy, c_Phi0) = momentum.cylindricalR();
224 jacobianInflate(iPz, c_Curv) = 0;
225 jacobianInflate(iPz, c_TanL) = momentum.cylindricalR();
226 } else {
227 jacobianInflate(iPx, c_Curv) = invChargeAlphaCurv2;
228 jacobianInflate(iPy, c_Phi0) = - invChargeAlphaCurv;
229 jacobianInflate(iPz, c_Curv) = tanLambda * invChargeAlphaCurv2;
230 jacobianInflate(iPz, c_TanL) = - invChargeAlphaCurv;
231 }
232
233 // Transform
234 CovarianceMatrix<6> cov6 = CovarianceMatrixUtil::transported(jacobianInflate, cov5);
235
237 JacobianMatrix<6, 6> jacobianRot = JacobianMatrixUtil::zero<6, 6>();
238
239 // Active rotation matrix by phi0:
240 jacobianRot(iX, iX) = cosPhi0;
241 jacobianRot(iX, iY) = -sinPhi0;
242 jacobianRot(iY, iX) = sinPhi0;
243 jacobianRot(iY, iY) = cosPhi0;
244 jacobianRot(iZ, iZ) = 1.0;
245
246 jacobianRot(iPx, iPx) = cosPhi0;
247 jacobianRot(iPx, iPy) = -sinPhi0;
248 jacobianRot(iPy, iPx) = sinPhi0;
249 jacobianRot(iPy, iPy) = cosPhi0;
250 jacobianRot(iPz, iPz) = 1.0;
251
252 // Apply transformation inplace
253 CovarianceMatrixUtil::transport(jacobianRot, cov6);
254
255 // 3. Forward the covariance matrix.
256 return cov6;
257 }
258}
259
260
261bool CDCTrajectory3D::fillInto(genfit::TrackCand& trackCand) const
262{
263 Vector3D position = getSupport();
264 return fillInto(trackCand, CDCBFieldUtil::getBFieldZ(position));
265}
266
267bool CDCTrajectory3D::fillInto(genfit::TrackCand& gfTrackCand, const double bZ) const
268{
269 // Set the start parameters
270 Vector3D position = getSupport();
271 Vector3D momentum = bZ == 0 ? getFlightDirection3DAtSupport() : getMom3DAtSupport(bZ);
272 ESign charge = getChargeSign();
273
274 // Do not propagate invalid fits, signal that the fit is invalid to the caller.
275 if (not ESignUtil::isValid(charge) or momentum.hasNAN() or position.hasNAN()) {
276 return false;
277 }
278
279 gfTrackCand.setPosMomSeed(position, momentum, charge);
280
281 const CovarianceMatrix<6> cov6 = calculateCovarianceMatrix(getLocalHelix(), momentum, charge, bZ);
282 TMatrixDSym covSeed = TMatrixConversion::toTMatrix(cov6);
283
284 gfTrackCand.setCovSeed(covSeed);
285
286 return true;
287}
288
289CovarianceMatrix<6> CDCTrajectory3D::getCartesianCovariance(double bZ) const
290{
291 // Set the start parameters
292 Vector3D momentum = bZ == 0 ? getFlightDirection3DAtSupport() : getMom3DAtSupport(bZ);
293 ESign charge = getChargeSign();
294 return calculateCovarianceMatrix(getLocalHelix(), momentum, charge, bZ);
295}
296
297bool CDCTrajectory3D::isCurler(double factor) const
298{
300 return getMaximalCylindricalR() < factor * topology.getOuterCylindricalR();
301}
302
304{
305 return CDCBFieldUtil::ccwInfoToChargeSign(getLocalHelix()->circleXY().orientation());
306}
307
308double CDCTrajectory3D::getAbsMom3D(const double bZ) const
309{
310 double tanLambda = getLocalHelix()->tanLambda();
311 double factor2DTo3D = hypot2(1, tanLambda);
312 double curvatureXY = getLocalHelix()->curvatureXY();
313 double absMom2D = CDCBFieldUtil::curvatureToAbsMom2D(curvatureXY, bZ);
314 return factor2DTo3D * absMom2D;
315}
316
318{
319 Vector3D position = getSupport();
320 double tanLambda = getLocalHelix()->tanLambda();
321 double factor2DTo3D = hypot2(1, tanLambda);
322 double curvatureXY = getLocalHelix()->curvatureXY();
323 double absMom2D = CDCBFieldUtil::curvatureToAbsMom2D(curvatureXY, position);
324 return factor2DTo3D * absMom2D;
325}
326
328{
329 double arcLength2D = m_localHelix.shiftPeriod(nPeriods);
330 m_flightTime += arcLength2D / Const::speedOfLight;
331 return arcLength2D;
332}
333
335{
336 return CDCTrajectory2D(getLocalOrigin().xy(),
337 getLocalHelix().uncertainCircleXY(),
338 getFlightTime());
339}
340
342{
344 globalSZLine.passiveMoveBy(Vector2D(0, -getLocalOrigin().z()));
345 return CDCTrajectorySZ(globalSZLine);
346}
347
348
350{
351 // Down cast since we do not necessarily won't the covariance matrix transformed as well
352 PerigeeCircle result(getLocalHelix()->circleXY());
353 result.passiveMoveBy(-getLocalOrigin().xy());
354 return result;
355}
356
361
366
368{
369 double arcLength2D = calcArcLength2D(localOrigin);
370 double factor2DTo3D = hypot2(1, getTanLambda());
371 double arcLength3D = arcLength2D * factor2DTo3D;
372 m_flightTime += arcLength3D / Const::speedOfLight;
373 m_localHelix.passiveMoveBy(localOrigin - m_localOrigin);
374 m_localOrigin = localOrigin;
375 return arcLength2D;
376}
377
378std::ostream& TrackingUtilities::operator<<(std::ostream& output, const CDCTrajectory3D& trajectory3D)
379{
380 return output << "Local origin : " << trajectory3D.getLocalOrigin() << ", "
381 << "local helix : " << trajectory3D.getLocalHelix();
382}
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.
Particle full three dimensional trajectory.
UncertainPerigeeCircle getLocalCircle() const
Getter for the circle in local coordinates.
double calcArcLength2D(const Vector3D &point) const
Calculate the travel distance from the start position of the trajectory.
Vector3D m_localOrigin
Memory for local coordinate origin of the circle representing the trajectory in global coordinates.
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.
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.
Vector3D getFlightDirection3DAtSupport() const
Get the unit momentum at the start point of the trajectory.
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.
Vector3D getMom3DAtSupport() const
Get the momentum at the start point of the trajectory.
UncertainHelix m_localHelix
Memory for the generalized circle describing the trajectory in coordinates from the local origin.
double setLocalOrigin(const Vector3D &localOrigin)
Setter for the origin of the local coordinate system.
const Vector3D & getLocalOrigin() const
Getter for the origin of the local coordinate system.
double m_flightTime
Memory for the estimation of the time at which the particle arrived at the support point.
Vector3D getSupport() const
Getter for the support point of the trajectory in global coordinates, where arcLength2D = 0.
double impactXY() const
Getter for the signed distance to the z axes at the perigee point.
Definition Helix.h:210
double tanLambda() const
Getter for the proportinality factor from arc length in xy space to z.
Definition Helix.h:240
double curvatureXY() const
Getter for the signed curvature in the xy projection.
Definition Helix.h:204
const Vector2D & phi0Vec() const
Getter for the direction vector in the xy projection at the perigee of the helix.
Definition Helix.h:295
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 Vector2D &bySZ)
Moves the coordinate system by the vector by and calculates the new sz line and its covariance matrix...
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition Vector2D.h:36
double x() const
Getter for the x coordinate.
Definition Vector2D.h:626
double y() const
Getter for the y coordinate.
Definition Vector2D.h:641
A three dimensional vector.
Definition Vector3D.h:34
bool hasNAN() const
Checks if one of the coordinates is NAN.
Definition Vector3D.h:166
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.