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