Belle II Software development
CDCTrajectory2D.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/CDCTrajectory2D.h>
9
10#include <tracking/trackingUtilities/eventdata/trajectories/CDCBFieldUtil.h>
11
12#include <cdc/topology/CDCWireTopology.h>
13#include <cdc/topology/CDCWireLayer.h>
14#include <cdc/topology/WireLine.h>
15#include <cdc/topology/ISuperLayer.h>
16
17#include <tracking/trackingUtilities/geometry/UncertainPerigeeCircle.h>
18#include <tracking/trackingUtilities/geometry/PerigeeCircle.h>
19#include <tracking/trackingUtilities/geometry/VectorUtil.h>
20
21#include <tracking/trackingUtilities/numerics/EForwardBackward.h>
22#include <tracking/trackingUtilities/numerics/ESign.h>
23#include <tracking/trackingUtilities/numerics/Quadratic.h>
24
25#include <framework/gearbox/Const.h>
26
27#include <vector>
28#include <utility>
29#include <ostream>
30#include <cmath>
31#include <cassert>
32
33using namespace Belle2;
34using namespace CDC;
35using namespace TrackingUtilities;
36
42
44 : m_localOrigin(0.0, 0.0)
45 , m_localPerigeeCircle(perigeeCircle)
46{
47}
48
49CDCTrajectory2D::CDCTrajectory2D(const ROOT::Math::XYVector& localOrigin,
50 const UncertainPerigeeCircle& localPerigeeCircle,
51 double flightTime)
52 : m_localOrigin(localOrigin)
53 , m_localPerigeeCircle(localPerigeeCircle)
54 , m_flightTime(flightTime)
55{
56}
57
58CDCTrajectory2D::CDCTrajectory2D(const ROOT::Math::XYVector& pos2D,
59 const double time,
60 const ROOT::Math::XYVector& mom2D,
61 const double charge,
62 const double bZ)
63 : m_localOrigin(pos2D)
64 , m_localPerigeeCircle(CDCBFieldUtil::absMom2DToCurvature(mom2D.R(), charge, bZ),
65 VectorUtil::unit(mom2D),
66 0.0)
67 , m_flightTime(time)
68{
69}
70
71CDCTrajectory2D::CDCTrajectory2D(const ROOT::Math::XYVector& pos2D,
72 const double time,
73 const ROOT::Math::XYVector& mom2D,
74 const double charge)
75 : m_localOrigin(pos2D)
76 , m_localPerigeeCircle(CDCBFieldUtil::absMom2DToCurvature(mom2D.R(), charge, pos2D),
77 VectorUtil::unit(mom2D),
78 0.0)
79 , m_flightTime(time)
80{
81}
82
84{
85 return not getLocalCircle()->isInvalid();
86}
87
89{
90 m_localOrigin.SetXY(0.0, 0.0);
91 m_localPerigeeCircle.invalidate();
92 m_flightTime = NAN;
93}
94
100
101
103{
104 CDCTrajectory2D result = *this;
105 result.reverse();
106 return result;
107}
108
109std::array<double, 2> CDCTrajectory2D::reconstructBothZ(const WireLine& wireLine,
110 const double distance,
111 const double z) const
112{
113 ROOT::Math::XYVector globalPos2D = wireLine.sagPos2DAtZ(z);
114 ROOT::Math::XYVector movePerZ = wireLine.sagMovePerZ(z);
115
116 ROOT::Math::XYVector localPos2D = globalPos2D - getLocalOrigin();
117 const PerigeeCircle& localCircle = getLocalCircle();
118
119 double fastDistance = distance != 0.0 ? localCircle.fastDistance(distance) : 0.0;
120
121 double c = localCircle.fastDistance(localPos2D) - fastDistance;
122 double b = localCircle.gradient(localPos2D).Dot(movePerZ);
123 double a = localCircle.n3() * movePerZ.Mag2();
124
125 const std::pair<double, double> solutionsDeltaZ = solveQuadraticABC(a, b, c);
126
127 // Put the solution of smaller deviation first
128 const std::array<double, 2> solutionsZ{solutionsDeltaZ.second + z, solutionsDeltaZ.first + z};
129 return solutionsZ;
130}
131
133 const double distance,
134 const double z) const
135{
136 const std::array<double, 2> solutionsZ = reconstructBothZ(wireLine, distance, z);
137
138 bool firstIsInCDC = (wireLine.backwardZ() < solutionsZ[0] and
139 solutionsZ[0] < wireLine.forwardZ());
140 bool secondIsInCDC = (wireLine.backwardZ() < solutionsZ[1] and
141 solutionsZ[1] < wireLine.forwardZ());
142
143 // Prefer the solution with the smaller deviation from the given z position which is the first
144 assert(not(std::fabs(solutionsZ[0] - z) > std::fabs(solutionsZ[1] - z)));
145 const double recoZ = (firstIsInCDC or not secondIsInCDC) ? solutionsZ[0] : solutionsZ[1];
146 return recoZ;
147}
148
149std::array<ROOT::Math::XYZVector, 2> CDCTrajectory2D::reconstructBoth3D(const WireLine& wireLine,
150 const double distance,
151 const double z) const
152{
153 const std::array<double, 2> solutionsZ = reconstructBothZ(wireLine, distance, z);
154
155 const ROOT::Math::XYZVector firstRecoWirePos3D = wireLine.sagPos3DAtZ(solutionsZ[0]);
156 const ROOT::Math::XYZVector secondRecoWirePos3D = wireLine.sagPos3DAtZ(solutionsZ[1]);
157 const auto& tmp1 = getClosest(VectorUtil::getXYVector(firstRecoWirePos3D));
158 const auto& tmp2 = getClosest(VectorUtil::getXYVector(secondRecoWirePos3D));
159 return {{{tmp1.X(), tmp1.Y(), firstRecoWirePos3D.z()},
160 {tmp2.X(), tmp2.Y(), secondRecoWirePos3D.z()}
161 }};
162}
163
164ROOT::Math::XYZVector CDCTrajectory2D::reconstruct3D(const WireLine& wireLine,
165 const double distance,
166 const double z) const
167{
168 const double recoZ = reconstructZ(wireLine, distance, z);
169 const ROOT::Math::XYZVector recoWirePos2D = wireLine.sagPos3DAtZ(recoZ);
170 const auto& tmp = getClosest(VectorUtil::getXYVector(recoWirePos2D));
171 return ROOT::Math::XYZVector(tmp.X(), tmp.Y(), recoZ);
172}
173
174ROOT::Math::XYVector CDCTrajectory2D::getClosest(const ROOT::Math::XYVector& point) const
175{
176 return getLocalCircle()->closest(point - getLocalOrigin()) + getLocalOrigin();
177}
178
180{
182
183 ISuperLayer minimalISuperLayer = getMinimalISuperLayer();
184 ISuperLayer maximalISuperLayer = getMaximalISuperLayer();
185 if (minimalISuperLayer == maximalISuperLayer) return ISuperLayerUtil::c_Invalid; // No next super layer to go to
186 if (iSuperLayer == minimalISuperLayer) return ISuperLayerUtil::getNextOutwards(iSuperLayer);
187 if (iSuperLayer == maximalISuperLayer) return ISuperLayerUtil::getNextInwards(iSuperLayer);
188
189 if (movingOutward) {
190 return ISuperLayerUtil::getNextOutwards(iSuperLayer);
191 } else {
192 return ISuperLayerUtil::getNextInwards(iSuperLayer);
193 }
194}
195
197{
198 ISuperLayer iSuperLayer = getStartISuperLayer();
199 return getISuperLayerAfter(iSuperLayer, movingOutward);
200}
201
202ISuperLayer CDCTrajectory2D::getISuperLayerAfterStart(const EForwardBackward forwardBackwardInfo) const
203{
204 bool movingOutward = isMovingOutward();
205 if (forwardBackwardInfo == EForwardBackward::c_Backward) {
206 movingOutward = not movingOutward;
207 }
208 return getISuperLayerAfterStart(movingOutward);
209}
210
212{
213 return getISuperLayerAfterStart(EForwardBackward::c_Forward);
214}
215
217{
218 return getISuperLayerAfterStart(EForwardBackward::c_Backward);
219}
220
221ISuperLayer CDCTrajectory2D::getAxialISuperLayerAfterStart(const EForwardBackward forwardBackwardInfo) const
222{
223 bool movingOutward = isMovingOutward();
224 if (forwardBackwardInfo == EForwardBackward::c_Backward) {
225 movingOutward = not movingOutward;
226 }
227 ISuperLayer startISuperLayer = getStartISuperLayer();
228 if (ISuperLayerUtil::isInvalid(startISuperLayer)) return ISuperLayerUtil::c_Invalid;
229
230 ISuperLayer nextISuperLayer = getISuperLayerAfter(startISuperLayer, movingOutward);
231 if (ISuperLayerUtil::isInvalid(nextISuperLayer)) return ISuperLayerUtil::c_Invalid;
232 if (ISuperLayerUtil::isAxial(nextISuperLayer)) return nextISuperLayer;
233
234 ISuperLayer iSuperLayerStep = nextISuperLayer - startISuperLayer;
235 assert(std::abs(iSuperLayerStep) == 1);
236 bool nextMovingOutward = iSuperLayerStep > 0;
237 return getISuperLayerAfter(nextISuperLayer, nextMovingOutward);
238}
239
241{
242 return getAxialISuperLayerAfterStart(EForwardBackward::c_Forward);
243}
244
246{
247 return getAxialISuperLayerAfterStart(EForwardBackward::c_Backward);
248}
249
251{
252 double maximalCylindricalR = getMaximalCylindricalR();
254}
255
257{
258 double startCylindricalR = getLocalOrigin().R();
260}
261
263{
264 double minimalCylindricalR = getMinimalCylindricalR();
266}
267
268bool CDCTrajectory2D::isCurler(double factor) const
269{
271 return getMaximalCylindricalR() < factor * topology.getOuterCylindricalR();
272}
273
274bool CDCTrajectory2D::isOriginer(double factor) const
275{
277 return getMinimalCylindricalR() < factor * topology.getInnerCylindricalR();
278}
279
280
282{
283 return CDCBFieldUtil::ccwInfoToChargeSign(getLocalCircle()->orientation());
284}
285
286double CDCTrajectory2D::getAbsMom2D(const double bZ) const
287{
288 return CDCBFieldUtil::curvatureToAbsMom2D(getLocalCircle()->curvature(), bZ);
289}
290
292{
293 ROOT::Math::XYVector position = getSupport();
294 return CDCBFieldUtil::curvatureToAbsMom2D(getLocalCircle()->curvature(), position);
295}
296
297ROOT::Math::XYVector CDCTrajectory2D::getInnerExit() const
298{
300 const CDCWireLayer& innerMostLayer = topology.getWireLayers().front();
301 double innerCylindricalR = innerMostLayer.getInnerCylindricalR();
302
303 const ROOT::Math::XYVector support = getSupport();
304 const PerigeeCircle globalCircle = getGlobalCircle();
305 if (support.Mag2() < innerCylindricalR * innerCylindricalR) {
306 // If we start within the inner volume of the CDC we want the trajectory to enter the CDC
307 // and not stop at first intersection with the inner wall.
308 // Therefore we take the inner exit that comes after the apogee (far point of the circle).
309 const ROOT::Math::XYVector apogee = globalCircle.apogee();
310 return globalCircle.atCylindricalRForwardOf(apogee, innerCylindricalR);
311
312 } else {
313 return globalCircle.atCylindricalRForwardOf(support, innerCylindricalR);
314 }
315}
316
317ROOT::Math::XYVector CDCTrajectory2D::getOuterExit(double factor) const
318{
320 const CDCWireLayer& outerMostLayer = topology.getWireLayers().back();
321 double outerCylindricalR = outerMostLayer.getOuterCylindricalR() * factor;
322
323 const ROOT::Math::XYVector support = getSupport();
324 const PerigeeCircle globalCircle = getGlobalCircle();
325 if (support.Mag2() > outerCylindricalR * outerCylindricalR) {
326 // If we start outside of the volume of the CDC we want the trajectory to enter the CDC
327 // and not stop at first intersection with the outer wall.
328 // Therefore we take the outer exit that comes after the perigee.
329 const ROOT::Math::XYVector perigee = globalCircle.perigee();
330 return globalCircle.atCylindricalRForwardOf(perigee, outerCylindricalR);
331
332 } else {
333 return getGlobalCircle().atCylindricalRForwardOf(support, outerCylindricalR);
334 }
335}
336
337ROOT::Math::XYVector CDCTrajectory2D::getExit() const
338{
339 const ROOT::Math::XYVector outerExit = getOuterExit();
340 const ROOT::Math::XYVector innerExit = getInnerExit();
341 const ROOT::Math::XYVector localExit = getLocalCircle()->chooseNextForwardOf(ROOT::Math::XYVector(0, 0),
342 outerExit - getLocalOrigin(),
343 innerExit - getLocalOrigin());
344 return localExit + getLocalOrigin();
345}
346
347void CDCTrajectory2D::setPosMom2D(const ROOT::Math::XYVector& pos2D,
348 const ROOT::Math::XYVector& mom2D,
349 const double charge)
350{
351 m_localOrigin = pos2D;
352 double curvature = CDCBFieldUtil::absMom2DToCurvature(mom2D.R(), charge, pos2D);
353 ROOT::Math::XYVector phiVec = VectorUtil::unit(mom2D);
354 double impact = 0.0;
355 m_localPerigeeCircle = UncertainPerigeeCircle(curvature, phiVec, impact);
356}
357
358double CDCTrajectory2D::setLocalOrigin(const ROOT::Math::XYVector& localOrigin)
359{
360 double arcLength2D = calcArcLength2D(localOrigin);
361 m_flightTime += arcLength2D / Const::speedOfLight;
362 m_localPerigeeCircle.passiveMoveBy(localOrigin - m_localOrigin);
363 m_localOrigin = localOrigin;
364 return arcLength2D;
365}
366
367
368std::ostream& TrackingUtilities::operator<<(std::ostream& output, const CDCTrajectory2D& trajectory2D)
369{
370 return output << "Local origin : " << trajectory2D.getLocalOrigin() << ", "
371 << "local circle : " << trajectory2D.getLocalCircle();
372}
double R
typedef autogenerated by FFTW
Class representing a sense wire layer in the central drift chamber.
double getInnerCylindricalR() const
Getter for inner radius of the layer as taken from the CDCGeometryPar.
double getOuterCylindricalR() const
Getter for outer radius of the layer as taken from the CDCGeometryPar.
Class representing the sense wire arrangement in the whole of the central drift chamber.
const std::vector< CDCWireLayer > & getWireLayers() const
Getter for the underlying storing layer vector.
ISuperLayer getISuperLayerAtCylindricalR(double cylindricalR)
Returns the logical superlayer number at the given radius.
double getInnerCylindricalR() const
Getter for the inner radius of the inner most wire layer.
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.
A three dimensional limited line represented by its closest approach to the z-axes (reference positio...
Definition WireLine.h:33
ROOT::Math::XYVector sagPos2DAtZ(const double z) const
Gives the two dimensional position with wire sag effect of the line at the given z value.
Definition WireLine.h:68
double backwardZ() const
Gives the backward z coordinate.
Definition WireLine.h:152
ROOT::Math::XYZVector sagPos3DAtZ(const double z) const
Gives the three dimensional position with wire sag effect of the line at the given z value.
Definition WireLine.h:61
double forwardZ() const
Gives the forward z coordinate.
Definition WireLine.h:148
ROOT::Math::XYVector sagMovePerZ(const double z) const
Gives the two dimensional position with wire sag effect of the line at the given z value.
Definition WireLine.h:83
static const double speedOfLight
[cm/ns]
Definition Const.h:695
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 absMom2DToCurvature(double absMom2D, double charge, double bZ)
Conversion helper for momenta to two dimensional curvature.
Particle trajectory as it is seen in xy projection represented as a circle.
std::array< ROOT::Math::XYZVector, 2 > reconstructBoth3D(const CDC::WireLine &wireLine, double distance=0.0, double z=0) const
Gives the two three dimensional points where the drift circle touches the wire line.
double getMaximalCylindricalR() const
Getter for the maximal distance from the origin.
ROOT::Math::XYVector m_localOrigin
Memory for local coordinate origin of the circle representing the trajectory in global coordinates.
CDCTrajectory2D reversed() const
Returns the reverse trajectory as a copy.
ROOT::Math::XYVector getSupport() const
Get the support point of the trajectory in global coordinates.
PerigeeCircle getGlobalCircle() const
Getter for the circle in global coordinates.
CDC::ISuperLayer getAxialISuperLayerAfterStart(EForwardBackward forwardBackwardInfo) const
Indicates which axial superlayer is traversed after the one, where the start point of the trajectory ...
CDC::ISuperLayer getISuperLayerAfter(CDC::ISuperLayer iSuperLayer, bool movingOutward) const
Returns which superlayer is traversed after the current one following the trajectory outward or inwar...
double reconstructZ(const CDC::WireLine &wireLine, double distance=0.0, double z=0) const
Gives the one z positions within the CDC closest to the given z where the given drift circle on the w...
void reverse()
Reverses the trajectory in place.
bool isOriginer(double factor=1) const
Checks if the trajectory intersects with the inner radius of the CDC time the given tolerance factor.
CDC::ISuperLayer getStartISuperLayer() const
Indicates the superlayer the trajectory starts in.
ROOT::Math::XYVector getClosest(const ROOT::Math::XYVector &point) const
Calculates the closest approach on the trajectory to the given point.
ESign getChargeSign() const
Gets the charge sign of the trajectory.
double calcArcLength2D(const ROOT::Math::XYVector &point) const
Calculate the travel distance from the start position of the trajectory.
CDC::ISuperLayer getISuperLayerAfterStart(bool movingOutward) const
Returns which superlayer is traversed after the current one following the trajectory outward or inwar...
double setLocalOrigin(const ROOT::Math::XYVector &localOrigin)
Setter for the origin of the local coordinate system.
ROOT::Math::XYVector getOuterExit(double factor=1) const
Calculates the point where the trajectory meets the outer wall of the CDC.
void setPosMom2D(const ROOT::Math::XYVector &pos2D, const ROOT::Math::XYVector &mom2D, double charge)
Setter for start point and momentum at the start point subjected to the charge sign.
CDC::ISuperLayer getPreviousISuperLayer() const
Indicates which superlayer the trajectory traverses before the one, where the start point of the traj...
const ROOT::Math::XYVector & getLocalOrigin() const
Getter for the origin of the local coordinate system.
bool isCurler(double factor=1) const
Checks if the trajectory leaves the outer radius of the CDC times the given tolerance factor.
CDC::ISuperLayer getMinimalISuperLayer() const
Indicates the minimal superlayer the trajectory traverses.
bool isFitted() const
Checks if the circle is already set to a valid value.
ROOT::Math::XYVector getExit() const
Calculates the point where the trajectory leaves the CDC.
double getMinimalCylindricalR() const
Getter for the minimal distance from the origin - same as absolute value of the impact parameter.
CDC::ISuperLayer getPreviousAxialISuperLayer() const
Indicates which axial superlayer the trajectory traverses before the one, where the start point of th...
CDC::ISuperLayer getMaximalISuperLayer() const
Indicates the maximal superlayer the trajectory traverses.
double getAbsMom2D() const
Get the estimation for the absolute value of the transvers momentum.
const UncertainPerigeeCircle & getLocalCircle() const
Getter for the circle in local coordinates.
std::array< double, 2 > reconstructBothZ(const CDC::WireLine &wireLine, double distance=0.0, double z=0) const
Gives the two z positions where the given drift circle on the wire line touches the trajectory.
ROOT::Math::XYZVector reconstruct3D(const CDC::WireLine &wireLine, double distance=0.0, double z=0) const
Gives the one three dimensional positions within the CDC closest to the given z where the given drift...
UncertainPerigeeCircle m_localPerigeeCircle
Memory for the generalized circle describing the trajectory in coordinates from the local origin.
CDCTrajectory2D()
Default constructor for ROOT compatibility.
void clear()
Clears all information from this trajectory.
bool isMovingOutward() const
Indicates if the trajectory is moving outwards or inwards (to or away from the origin) from the start...
ROOT::Math::XYVector getInnerExit() const
Calculates the point where the trajectory meets the inner wall of the CDC.
CDC::ISuperLayer getNextISuperLayer() const
Indicates which superlayer the trajectory traverses after the one, where the start point of the traje...
CDC::ISuperLayer getNextAxialISuperLayer() const
Indicates which axial superlayer the trajectory traverses after the one, where the start point of the...
double m_flightTime
Memory for the estimation of the time at which the particle arrived at the support point.
Extension of the generalized circle also caching the perigee coordinates.
ROOT::Math::XYVector gradient(const ROOT::Math::XYVector &point) const
Gradient of the distance field, hence indicates the direction of increasing distance.
ROOT::Math::XYVector apogee() const
Getter for the apogee of the circle. If it was a line both components will be infinity.
double fastDistance(const ROOT::Math::XYVector &point) const
Getter for the linearised distance measure to a point.
bool isInvalid() const
Indicates if all circle parameters are zero.
ROOT::Math::XYVector closest(const ROOT::Math::XYVector &point) const
Calculates the point of closest approach on the circle to the given point.
double n3() const
Getter for the generalised circle parameter n3.
ROOT::Math::XYVector perigee() const
Getter for the perigee point.
ROOT::Math::XYVector chooseNextForwardOf(const ROOT::Math::XYVector &start, const ROOT::Math::XYVector &end1, const ROOT::Math::XYVector &end2) const
Returns the one of two end point which is first reached from the given start if one strictly follows ...
ROOT::Math::XYVector atCylindricalRForwardOf(const ROOT::Math::XYVector &startPoint, double cylindricalR) const
Approach on the circle with the given cylindrical radius that lies in the forward direction of a star...
Adds an uncertainty matrix to the circle in perigee parameterisation.
signed short ISuperLayer
The type of the layer and superlayer ids.
Definition ISuperLayer.h:24
Abstract base class for different kinds of events.
static const ISuperLayer c_Invalid
Constant making an invalid superlayer id.
Definition ISuperLayer.h:65
static bool isAxial(ISuperLayer iSuperLayer)
Returns if the super layer with the given id is axial.
static ISuperLayer getNextInwards(ISuperLayer iSuperLayer)
Returns the super layer that is inside of the given super layer.
static bool isInvalid(ISuperLayer iSuperLayer)
Indicates if the given number corresponds to a true cdc superlayer - excludes the logic ids for inner...
static ISuperLayer getNextOutwards(ISuperLayer iSuperLayer)
Returns the super layer that is outside of the given super layer.