Belle II Software  light-2212-foldex
TrackVariables.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 
9 // Own includes
10 #include <analysis/variables/TrackVariables.h>
11 
12 // include VariableManager
13 #include <analysis/VariableManager/Manager.h>
14 
15 #include <analysis/dataobjects/Particle.h>
16 
17 // framework - DataStore
18 #include <framework/datastore/StoreObjPtr.h>
19 #include <framework/dataobjects/Helix.h>
20 
21 // dataobjects from the MDST
22 #include <mdst/dataobjects/Track.h>
23 #include <mdst/dataobjects/MCParticle.h>
24 #include <mdst/dataobjects/TrackFitResult.h>
25 #include <mdst/dataobjects/EventLevelTrackingInfo.h>
26 #include <mdst/dataobjects/HitPatternVXD.h>
27 #include <mdst/dataobjects/ECLCluster.h>
28 
29 // framework aux
30 #include <framework/logging/Logger.h>
31 
32 #include <cmath>
33 
34 namespace Belle2 {
39  namespace Variable {
40 
41  static const double realNaN = std::numeric_limits<double>::quiet_NaN();
42  static const B2Vector3D vecNaN(realNaN, realNaN, realNaN);
43 
44  double trackNHits(const Particle* part, const Const::EDetector& det)
45  {
46  auto trackFit = part->getTrackFitResult();
47  if (!trackFit) return realNaN;
48 
49  // Before release-05 (MC13 + proc 11 and older) the hit patterns of TrackFitResults for V0s from the V0Finder were set to 0.
50  // Then, we have to take the detour via the related track to access the number of track hits.
51  if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
52  trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
53  }
54  if (det == Const::EDetector::CDC) {
55  return trackFit->getHitPatternCDC().getNHits();
56  } else if (det == Const::EDetector::SVD) {
57  return trackFit->getHitPatternVXD().getNSVDHits();
58  } else if (det == Const::EDetector::PXD) {
59  return trackFit->getHitPatternVXD().getNPXDHits();
60  } else {
61  return realNaN;
62  }
63  }
64 
65  double trackNCDCHits(const Particle* part)
66  {
67  return trackNHits(part, Const::EDetector::CDC);
68  }
69 
70  double trackNSVDHits(const Particle* part)
71  {
72  return trackNHits(part, Const::EDetector::SVD);
73  }
74 
75  double trackNPXDHits(const Particle* part)
76  {
77  return trackNHits(part, Const::EDetector::PXD);
78  }
79 
80  double trackNVXDHits(const Particle* part)
81  {
82  return trackNPXDHits(part) + trackNSVDHits(part);
83  }
84 
85  double trackNDF(const Particle* part)
86  {
87  auto trackFit = part->getTrackFitResult();
88  if (!trackFit) return realNaN;
89  return trackFit->getNDF();
90  }
91 
92  double trackChi2(const Particle* part)
93  {
94  auto trackFit = part->getTrackFitResult();
95  if (!trackFit) return realNaN;
96  return trackFit->getChi2();
97  }
98 
99  double trackFirstSVDLayer(const Particle* part)
100  {
101  auto trackFit = part->getTrackFitResult();
102  if (!trackFit) return realNaN;
103  // Before release-05 (MC13 + proc 11 and older) the hit patterns of TrackFitResults for V0s from the V0Finder were set to 0.
104  // Then, we have to take the detour via the related track to access the real pattern and get the first SVD layer if available.
105  if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
106  trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
107  }
108  return trackFit->getHitPatternVXD().getFirstSVDLayer();
109  }
110 
111  double trackFirstPXDLayer(const Particle* part)
112  {
113  auto trackFit = part->getTrackFitResult();
114  if (!trackFit) return realNaN;
115  // Before release-05 (MC13 + proc 11 and older) the hit patterns of TrackFitResults for V0s from the V0Finder were set to 0.
116  // Then, we have to take the detour via the related track to access the real pattern and get the first PXD layer if available.
117  if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
118  trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
119  }
120  return trackFit->getHitPatternVXD().getFirstPXDLayer(HitPatternVXD::PXDMode::normal);
121  }
122 
123  double trackFirstCDCLayer(const Particle* part)
124  {
125  auto trackFit = part->getTrackFitResult();
126  if (!trackFit) return realNaN;
127  // Before release-05 (MC13 + proc 11 and older) the hit patterns of TrackFitResults for V0s from the V0Finder were set to 0.
128  // Then, we have to take the detour via the related track to access the real pattern and get the first CDC layer if available.
129  if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
130  trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
131  }
132  return trackFit->getHitPatternCDC().getFirstLayer();
133  }
134 
135  double trackLastCDCLayer(const Particle* part)
136  {
137  auto trackFit = part->getTrackFitResult();
138  if (!trackFit) return realNaN;
139  // Before release-05 (MC13 + proc 11 and older) the hit patterns of TrackFitResults for V0s from the V0Finder were set to 0.
140  // Then, we have to take the detour via the related track to access the real pattern and get the last CDC layer if available.
141  if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
142  trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
143  }
144  return trackFit->getHitPatternCDC().getLastLayer();
145  }
146 
147  double trackD0(const Particle* part)
148  {
149  auto trackFit = part->getTrackFitResult();
150  if (!trackFit) return realNaN;
151  return trackFit->getD0();
152  }
153 
154  double trackPhi0(const Particle* part)
155  {
156  auto trackFit = part->getTrackFitResult();
157  if (!trackFit) return realNaN;
158  return trackFit->getPhi0();
159  }
160 
161  double trackOmega(const Particle* part)
162  {
163  auto trackFit = part->getTrackFitResult();
164  if (!trackFit) return realNaN;
165  return trackFit->getOmega();
166  }
167 
168  double trackZ0(const Particle* part)
169  {
170  auto trackFit = part->getTrackFitResult();
171  if (!trackFit) return realNaN;
172  return trackFit->getZ0();
173  }
174 
175  double trackTanLambda(const Particle* part)
176  {
177  auto trackFit = part->getTrackFitResult();
178  if (!trackFit) return realNaN;
179  return trackFit->getTanLambda();
180  }
181 
182  double trackD0Error(const Particle* part)
183  {
184  auto trackFit = part->getTrackFitResult();
185  if (!trackFit) return realNaN;
186 
187  double errorSquared = trackFit->getCovariance5()[0][0];
188  if (errorSquared <= 0) return realNaN;
189  return sqrt(errorSquared);
190  }
191 
192  double trackPhi0Error(const Particle* part)
193  {
194  auto trackFit = part->getTrackFitResult();
195  if (!trackFit) return realNaN;
196 
197  double errorSquared = trackFit->getCovariance5()[1][1];
198  if (errorSquared <= 0) return realNaN;
199  return sqrt(errorSquared);
200  }
201 
202  double trackOmegaError(const Particle* part)
203  {
204  auto trackFit = part->getTrackFitResult();
205  if (!trackFit) return realNaN;
206 
207  double errorSquared = trackFit->getCovariance5()[2][2];
208  if (errorSquared <= 0) return realNaN;
209  return sqrt(errorSquared);
210  }
211 
212  double trackZ0Error(const Particle* part)
213  {
214  auto trackFit = part->getTrackFitResult();
215  if (!trackFit) return realNaN;
216 
217  double errorSquared = trackFit->getCovariance5()[3][3];
218  if (errorSquared <= 0) return realNaN;
219  return sqrt(errorSquared);
220  }
221 
222  double trackTanLambdaError(const Particle* part)
223  {
224  auto trackFit = part->getTrackFitResult();
225  if (!trackFit) return realNaN;
226 
227  double errorSquared = trackFit->getCovariance5()[4][4];
228  if (errorSquared <= 0) return realNaN;
229  return sqrt(errorSquared);
230  }
231 
232  double trackFitCovariance(const Particle* particle, const std::vector<double>& indices)
233  {
234  if (indices.size() != 2) {
235  B2FATAL("Exactly two indices must be provided to the variable trackFitCovariance!");
236  }
237  if (*(std::min_element(indices.begin(), indices.end())) < 0 or *(std::max_element(indices.begin(), indices.end())) > 4) {
238  B2FATAL("The indices provided to the variable trackFitCovariance must be in the range 0 - 4!");
239  }
240  auto trackFit = particle->getTrackFitResult();
241  if (!trackFit) return realNaN;
242  return trackFit->getCovariance5()[indices[0]][indices[1]];
243  }
244 
245  double trackPValue(const Particle* part)
246  {
247  auto trackFit = part->getTrackFitResult();
248  if (!trackFit) return realNaN;
249  return trackFit->getPValue();
250  }
251 
252  double trackFitHypothesisPDG(const Particle* part)
253  {
254  auto trackFit = part->getTrackFitResult();
255  if (!trackFit) return realNaN;
256  return trackFit->getParticleType().getPDGCode();
257  }
258 
259  double trackNECLClusters(const Particle* part)
260  {
261  const Track* track = part->getTrack();
262  if (!track) return realNaN;
263 
264  // count the number of nPhotons hypothesis ecl clusters
265  int count = 0;
266  for (const ECLCluster& cluster : track->getRelationsTo<ECLCluster>())
267  if (cluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
268  ++count;
269  return count;
270  }
271 
272  // used in trackHelixExtTheta and trackHelixExtPhi
273  B2Vector3D getPositionOnHelix(const Particle* part, const std::vector<double>& pars)
274  {
275  const auto nParams = pars.size();
276  if (nParams != 3 && nParams != 4) {
277  B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required.");
278  }
279 
280  const double r = pars[0];
281  const double zfwd = pars[1];
282  const double zbwd = pars[2];
283  const auto useHighestProbMass = (nParams == 4) ? bool(pars[3]) : false;
284 
285  const Track* track = part->getTrack();
286 
287  if (!track) return vecNaN;
288 
289  auto highestProbMass = (useHighestProbMass) ? part->getMostLikelyTrackFitResult().first : Const::ChargedStable(std::abs(
290  part->getPDGCode()));
291 
292  const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(highestProbMass);
293 
294  // get helix and parameters
295  const double z0 = trackFit->getZ0();
296  const double tanlambda = trackFit->getTanLambda();
297  const Helix h = trackFit->getHelix();
298 
299  // extrapolate to radius
300  const double arcLength = h.getArcLength2DAtCylindricalR(r);
301  const double lHelixRadius = arcLength > 0 ? arcLength : std::numeric_limits<double>::max();
302 
303  // extrapolate to FWD z
304  const double lFWD = (zfwd - z0) / tanlambda > 0 ? (zfwd - z0) / tanlambda : std::numeric_limits<double>::max();
305 
306  // extrapolate to BWD z
307  const double lBWD = (zbwd - z0) / tanlambda > 0 ? (zbwd - z0) / tanlambda : std::numeric_limits<double>::max();
308 
309  // pick smallest arclength
310  const double l = std::min({lHelixRadius, lFWD, lBWD});
311 
312  return h.getPositionAtArcLength2D(l);
313  }
314 
315  // returns extrapolated theta position based on helix parameters
316  double trackHelixExtTheta(const Particle* part, const std::vector<double>& pars)
317  {
318  const auto nParams = pars.size();
319  if (nParams != 3 && nParams != 4) {
320  B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtTheta.");
321  }
322  B2Vector3D position = getPositionOnHelix(part, pars);
323  if (position == vecNaN) return realNaN;
324  return position.Theta();
325  }
326 
327  // returns extrapolated phi position based on helix parameters
328  double trackHelixExtPhi(const Particle* part, const std::vector<double>& pars)
329  {
330  const auto nParams = pars.size();
331  if (nParams != 3 && nParams != 4) {
332  B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtPhi.");
333  }
334  B2Vector3D position = getPositionOnHelix(part, pars);
335  if (position == vecNaN) return realNaN;
336  return position.Phi();
337  }
338 
339 
340  /***************************************************
341  * Event level tracking quantities
342  */
343 
344  // The number of CDC hits in the event not assigned to any track
345  double nExtraCDCHits(const Particle*)
346  {
347  StoreObjPtr<EventLevelTrackingInfo> elti;
348  if (!elti) return realNaN;
349  return elti->getNCDCHitsNotAssigned();
350  }
351 
352  // The number of CDC hits in the event not assigned to any track nor very
353  // likely beam background (i.e. hits that survive a cleanup selection)
354  double nExtraCDCHitsPostCleaning(const Particle*)
355  {
356  StoreObjPtr<EventLevelTrackingInfo> elti;
357  if (!elti) return realNaN;
358  return elti->getNCDCHitsNotAssignedPostCleaning();
359  }
360 
361  // Check for the presence of a non-assigned hit in the specified CDC layer
362  double hasExtraCDCHitsInLayer(const Particle*, const std::vector<double>& layer)
363  {
364  StoreObjPtr<EventLevelTrackingInfo> elti;
365  if (!elti) return realNaN;
366  int ilayer = std::lround(layer[0]);
367  return elti->hasCDCLayer(ilayer);
368  }
369 
370  // Check for the presence of a non-assigned hit in the specified CDC SuperLayer
371  double hasExtraCDCHitsInSuperLayer(const Particle*, const std::vector<double>& layer)
372  {
373  StoreObjPtr<EventLevelTrackingInfo> elti;
374  if (!elti) return realNaN;
375  int ilayer = std::lround(layer[0]);
376  return elti->hasCDCSLayer(ilayer);
377  }
378 
379  // The number of segments that couldn't be assigned to any track
380  double nExtraCDCSegments(const Particle*)
381  {
382  StoreObjPtr<EventLevelTrackingInfo> elti;
383  if (!elti) return realNaN;
384  return elti->getNCDCSegments();
385  }
386 
387  // The number of VXD hits not assigned to any track in the specified layer
388  double nExtraVXDHitsInLayer(const Particle*, const std::vector<double>& layer)
389  {
390  StoreObjPtr<EventLevelTrackingInfo> elti;
391  if (!elti) return realNaN;
392  int ilayer = std::lround(layer[0]);
393  return elti->getNVXDClustersInLayer(ilayer);
394  }
395 
396  // The number of VXD hits not assigned to any track
397  double nExtraVXDHits(const Particle*)
398  {
399  StoreObjPtr<EventLevelTrackingInfo> elti;
400  if (!elti) return realNaN;
401  double out = 0.0;
402  for (uint16_t ilayer = 1; ilayer < 7; ++ilayer)
403  out += elti->getNVXDClustersInLayer(ilayer);
404  return out;
405  }
406 
407  // time of first SVD sample relative to event T0
408  double svdFirstSampleTime(const Particle*)
409  {
410  StoreObjPtr<EventLevelTrackingInfo> elti;
411  if (!elti) return realNaN;
412  return elti->getSVDFirstSampleTime();
413  }
414 
415  // A flag set by the tracking if there is reason to assume there was a track
416  // in the event missed by the tracking or the track finding was (partly) aborted
417  // for this event. Further information about this can be obtained from the flagBlock
418  // of the EventLevelTrackingInfo object.
419  double trackFindingFailureFlag(const Particle*)
420  {
421  StoreObjPtr<EventLevelTrackingInfo> elti;
422  if (!elti) return realNaN;
423  return elti->hasAnErrorFlag();
424  }
425 
426  double getHelixParameterPullAtIndex(const Particle* particle, const int index)
427  {
428  if (!particle) return realNaN;
429 
430  const MCParticle* mcparticle = particle->getMCParticle();
431  if (!mcparticle) return realNaN;
432 
433  const Belle2::TrackFitResult* trackfit = particle->getTrackFitResult();
434  if (!trackfit) return realNaN;
435 
436  const Belle2::UncertainHelix measHelix = trackfit->getUncertainHelix();
437  const TMatrixDSym measCovariance = measHelix.getCovariance();
438  const ROOT::Math::XYZVector mcProdVertex = mcparticle->getVertex();
439  const ROOT::Math::XYZVector mcMomentum = mcparticle->getMomentum();
440 
441  const double BzAtProdVertex = Belle2::BFieldManager::getFieldInTesla(mcProdVertex).Z();
442  const double mcParticleCharge = mcparticle->getCharge();
443  const Belle2::Helix mcHelix = Belle2::Helix(mcProdVertex, mcMomentum, mcParticleCharge, BzAtProdVertex);
444 
445  const std::vector<double> mcHelixPars = {mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
446  const std::vector<double> measHelixPars = {measHelix.getD0(), measHelix.getPhi0(), measHelix.getOmega(), measHelix.getZ0(), measHelix.getTanLambda()};
447  const std::vector<double> measErrSquare = {measCovariance[0][0], measCovariance[1][1], measCovariance[2][2], measCovariance[3][3], measCovariance[4][4]};
448 
449  return (mcHelixPars.at(index) - measHelixPars.at(index)) / std::sqrt(measErrSquare.at(index));
450  }
451 
452  double getHelixD0Pull(const Particle* part)
453  {
454  return getHelixParameterPullAtIndex(part, 0);
455  }
456 
457  double getHelixPhi0Pull(const Particle* part)
458  {
459  return getHelixParameterPullAtIndex(part, 1);
460  }
461 
462  double getHelixOmegaPull(const Particle* part)
463  {
464  return getHelixParameterPullAtIndex(part, 2);
465  }
466 
467  double getHelixZ0Pull(const Particle* part)
468  {
469  return getHelixParameterPullAtIndex(part, 3);
470  }
471  double getHelixTanLambdaPull(const Particle* part)
472  {
473  return getHelixParameterPullAtIndex(part, 4);
474  }
475  double getTrackTime(const Particle* part)
476  {
477  const Track* track = part->getTrack();
478  if (!track) return realNaN;
479  return track->getTrackTime();
480  }
481 
482  double isTrackFlippedAndRefitted(const Particle* part)
483  {
484  auto track = part->getTrack();
485  if (!track) return realNaN;
486  return track->isFlippedAndRefitted() ? 1 : 0;
487  }
488 
489  VARIABLE_GROUP("Tracking");
490  REGISTER_VARIABLE("d0Pull", getHelixD0Pull, R"DOC(
491 The pull of the tracking parameter :math:`d_0` for the reconstructed
492 pattern-recognition track, with respect to the MC track. That is:
493 
494 .. math::
495 
496  \frac{d_0^\textrm{MC} - d_0^\textrm{PR}}{\sigma_{d_0; \textrm{PR}}}
497 
498 .. seealso:: :b2:var:`d0`, :b2:var:`d0Err`
499 
500 Returns NaN if no MC particle is related or if called on something other than a
501 track-based particle.
502  )DOC");
503  REGISTER_VARIABLE("phi0Pull", getHelixPhi0Pull, R"DOC(
504 The pull of the tracking parameter :math:`\phi_0` for the reconstructed
505 pattern-recognition track, with respect to the MC track. That is:
506 
507 .. math::
508 
509  \frac{\phi_0^\textrm{MC} - \phi_0^\textrm{PR}}{\sigma_{\phi_0; \textrm{PR}}}
510 
511 .. seealso:: :b2:var:`phi0`, :b2:var:`phi0Err`
512 
513 Returns NaN if no MC particle is related or if called on something other than a
514 track-based particle.
515  )DOC");
516  REGISTER_VARIABLE("omegaPull", getHelixOmegaPull, R"DOC(
517 The pull of the tracking parameter :math:`\omega` for the reconstructed
518 pattern-recognition track, with respect to the MC track. That is:
519 
520 .. math::
521 
522  \frac{\omega^\textrm{MC} - \omega^\textrm{PR}}{\sigma_{\omega; \textrm{PR}}}
523 
524 .. seealso:: :b2:var:`omega`, :b2:var:`omegaErr`
525 
526 Returns NaN if no MC particle is related or if called on something other than a
527 track-based particle.
528  )DOC");
529  REGISTER_VARIABLE("z0Pull", getHelixZ0Pull, R"DOC(
530 The pull of the tracking parameter :math:`z_0` for the reconstructed
531 pattern-recognition track, with respect to the MC track. That is:
532 
533 .. math::
534 
535  \frac{z_0^\textrm{MC} - z_0^\textrm{PR}}{\sigma_{z_0; \textrm{PR}}}
536 
537 .. seealso:: :b2:var:`z0`, :b2:var:`z0Err`
538 
539 Returns NaN if no MC particle is related or if called on something other than a
540 track-based particle.
541  )DOC");
542  REGISTER_VARIABLE("tanLambdaPull", getHelixTanLambdaPull, R"DOC(
543 The pull of the tracking parameter :math:`\tan\lambda` for the reconstructed
544 pattern-recognition track, with respect to the MC track. That is:
545 
546 .. math::
547 
548  \frac{(\tan\lambda)^\textrm{MC} - (\tan\lambda)^\textrm{PR}}{\sigma_{\tan\lambda; \textrm{PR}}}
549 
550 .. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaErr`
551 
552 Returns NaN if no MC particle is related or if called on something other than a
553 track-based particle.
554  )DOC");
555  REGISTER_VARIABLE("nCDCHits", trackNCDCHits,
556  "The number of CDC hits associated to the track. Returns NaN if called for something other than a track-based particle.");
557  REGISTER_VARIABLE("nSVDHits", trackNSVDHits,
558  "The number of SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
559  REGISTER_VARIABLE("nPXDHits", trackNPXDHits,
560  "The number of PXD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
561  REGISTER_VARIABLE("nVXDHits", trackNVXDHits,
562  "The number of PXD and SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
563  REGISTER_VARIABLE("ndf", trackNDF, R"DOC(
564 Returns the number of degrees of freedom of the track fit.
565 
566 .. note::
567 
568  Note that this is not simply the number of hits -5 due to outlier hit
569  rejection.
570 
571 Returns NaN if called for something other than a track-based particle, or for
572 mdst files processed with basf2 versions older than ``release-05-01``.
573  )DOC");
574  REGISTER_VARIABLE("chi2", trackChi2, R"DOC(
575 Returns the :math:`\chi^2` of the track fit. This is actually computed based on
576 :b2:var:`pValue` and :b2:var:`ndf`.
577 
578 .. note:: Note that for :b2:var:`pValue` exactly equal to 0 it returns infinity.
579 
580 Returns NaN if called for something other than a track-based particle, or for
581 mdst files processed with basf2 versions older than ``release-05-01``.
582  )DOC");
583  REGISTER_VARIABLE("firstSVDLayer", trackFirstSVDLayer,
584  "The first activated SVD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
585  REGISTER_VARIABLE("firstPXDLayer", trackFirstPXDLayer,
586  "The first activated PXD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
587  REGISTER_VARIABLE("firstCDCLayer", trackFirstCDCLayer,
588  "The first activated CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
589  REGISTER_VARIABLE("lastCDCLayer", trackLastCDCLayer,
590  "The last CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
591  REGISTER_VARIABLE("d0", trackD0, R"DOC(
592 Returns the tracking parameter :math:`d_0`, the signed distance to the
593 point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
594 
595 .. note::
596 
597  Tracking parameters are with respect to the origin (0,0,0). For the
598  POCA with respect to the measured beam interaction point, see
599  :b2:var:`dr` (you probably want this unless you're doing a tracking
600  study or some debugging).
601 
602 Returns NaN if called for something other than a track-based particle.
603  )DOC", "cm");
604  REGISTER_VARIABLE("phi0", trackPhi0, R"DOC(
605 Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
606 momentum in the :math:`r-\phi` plane.
607 
608 Returns NaN if called for something other than a track-based particle.
609  )DOC", "rad");
610  REGISTER_VARIABLE("omega", trackOmega, R"DOC(
611 Returns the tracking parameter :math:`\omega`, the curvature of the track.
612 
613 Returns NaN if called for something other than a track-based particle.
614  )DOC", ":math:`\\text{cm}^{-1}`");
615  REGISTER_VARIABLE("z0", trackZ0, R"DOC(
616 Returns the tracking parameter :math:`z_0`, the z-coordinate of the
617 point-of-closest-approach (POCA).
618 
619 .. note::
620 
621  Tracking parameters are with respect to the origin (0,0,0). For the
622  POCA with respect to the measured beam interaction point, see
623  :b2:var:`dz` (you probably want this unless you're doing a tracking
624  study or some debugging).
625 
626 Returns NaN if called for something other than a track-based particle.
627  )DOC", "cm");
628  REGISTER_VARIABLE("tanLambda", trackTanLambda, R"DOC(
629 Returns :math:`\tan\lambda`, the slope of the track in the :math:`r-z` plane.
630 
631 Returns NaN if called for something other than a track-based particle.
632  )DOC");
633  REGISTER_VARIABLE("d0Err", trackD0Error, R"DOC(
634 Returns the uncertainty on :math:`d_0`, the signed distance to the
635 point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
636 
637 .. seealso:: :b2:var:`d0`, :b2:var:`d0Pull`
638 
639 Returns NaN if called for something other than a track-based particle.
640  )DOC", "cm");
641  REGISTER_VARIABLE("phi0Err", trackPhi0Error, R"DOC(
642 Returns the uncertainty on :math:`\phi_0`, the angle of the transverse momentum
643 in the :math:`r-\phi` plane.
644 
645 .. seealso:: :b2:var:`phi0`, :b2:var:`phi0Pull`
646 
647 Returns NaN if called for something other than a track-based particle.
648  )DOC", "rad");
649  REGISTER_VARIABLE("omegaErr", trackOmegaError, R"DOC(
650 Returns the uncertainty on :math:`\omega`, the curvature of the track.
651 
652 .. seealso:: :b2:var:`omega`, :b2:var:`omegaPull`
653 
654 Returns NaN if called for something other than a track-based particle.
655  )DOC", ":math:`\\text{cm}^{-1}`");
656  REGISTER_VARIABLE("z0Err", trackZ0Error, R"DOC(
657 Returns the uncertainty on :math:`z_0`, the z-coordinate of the
658 point-of-closest-approach (POCA).
659 
660 .. seealso:: :b2:var:`z0`, :b2:var:`z0Pull`
661 
662 Returns NaN if called for something other than a track-based particle."
663  )DOC", "cm");
664  REGISTER_VARIABLE("tanLambdaErr", trackTanLambdaError, R"DOC(
665 Returns the uncertainty on :math:`\tan\lambda`, the slope of the track in the
666 :math:`r-z` plane.
667 
668 .. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaPull`
669 
670 Returns NaN if called for something other than a track-based particle.
671  )DOC");
672  REGISTER_VARIABLE("trackFitCovariance(i, j)", trackFitCovariance, R"DOC(
673  The track fit covariance matrix element corresponding to the two indices is returned.
674  This is the association between integers and parameters:
675 
676  * 0: :math:`d_0`
677  * 1: :math:`\phi_0`
678  * 2: :math:`\omega`
679  * 3: :math:`z_0`
680  * 4: :math:`\tan\lambda`
681 
682  .. note::
683 
684  The covariance is returned. This means that the return value can be negative.
685  Furthermore, it's the squared value of the track fit error variables :b2:var:`d0Err`, etc.
686  when selecting the diagonal entries.
687 
688  )DOC");
689  REGISTER_VARIABLE("pValue", trackPValue, R"DOC(
690 The :math:`\chi^2` probability of the **track** fit.
691 
692 .. note::
693 
694  This is the p-value of the track-fit. It does not get updated after
695  vertex fitting or kinematic fitting, and is meaningless for composite
696  particles.
697 
698  See :b2:var:`chiProb` (you probably want this for high-level analysis).
699 
700 Returns NaN if called for something other than a track-based particle.
701  )DOC");
702  REGISTER_VARIABLE("trackFitHypothesisPDG", trackFitHypothesisPDG, R"DOC(
703 Returns the PDG code of the track hypothesis actually used for the fit.
704 Returns NaN if called for something other than a track-based particle.
705  )DOC");
706  REGISTER_VARIABLE("trackNECLClusters", trackNECLClusters, R"DOC(
707 Returns a count of the number of ECLClusters matched to the track. This is
708 always 0 or 1 with newer versions of ECL reconstruction.
709 
710 .. note::
711 
712  For high-level analysis it is recommended to require the presence of a
713  matched ECL cluster along with a minimum energy requirement. A
714  track-based particle will have a clusterE if it is matched (NaN if
715  there is no cluster match for the track.
716 
717  .. code-block:: python
718 
719  import modularAnalysis as ma
720  # minimum energy of 200 MeV
721  ma.fillParticleList("e+:clusters", "clusterE > 0.2", path)
722 
723  # these two are equivalent
724  ma.fillParticleList("e+:unmatched", "isNAN(clusterE) == 1", path)
725  ma.fillParticleList("e+:unmatched2", "trackNECLClusters == 0", path)
726 
727 Returns NaN if called for something other than a track-based particle.
728  )DOC");
729  REGISTER_VARIABLE("helixExtTheta(radius [cm], z fwd [cm], z bwd [cm], useHighestProbMass=0)", trackHelixExtTheta,
730  "Returns theta of extrapolated helix parameters. If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.",
731  "rad");
732  REGISTER_VARIABLE("helixExtPhi(radius, z fwd, z bwd, useHighestProbMass=0)", trackHelixExtPhi,
733  "Returns phi of extrapolated helix parameters. If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.",
734  "rad");
735 
736  REGISTER_VARIABLE("nExtraCDCHits", nExtraCDCHits, R"DOC(
737 [Eventbased] The number of CDC hits in the event not assigned to any track.
738 
739 Returns NaN if there is no event-level tracking information available.
740  )DOC");
741  REGISTER_VARIABLE("nExtraCDCHitsPostCleaning", nExtraCDCHitsPostCleaning, R"DOC(
742 [Eventbased] Returns a count of the number of CDC hits in the event not assigned
743 to any track nor very likely beam background (i.e. hits that survive a cleanup
744 selection).
745 
746 Returns NaN if there is no event-level tracking information available.
747  )DOC");
748  REGISTER_VARIABLE("hasExtraCDCHitsInLayer(i)", hasExtraCDCHitsInLayer, R"DOC(
749 [Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC layer,
750 0 otherwise.
751 
752 Returns NaN if there is no event-level tracking information available.
753  )DOC");
754  REGISTER_VARIABLE("hasExtraCDCHitsInSuperLayer(i)", hasExtraCDCHitsInSuperLayer, R"DOC(
755 [Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC
756 SuperLayer, 0 otherwise.
757 
758 Returns NaN if there is no event-level tracking information available.
759  )DOC");
760  REGISTER_VARIABLE("nExtraCDCSegments", nExtraCDCSegments, R"DOC(
761 [Eventbased] Returns the number of CDC segments not assigned to any track.
762 
763 Returns NaN if there is no event-level tracking information available.
764  )DOC");
765  // TODO: once the Tracking group fill the dataobject these can be
766  // uncommented - at the moment they are not filled, so leave out
767  //REGISTER_VARIABLE("nExtraVXDHitsInLayer(i)", nExtraVXDHitsInLayer,
768  //"[Eventbased] The number VXD hits not assigned in the specified VXD layer");
769  //REGISTER_VARIABLE("nExtraVXDHits", nExtraVXDHits, "[Eventbased] The number of VXD hits not assigned to any track");
770  //REGISTER_VARIABLE("svdFirstSampleTime", svdFirstSampleTime, "[Eventbased] The time of first SVD sample relatvie to event T0");
771  REGISTER_VARIABLE("trackFindingFailureFlag", trackFindingFailureFlag, R"DOC(
772 [Eventbased] Returns a flag set by the tracking if there is reason to assume
773 there was a track in the event missed by the tracking, or the track finding was
774 (partly) aborted for this event.
775 
776 Returns NaN if there is no event-level tracking information available.
777  )DOC");
778 
779  REGISTER_VARIABLE("isTrackFlippedAndRefitted", isTrackFlippedAndRefitted, R"DOC(
780 Returns 1 if the charged final state particle comes from a track that has been flipped and refitted
781 at the end of the reconstruction chain, in particular after the outer detector reconstruction.
782  )DOC");
783 
784  REGISTER_VARIABLE("trackTime", getTrackTime, R"DOC(
785 Returns the time at which the track is produced relative to the time of the collision (given by SVD EventT0).
786 Both the time of the collision and the track time are computed using only SVD hits.
787 Returns NaN if SVD EventT0 is NaN, or if no SVD Hits are attached to the track.
788 For more details, see :ref:`Time Extraction <tracking_eventTimeExtraction>` page.
789  )DOC", "ns");
790  }
792 }
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
Definition: BFieldManager.h:61
EDetector
Enum for identifying the detector components (detector and subdetector).
Definition: Const.h:42
@ c_nPhotons
CR is split into n photons (N1)
This class represents an ideal helix in perigee parameterization.
Definition: Helix.h:59
double getOmega() const
Getter for omega, which is a signed curvature measure of the track.
Definition: Helix.h:387
double getD0() const
Getter for d0, which is the signed distance to the perigee in the r-phi plane.
Definition: Helix.h:372
double getTanLambda() const
Getter for tan lambda, which is the z over two dimensional arc length slope of the track.
Definition: Helix.h:393
double getZ0() const
Getter for z0, which is the z coordinate of the perigee.
Definition: Helix.h:390
double getPhi0() const
Getter for phi0, which is the azimuth angle of the transverse momentum at the perigee.
Definition: Helix.h:378
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
Definition: Particle.cc:972
Values of the result of a track fit with a given particle hypothesis.
UncertainHelix getUncertainHelix() const
Conversion to framework Uncertain Helix (i.e., with covariance).
This class represents an ideal helix in perigee parameterization including the covariance matrix of t...
const TMatrixDSym & getCovariance() const
Getter for covariance matrix of perigee parameters in matrix form.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23