Belle II Software  light-2403-persian
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 header.
10 #include <analysis/variables/TrackVariables.h>
11 
12 // include VariableManager
13 #include <analysis/VariableManager/Manager.h>
14 
15 #include <analysis/dataobjects/Particle.h>
16 #include <analysis/utility/DetectorSurface.h>
17 
18 // framework - DataStore
19 #include <framework/datastore/StoreObjPtr.h>
20 #include <framework/dataobjects/Helix.h>
21 
22 // dataobjects from the MDST
23 #include <mdst/dataobjects/Track.h>
24 #include <mdst/dataobjects/MCParticle.h>
25 #include <mdst/dataobjects/TrackFitResult.h>
26 #include <mdst/dataobjects/EventLevelTrackingInfo.h>
27 #include <mdst/dataobjects/HitPatternVXD.h>
28 #include <mdst/dataobjects/ECLCluster.h>
29 
30 // framework aux
31 #include <framework/logging/Logger.h>
32 
33 #include <cmath>
34 
35 namespace Belle2 {
40  namespace Variable {
41 
43 
44  double trackNHits(const Particle* part, const Const::EDetector& det)
45  {
46  auto trackFit = part->getTrackFitResult();
47  if (!trackFit) return Const::doubleNaN;
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 Const::doubleNaN;
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 Const::doubleNaN;
89  return trackFit->getNDF();
90  }
91 
92  double trackChi2(const Particle* part)
93  {
94  auto trackFit = part->getTrackFitResult();
95  if (!trackFit) return Const::doubleNaN;
96  return trackFit->getChi2();
97  }
98 
99  double trackFirstSVDLayer(const Particle* part)
100  {
101  auto trackFit = part->getTrackFitResult();
102  if (!trackFit) return Const::doubleNaN;
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 Const::doubleNaN;
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 Const::doubleNaN;
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 Const::doubleNaN;
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 Const::doubleNaN;
151  return trackFit->getD0();
152  }
153 
154  double trackPhi0(const Particle* part)
155  {
156  auto trackFit = part->getTrackFitResult();
157  if (!trackFit) return Const::doubleNaN;
158  return trackFit->getPhi0();
159  }
160 
161  double trackOmega(const Particle* part)
162  {
163  auto trackFit = part->getTrackFitResult();
164  if (!trackFit) return Const::doubleNaN;
165  return trackFit->getOmega();
166  }
167 
168  double trackZ0(const Particle* part)
169  {
170  auto trackFit = part->getTrackFitResult();
171  if (!trackFit) return Const::doubleNaN;
172  return trackFit->getZ0();
173  }
174 
175  double trackTanLambda(const Particle* part)
176  {
177  auto trackFit = part->getTrackFitResult();
178  if (!trackFit) return Const::doubleNaN;
179  return trackFit->getTanLambda();
180  }
181 
182  double trackD0Error(const Particle* part)
183  {
184  auto trackFit = part->getTrackFitResult();
185  if (!trackFit) return Const::doubleNaN;
186 
187  double errorSquared = trackFit->getCovariance5()[0][0];
188  if (errorSquared <= 0) return Const::doubleNaN;
189  return sqrt(errorSquared);
190  }
191 
192  double trackPhi0Error(const Particle* part)
193  {
194  auto trackFit = part->getTrackFitResult();
195  if (!trackFit) return Const::doubleNaN;
196 
197  double errorSquared = trackFit->getCovariance5()[1][1];
198  if (errorSquared <= 0) return Const::doubleNaN;
199  return sqrt(errorSquared);
200  }
201 
202  double trackOmegaError(const Particle* part)
203  {
204  auto trackFit = part->getTrackFitResult();
205  if (!trackFit) return Const::doubleNaN;
206 
207  double errorSquared = trackFit->getCovariance5()[2][2];
208  if (errorSquared <= 0) return Const::doubleNaN;
209  return sqrt(errorSquared);
210  }
211 
212  double trackZ0Error(const Particle* part)
213  {
214  auto trackFit = part->getTrackFitResult();
215  if (!trackFit) return Const::doubleNaN;
216 
217  double errorSquared = trackFit->getCovariance5()[3][3];
218  if (errorSquared <= 0) return Const::doubleNaN;
219  return sqrt(errorSquared);
220  }
221 
222  double trackTanLambdaError(const Particle* part)
223  {
224  auto trackFit = part->getTrackFitResult();
225  if (!trackFit) return Const::doubleNaN;
226 
227  double errorSquared = trackFit->getCovariance5()[4][4];
228  if (errorSquared <= 0) return Const::doubleNaN;
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 Const::doubleNaN;
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 Const::doubleNaN;
249  return trackFit->getPValue();
250  }
251 
252  double trackFitHypothesisPDG(const Particle* part)
253  {
254  auto trackFit = part->getTrackFitResult();
255  if (!trackFit) return Const::doubleNaN;
256  return trackFit->getParticleType().getPDGCode();
257  }
258 
259  double trackNECLClusters(const Particle* part)
260  {
261  const Track* track = part->getTrack();
262  if (!track) return Const::doubleNaN;
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 TrackFitResult* trackFit, const std::vector<double>& pars)
274  {
275  const double r = pars[0];
276  const double zfwd = pars[1];
277  const double zbwd = pars[2];
278 
279  // get helix and parameters
280  const double z0 = trackFit->getZ0();
281  const double tanlambda = trackFit->getTanLambda();
282  const Helix h = trackFit->getHelix();
283 
284  // extrapolate to radius
285  const double arcLength = h.getArcLength2DAtCylindricalR(r);
286  const double lHelixRadius = arcLength > 0 ? arcLength : std::numeric_limits<double>::max();
287 
288  // extrapolate to FWD z
289  const double lFWD = (zfwd - z0) / tanlambda > 0 ? (zfwd - z0) / tanlambda : std::numeric_limits<double>::max();
290 
291  // extrapolate to BWD z
292  const double lBWD = (zbwd - z0) / tanlambda > 0 ? (zbwd - z0) / tanlambda : std::numeric_limits<double>::max();
293 
294  // pick smallest arclength
295  const double l = std::min({lHelixRadius, lFWD, lBWD});
296 
297  return h.getPositionAtArcLength2D(l);
298  }
299 
300  B2Vector3D getPositionOnHelix(const Particle* part, const std::vector<double>& pars)
301  {
302  if (pars.size() == 4 and pars[3]) {
303  const Track* track = part->getTrack();
304  if (!track)
305  return vecNaN;
306 
307  auto highestProbMass = part->getMostLikelyTrackFitResult().first;
308  const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(highestProbMass);
309  return getPositionOnHelix(trackFit, pars);
310  } else {
311  const TrackFitResult* trackFit = part->getTrackFitResult();
312  return getPositionOnHelix(trackFit, pars);
313  }
314  }
315 
316  // returns extrapolated theta position based on helix parameters
317  double trackHelixExtTheta(const Particle* part, const std::vector<double>& pars)
318  {
319  const auto nParams = pars.size();
320  if (nParams != 3 && nParams != 4) {
321  B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtTheta.");
322  }
323 
324  B2Vector3D position = getPositionOnHelix(part, pars);
325  if (position == vecNaN) return Const::doubleNaN;
326  return position.Theta();
327  }
328 
329  // returns extrapolated phi position based on helix parameters
330  double trackHelixExtPhi(const Particle* part, const std::vector<double>& pars)
331  {
332  const auto nParams = pars.size();
333  if (nParams != 3 && nParams != 4) {
334  B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtPhi.");
335  }
336 
337  B2Vector3D position = getPositionOnHelix(part, pars);
338  if (position == vecNaN) return Const::doubleNaN;
339  return position.Phi();
340  }
341 
342  Manager::FunctionPtr trackHelixExtThetaOnDet(const std::vector<std::string>& arguments)
343  {
344  if (arguments.size() != 1 && arguments.size() != 2)
345  B2FATAL("Exactly one (+1 optional) parameter (detector_surface_name, [useHighestProbMass]) is required for helixExtThetaOnDet.");
346 
347  std::vector<double> parameters(3);
348  const std::string det = arguments[0];
350  parameters[0] = DetectorSurface::detToSurfBoundaries.at(det).m_rho;
351  parameters[1] = DetectorSurface::detToSurfBoundaries.at(det).m_zfwd;
352  parameters[2] = DetectorSurface::detToSurfBoundaries.at(det).m_zbwd;
354  parameters[0] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_rho;
355  parameters[1] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zfwd;
356  parameters[2] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zbwd;
357  } else
358  B2FATAL("Given detector surface name is not supported.");
359 
360  if (arguments.size() == 2)
361  parameters.push_back(std::stod(arguments[1]));
362 
363  auto func = [parameters](const Particle * part) -> double {
364 
365  B2Vector3D position = getPositionOnHelix(part, parameters);
366  if (position == vecNaN) return Const::doubleNaN;
367  return position.Theta();
368  };
369  return func;
370  }
371 
372  Manager::FunctionPtr trackHelixExtPhiOnDet(const std::vector<std::string>& arguments)
373  {
374  if (arguments.size() != 1 && arguments.size() != 2)
375  B2FATAL("Exactly one (+1 optional) parameter (detector_surface_name, [useHighestProbMass]) is required for helixExtPhiOnDet.");
376 
377  std::vector<double> parameters(3);
378  const std::string det = arguments[0];
380  parameters[0] = DetectorSurface::detToSurfBoundaries.at(det).m_rho;
381  parameters[1] = DetectorSurface::detToSurfBoundaries.at(det).m_zfwd;
382  parameters[2] = DetectorSurface::detToSurfBoundaries.at(det).m_zbwd;
384  parameters[0] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_rho;
385  parameters[1] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zfwd;
386  parameters[2] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zbwd;
387  } else
388  B2FATAL("Given detector surface name is not supported.");
389 
390  if (arguments.size() == 2)
391  parameters.push_back(std::stod(arguments[1]));
392 
393  auto func = [parameters](const Particle * part) -> double {
394 
395  B2Vector3D position = getPositionOnHelix(part, parameters);
396  if (position == vecNaN) return Const::doubleNaN;
397  return position.Phi();
398  };
399  return func;
400  }
401 
402 
403  /***************************************************
404  * Event level tracking quantities
405  */
406 
407  // The number of CDC hits in the event not assigned to any track
408  double nExtraCDCHits(const Particle*)
409  {
410  StoreObjPtr<EventLevelTrackingInfo> elti;
411  if (!elti) return Const::doubleNaN;
412  return elti->getNCDCHitsNotAssigned();
413  }
414 
415  // The number of CDC hits in the event not assigned to any track nor very
416  // likely beam background (i.e. hits that survive a cleanup selection)
417  double nExtraCDCHitsPostCleaning(const Particle*)
418  {
419  StoreObjPtr<EventLevelTrackingInfo> elti;
420  if (!elti) return Const::doubleNaN;
421  return elti->getNCDCHitsNotAssignedPostCleaning();
422  }
423 
424  // Check for the presence of a non-assigned hit in the specified CDC layer
425  double hasExtraCDCHitsInLayer(const Particle*, const std::vector<double>& layer)
426  {
427  StoreObjPtr<EventLevelTrackingInfo> elti;
428  if (!elti) return Const::doubleNaN;
429  int ilayer = std::lround(layer[0]);
430  return elti->hasCDCLayer(ilayer);
431  }
432 
433  // Check for the presence of a non-assigned hit in the specified CDC SuperLayer
434  double hasExtraCDCHitsInSuperLayer(const Particle*, const std::vector<double>& layer)
435  {
436  StoreObjPtr<EventLevelTrackingInfo> elti;
437  if (!elti) return Const::doubleNaN;
438  int ilayer = std::lround(layer[0]);
439  return elti->hasCDCSLayer(ilayer);
440  }
441 
442  // The number of segments that couldn't be assigned to any track
443  double nExtraCDCSegments(const Particle*)
444  {
445  StoreObjPtr<EventLevelTrackingInfo> elti;
446  if (!elti) return Const::doubleNaN;
447  return elti->getNCDCSegments();
448  }
449 
450  // The number of VXD hits not assigned to any track in the specified layer
451  double nExtraVXDHitsInLayer(const Particle*, const std::vector<double>& layer)
452  {
453  StoreObjPtr<EventLevelTrackingInfo> elti;
454  if (!elti) return Const::doubleNaN;
455  int ilayer = std::lround(layer[0]);
456  return elti->getNVXDClustersInLayer(ilayer);
457  }
458 
459  // The number of VXD hits not assigned to any track
460  double nExtraVXDHits(const Particle*)
461  {
462  StoreObjPtr<EventLevelTrackingInfo> elti;
463  if (!elti) return Const::doubleNaN;
464  double out = 0.0;
465  for (uint16_t ilayer = 1; ilayer < 7; ++ilayer)
466  out += elti->getNVXDClustersInLayer(ilayer);
467  return out;
468  }
469 
470  // time of first SVD sample relative to event T0
471  double svdFirstSampleTime(const Particle*)
472  {
473  StoreObjPtr<EventLevelTrackingInfo> elti;
474  if (!elti) return Const::doubleNaN;
475  return elti->getSVDFirstSampleTime();
476  }
477 
478  // A flag set by the tracking if there is reason to assume there was a track
479  // in the event missed by the tracking or the track finding was (partly) aborted
480  // for this event. Further information about this can be obtained from the flagBlock
481  // of the EventLevelTrackingInfo object.
482  double trackFindingFailureFlag(const Particle*)
483  {
484  StoreObjPtr<EventLevelTrackingInfo> elti;
485  if (!elti) return Const::doubleNaN;
486  return elti->hasAnErrorFlag();
487  }
488 
489  // Build a Helix from a MCParticle's kinematics. Does NOT check for null pointer!!!
490  Belle2::Helix getMCHelix(const MCParticle* mcparticle)
491  {
492  const ROOT::Math::XYZVector mcProdVertex = mcparticle->getVertex();
493  const ROOT::Math::XYZVector mcMomentum = mcparticle->getMomentum();
494  const double BzAtProdVertex = Belle2::BFieldManager::getFieldInTesla(mcProdVertex).Z();
495  const double mcParticleCharge = mcparticle->getCharge();
496  return Belle2::Helix(mcProdVertex, mcMomentum, mcParticleCharge, BzAtProdVertex);
497  }
498 
499  double getMCHelixParameterAtIndex(const Particle* particle, const int index)
500  {
501  if (!particle) return Const::doubleNaN;
502 
503  const MCParticle* mcparticle = particle->getMCParticle();
504  if (!mcparticle) return Const::doubleNaN;
505 
506  const Belle2::Helix mcHelix(getMCHelix(mcparticle));
507  const std::vector<double> mcHelixPars{mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
508  return mcHelixPars.at(index);
509  }
510 
511  double getHelixParameterPullAtIndex(const Particle* particle, const int index)
512  {
513  if (!particle) return Const::doubleNaN;
514 
515  const MCParticle* mcparticle = particle->getMCParticle();
516  if (!mcparticle) return Const::doubleNaN;
517 
518  const Belle2::TrackFitResult* trackfit = particle->getTrackFitResult();
519  if (!trackfit) return Const::doubleNaN;
520 
521  const Belle2::UncertainHelix measHelix = trackfit->getUncertainHelix();
522  const TMatrixDSym& measCovariance = measHelix.getCovariance();
523  const Belle2::Helix mcHelix(getMCHelix(mcparticle));
524 
525  const std::vector<double> mcHelixPars = {mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
526  const std::vector<double> measHelixPars = {measHelix.getD0(), measHelix.getPhi0(), measHelix.getOmega(), measHelix.getZ0(), measHelix.getTanLambda()};
527 
528  return (mcHelixPars.at(index) - measHelixPars.at(index)) / std::sqrt(measCovariance(index, index));
529  }
530 
531  double getHelixMCD0(const Particle* part) { return getMCHelixParameterAtIndex(part, 0); }
532  double getHelixMCPhi0(const Particle* part) { return getMCHelixParameterAtIndex(part, 1); }
533  double getHelixMCOmega(const Particle* part) { return getMCHelixParameterAtIndex(part, 2); }
534  double getHelixMCZ0(const Particle* part) { return getMCHelixParameterAtIndex(part, 3); }
535  double getHelixMCTanLambda(const Particle* part) { return getMCHelixParameterAtIndex(part, 4); }
536 
537  double getHelixD0Pull(const Particle* part)
538  {
539  return getHelixParameterPullAtIndex(part, 0);
540  }
541 
542  double getHelixPhi0Pull(const Particle* part)
543  {
544  return getHelixParameterPullAtIndex(part, 1);
545  }
546 
547  double getHelixOmegaPull(const Particle* part)
548  {
549  return getHelixParameterPullAtIndex(part, 2);
550  }
551 
552  double getHelixZ0Pull(const Particle* part)
553  {
554  return getHelixParameterPullAtIndex(part, 3);
555  }
556 
557  double getHelixTanLambdaPull(const Particle* part)
558  {
559  return getHelixParameterPullAtIndex(part, 4);
560  }
561 
562  double getTrackTime(const Particle* part)
563  {
564  const Track* track = part->getTrack();
565  if (!track) return Const::doubleNaN;
566  return track->getTrackTime();
567  }
568 
569  double isTrackFlippedAndRefitted(const Particle* part)
570  {
571  auto track = part->getTrack();
572  if (!track) return Const::doubleNaN;
573  return track->isFlippedAndRefitted() ? 1 : 0;
574  }
575 
576  double getTrackLength(const Particle* part)
577  {
578  auto trackFit = part->getTrackFitResult();
579  if (!trackFit) return Const::doubleNaN;
580 
581  const double lastCDCLayer = trackLastCDCLayer(part);
582  if (std::isnan(lastCDCLayer) or lastCDCLayer < 0)
583  return Const::doubleNaN;
584 
585  const double r = DetectorSurface::cdcWireRadiuses.at((int)lastCDCLayer);
586 
587  return trackFit->getHelix().getArcLength2DAtCylindricalR(r);
588  }
589 
590 
591  VARIABLE_GROUP("Tracking");
592 
593  REGISTER_VARIABLE("mcD0", getHelixMCD0, R"DOC(
594 Returns the MC value of :math:`d_0`, the signed distance to the
595 point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
596 
597 .. seealso:: :b2:var:`d0`
598 
599 Returns NaN if the particle is not related to any MCParticle.
600 
601 )DOC", "cm");
602  REGISTER_VARIABLE("mcPhi0", getHelixMCPhi0, R"DOC(
603 Returns the MC value of :math:`\phi_0`, the angle of the transverse momentum
604 in the :math:`r-\phi` plane.
605 
606 .. seealso:: :b2:var:`phi0`
607 
608 Returns NaN if the particle is not related to any MCParticle.
609 
610 )DOC", "rad");
611  REGISTER_VARIABLE("mcOmega", getHelixMCOmega, R"DOC(
612 Returns the MC value of :math:`\omega`, the curvature of the track.
613 
614 .. seealso:: :b2:var:`omega`
615 
616 Returns NaN if the particle is not related to any MCParticle.
617 
618 )DOC", ":math:`\\text{cm}^{-1}`");
619  REGISTER_VARIABLE("mcZ0", getHelixMCZ0, R"DOC(
620 Returns the MC value of :math:`z_0`, the z-coordinate of the
621 point-of-closest-approach (POCA).
622 
623 .. seealso:: :b2:var:`z0`
624 
625 Returns NaN if the particle is not related to any MCParticle.
626 
627 )DOC", "cm");
628  REGISTER_VARIABLE("mcTanLambda", getHelixMCTanLambda, R"DOC(
629 Returns the MC value of :math:`\tan\lambda`, the slope of the track in the
630 :math:`r-z` plane.
631 
632 .. seealso:: :b2:var:`tanLambda`
633 
634 Returns NaN if the particle is not related to any MCParticle.
635 )DOC");
636 
637  REGISTER_VARIABLE("d0Pull", getHelixD0Pull, R"DOC(
638 The pull of the tracking parameter :math:`d_0` for the reconstructed
639 pattern-recognition track, with respect to the MC track. That is:
640 
641 .. math::
642 
643  \frac{d_0^\textrm{MC} - d_0^\textrm{PR}}{\sigma_{d_0; \textrm{PR}}}
644 
645 .. seealso:: :b2:var:`d0`, :b2:var:`d0Err`
646 
647 Returns NaN if no MC particle is related or if called on something other than a
648 track-based particle.
649  )DOC");
650  REGISTER_VARIABLE("phi0Pull", getHelixPhi0Pull, R"DOC(
651 The pull of the tracking parameter :math:`\phi_0` for the reconstructed
652 pattern-recognition track, with respect to the MC track. That is:
653 
654 .. math::
655 
656  \frac{\phi_0^\textrm{MC} - \phi_0^\textrm{PR}}{\sigma_{\phi_0; \textrm{PR}}}
657 
658 .. seealso:: :b2:var:`phi0`, :b2:var:`phi0Err`
659 
660 Returns NaN if no MC particle is related or if called on something other than a
661 track-based particle.
662  )DOC");
663  REGISTER_VARIABLE("omegaPull", getHelixOmegaPull, R"DOC(
664 The pull of the tracking parameter :math:`\omega` for the reconstructed
665 pattern-recognition track, with respect to the MC track. That is:
666 
667 .. math::
668 
669  \frac{\omega^\textrm{MC} - \omega^\textrm{PR}}{\sigma_{\omega; \textrm{PR}}}
670 
671 .. seealso:: :b2:var:`omega`, :b2:var:`omegaErr`
672 
673 Returns NaN if no MC particle is related or if called on something other than a
674 track-based particle.
675  )DOC");
676  REGISTER_VARIABLE("z0Pull", getHelixZ0Pull, R"DOC(
677 The pull of the tracking parameter :math:`z_0` for the reconstructed
678 pattern-recognition track, with respect to the MC track. That is:
679 
680 .. math::
681 
682  \frac{z_0^\textrm{MC} - z_0^\textrm{PR}}{\sigma_{z_0; \textrm{PR}}}
683 
684 .. seealso:: :b2:var:`z0`, :b2:var:`z0Err`
685 
686 Returns NaN if no MC particle is related or if called on something other than a
687 track-based particle.
688  )DOC");
689  REGISTER_VARIABLE("tanLambdaPull", getHelixTanLambdaPull, R"DOC(
690 The pull of the tracking parameter :math:`\tan\lambda` for the reconstructed
691 pattern-recognition track, with respect to the MC track. That is:
692 
693 .. math::
694 
695  \frac{(\tan\lambda)^\textrm{MC} - (\tan\lambda)^\textrm{PR}}{\sigma_{\tan\lambda; \textrm{PR}}}
696 
697 .. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaErr`
698 
699 Returns NaN if no MC particle is related or if called on something other than a
700 track-based particle.
701  )DOC");
702  REGISTER_VARIABLE("nCDCHits", trackNCDCHits,
703  "The number of CDC hits associated to the track. Returns NaN if called for something other than a track-based particle.");
704  REGISTER_VARIABLE("nSVDHits", trackNSVDHits,
705  "The number of SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
706  REGISTER_VARIABLE("nPXDHits", trackNPXDHits,
707  "The number of PXD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
708  REGISTER_VARIABLE("nVXDHits", trackNVXDHits,
709  "The number of PXD and SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
710  REGISTER_VARIABLE("ndf", trackNDF, R"DOC(
711 Returns the number of degrees of freedom of the track fit.
712 
713 .. note::
714 
715  Note that this is not simply the number of hits -5 due to outlier hit
716  rejection.
717 
718 Returns NaN if called for something other than a track-based particle, or for
719 mdst files processed with basf2 versions older than ``release-05-01``.
720  )DOC");
721  REGISTER_VARIABLE("chi2", trackChi2, R"DOC(
722 Returns the :math:`\chi^2` of the track fit. This is actually computed based on
723 :b2:var:`pValue` and :b2:var:`ndf`.
724 
725 .. note:: Note that for :b2:var:`pValue` exactly equal to 0 it returns infinity.
726 
727 Returns NaN if called for something other than a track-based particle, or for
728 mdst files processed with basf2 versions older than ``release-05-01``.
729  )DOC");
730  REGISTER_VARIABLE("firstSVDLayer", trackFirstSVDLayer,
731  "The first activated SVD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
732  REGISTER_VARIABLE("firstPXDLayer", trackFirstPXDLayer,
733  "The first activated PXD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
734  REGISTER_VARIABLE("firstCDCLayer", trackFirstCDCLayer,
735  "The first activated CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
736  REGISTER_VARIABLE("lastCDCLayer", trackLastCDCLayer,
737  "The last CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
738  REGISTER_VARIABLE("d0", trackD0, R"DOC(
739 Returns the tracking parameter :math:`d_0`, the signed distance to the
740 point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
741 
742 .. note::
743 
744  Tracking parameters are with respect to the origin (0,0,0). For the
745  POCA with respect to the measured beam interaction point, see
746  :b2:var:`dr` (you probably want this unless you're doing a tracking
747  study or some debugging).
748 
749 Returns NaN if called for something other than a track-based particle.
750 
751 )DOC", "cm");
752  REGISTER_VARIABLE("phi0", trackPhi0, R"DOC(
753 Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
754 momentum in the :math:`r-\phi` plane.
755 
756 Returns NaN if called for something other than a track-based particle.
757 
758 )DOC", "rad");
759  REGISTER_VARIABLE("omega", trackOmega, R"DOC(
760 Returns the tracking parameter :math:`\omega`, the curvature of the track.
761 
762 Returns NaN if called for something other than a track-based particle.
763 
764 )DOC", ":math:`\\text{cm}^{-1}`");
765  REGISTER_VARIABLE("z0", trackZ0, R"DOC(
766 Returns the tracking parameter :math:`z_0`, the z-coordinate of the
767 point-of-closest-approach (POCA).
768 
769 .. note::
770 
771  Tracking parameters are with respect to the origin (0,0,0). For the
772  POCA with respect to the measured beam interaction point, see
773  :b2:var:`dz` (you probably want this unless you're doing a tracking
774  study or some debugging).
775 
776 Returns NaN if called for something other than a track-based particle.
777 
778 )DOC", "cm");
779  REGISTER_VARIABLE("tanLambda", trackTanLambda, R"DOC(
780 Returns :math:`\tan\lambda`, the slope of the track in the :math:`r-z` plane.
781 
782 Returns NaN if called for something other than a track-based particle.
783  )DOC");
784  REGISTER_VARIABLE("d0Err", trackD0Error, R"DOC(
785 Returns the uncertainty on :math:`d_0`, the signed distance to the
786 point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
787 
788 .. seealso:: :b2:var:`d0`, :b2:var:`d0Pull`
789 
790 Returns NaN if called for something other than a track-based particle.
791 
792 )DOC", "cm");
793  REGISTER_VARIABLE("phi0Err", trackPhi0Error, R"DOC(
794 Returns the uncertainty on :math:`\phi_0`, the angle of the transverse momentum
795 in the :math:`r-\phi` plane.
796 
797 .. seealso:: :b2:var:`phi0`, :b2:var:`phi0Pull`
798 
799 Returns NaN if called for something other than a track-based particle.
800 
801 )DOC", "rad");
802  REGISTER_VARIABLE("omegaErr", trackOmegaError, R"DOC(
803 Returns the uncertainty on :math:`\omega`, the curvature of the track.
804 
805 .. seealso:: :b2:var:`omega`, :b2:var:`omegaPull`
806 
807 Returns NaN if called for something other than a track-based particle.
808 
809 )DOC", ":math:`\\text{cm}^{-1}`");
810  REGISTER_VARIABLE("z0Err", trackZ0Error, R"DOC(
811 Returns the uncertainty on :math:`z_0`, the z-coordinate of the
812 point-of-closest-approach (POCA).
813 
814 .. seealso:: :b2:var:`z0`, :b2:var:`z0Pull`
815 
816 Returns NaN if called for something other than a track-based particle."
817 
818 )DOC", "cm");
819  REGISTER_VARIABLE("tanLambdaErr", trackTanLambdaError, R"DOC(
820 Returns the uncertainty on :math:`\tan\lambda`, the slope of the track in the
821 :math:`r-z` plane.
822 
823 .. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaPull`
824 
825 Returns NaN if called for something other than a track-based particle.
826  )DOC");
827  REGISTER_VARIABLE("trackFitCovariance(i, j)", trackFitCovariance, R"DOC(
828  The track fit covariance matrix element corresponding to the two indices is returned.
829  This is the association between integers and parameters:
830 
831  * 0: :math:`d_0`
832  * 1: :math:`\phi_0`
833  * 2: :math:`\omega`
834  * 3: :math:`z_0`
835  * 4: :math:`\tan\lambda`
836 
837  .. note::
838 
839  The covariance is returned. This means that the return value can be negative.
840  Furthermore, it's the squared value of the track fit error variables :b2:var:`d0Err`, etc.
841  when selecting the diagonal entries.
842 
843  )DOC");
844  REGISTER_VARIABLE("pValue", trackPValue, R"DOC(
845 The :math:`\chi^2` probability of the **track** fit.
846 
847 .. note::
848 
849  This is the p-value of the track-fit. It does not get updated after
850  vertex fitting or kinematic fitting, and is meaningless for composite
851  particles.
852 
853  See :b2:var:`chiProb` (you probably want this for high-level analysis).
854 
855 Returns NaN if called for something other than a track-based particle.
856  )DOC");
857  REGISTER_VARIABLE("trackFitHypothesisPDG", trackFitHypothesisPDG, R"DOC(
858 Returns the PDG code of the track hypothesis actually used for the fit.
859 Returns NaN if called for something other than a track-based particle.
860  )DOC");
861  REGISTER_VARIABLE("trackNECLClusters", trackNECLClusters, R"DOC(
862 Returns a count of the number of ECLClusters matched to the track. This is
863 always 0 or 1 with newer versions of ECL reconstruction.
864 
865 .. note::
866 
867  For high-level analysis it is recommended to require the presence of a
868  matched ECL cluster along with a minimum energy requirement. A
869  track-based particle will have a clusterE if it is matched (NaN if
870  there is no cluster match for the track.
871 
872  .. code-block:: python
873 
874  import modularAnalysis as ma
875  # minimum energy of 200 MeV
876  ma.fillParticleList("e+:clusters", "clusterE > 0.2", path)
877 
878  # these two are equivalent
879  ma.fillParticleList("e+:unmatched", "isNAN(clusterE) == 1", path)
880  ma.fillParticleList("e+:unmatched2", "trackNECLClusters == 0", path)
881 
882 Returns NaN if called for something other than a track-based particle.
883  )DOC");
884  REGISTER_VARIABLE("helixExtTheta(radius [cm], z fwd [cm], z bwd [cm], useHighestProbMass=0)", trackHelixExtTheta,
885  R"DOC(Returns theta of extrapolated helix parameters. If ``useHighestProbMass=1`` is set, the extrapolation will
886  use the track fit result for the mass hypothesis with the highest pValue.
887 
888  )DOC", "rad");
889  REGISTER_VARIABLE("helixExtPhi(radius, z fwd, z bwd, useHighestProbMass=0)", trackHelixExtPhi,
890  "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.\n\n",
891  "rad");
892 
893  REGISTER_METAVARIABLE("helixExtThetaOnDet(detector_surface_name, useHighestProbMass=0)", trackHelixExtThetaOnDet,
894  R"DOC(Returns theta of extrapolated helix parameters on the given detector surface. The unit of angle is ``rad``.
895  If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.
896  The supported detector surface names are ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
897  Also, the detector name with number of meaningful-layer is supported, e.g. ``'CDC8'``: last superlayer of CDC, ``'ECL1'``: mid-point of ECL.
898 
899  ..note:: You can find more information in `modularAnalysis.calculateTrackIsolation`.
900  )DOC", Manager::VariableDataType::c_double);
901  REGISTER_METAVARIABLE("helixExtPhiOnDet(detector_surface_name, useHighestProbMass=0)", trackHelixExtPhiOnDet,
902  R"DOC(Returns phi of extrapolated helix parameters on the given detector surface. The unit of angle is ``rad``.
903  If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.
904  The supported detector surface names are ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
905  Also, the detector name with number of meaningful-layer is supported, e.g. ``'CDC8'``: last superlayer of CDC, ``'ECL1'``: mid-point of ECL.
906 
907  ..note:: You can find more information in `modularAnalysis.calculateTrackIsolation`.
908  )DOC", Manager::VariableDataType::c_double);
909 
910 
911  REGISTER_VARIABLE("nExtraCDCHits", nExtraCDCHits, R"DOC(
912 [Eventbased] The number of CDC hits in the event not assigned to any track.
913 
914 Returns NaN if there is no event-level tracking information available.
915  )DOC");
916  REGISTER_VARIABLE("nExtraCDCHitsPostCleaning", nExtraCDCHitsPostCleaning, R"DOC(
917 [Eventbased] Returns a count of the number of CDC hits in the event not assigned
918 to any track nor very likely beam background (i.e. hits that survive a cleanup
919 selection).
920 
921 Returns NaN if there is no event-level tracking information available.
922  )DOC");
923  REGISTER_VARIABLE("hasExtraCDCHitsInLayer(i)", hasExtraCDCHitsInLayer, R"DOC(
924 [Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC layer,
925 0 otherwise.
926 
927 Returns NaN if there is no event-level tracking information available.
928  )DOC");
929  REGISTER_VARIABLE("hasExtraCDCHitsInSuperLayer(i)", hasExtraCDCHitsInSuperLayer, R"DOC(
930 [Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC
931 SuperLayer, 0 otherwise.
932 
933 Returns NaN if there is no event-level tracking information available.
934  )DOC");
935  REGISTER_VARIABLE("nExtraCDCSegments", nExtraCDCSegments, R"DOC(
936 [Eventbased] Returns the number of CDC segments not assigned to any track.
937 
938 Returns NaN if there is no event-level tracking information available.
939  )DOC");
940  // TODO: once the Tracking group fill the dataobject these can be
941  // uncommented - at the moment they are not filled, so leave out
942  //REGISTER_VARIABLE("nExtraVXDHitsInLayer(i)", nExtraVXDHitsInLayer,
943  //"[Eventbased] The number VXD hits not assigned in the specified VXD layer");
944  //REGISTER_VARIABLE("nExtraVXDHits", nExtraVXDHits, "[Eventbased] The number of VXD hits not assigned to any track");
945  //REGISTER_VARIABLE("svdFirstSampleTime", svdFirstSampleTime, "[Eventbased] The time of first SVD sample relatvie to event T0");
946  REGISTER_VARIABLE("trackFindingFailureFlag", trackFindingFailureFlag, R"DOC(
947 [Eventbased] Returns a flag set by the tracking if there is reason to assume
948 there was a track in the event missed by the tracking, or the track finding was
949 (partly) aborted for this event.
950 
951 Returns NaN if there is no event-level tracking information available.
952  )DOC");
953 
954  REGISTER_VARIABLE("isTrackFlippedAndRefitted", isTrackFlippedAndRefitted, R"DOC(
955 Returns 1 if the charged final state particle comes from a track that has been flipped and refitted
956 at the end of the reconstruction chain, in particular after the outer detector reconstruction.
957  )DOC");
958 
959  REGISTER_VARIABLE("trackTime", getTrackTime, R"DOC(
960 Returns the time at which the track is produced relative to the time of the collision (given by SVD EventT0).
961 Both the time of the collision and the track time are computed using only SVD hits.
962 Returns NaN if SVD EventT0 is NaN, or if no SVD Hits are attached to the track.
963 For more details, see :ref:`Time Extraction <tracking_eventTimeExtraction>` page.
964 
965 )DOC", "ns");
966 
967  REGISTER_VARIABLE("trackLength", getTrackLength, R"DOC(
968 Returns the arc length of the helix for the TrackFitResult associated with the particle.
969 The arc length is measured from the track origin to the radius of the CDC layer in which the Track has a hit.
970 Returns NaN if the particle has no CDC Hits.
971 
972 )DOC", "cm");
973 
974 
975  }
977 }
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
static const double doubleNaN
quiet_NaN
Definition: Const.h:694
@ 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
ROOT::Math::XYZVector getMomentum(const double bZ) const
Getter for vector of momentum at the perigee position.
Definition: Helix.cc:89
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:942
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.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
Definition: Manager.h:113
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:24
static const std::unordered_map< int, double > cdcWireRadiuses
CDC sense wire radiuses Values are take from cdc/data/CDC.xml.
static const std::unordered_map< std::string, DetSurfCylBoundaries > detToSurfBoundaries
Map that associates to each detector its valid cylindrical surface's boundaries.
static const std::unordered_map< std::string, DetSurfCylBoundaries > detLayerToSurfBoundaries
Map that associates to each detector layer its valid cylindrical surface's boundaries.