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 if (!trackFit) return vecNaN;
316 else return getPositionOnHelix(trackFit, pars);
317 } else {
318 const TrackFitResult* trackFit = part->getTrackFitResult();
319 if (!trackFit) return vecNaN;
320 else return getPositionOnHelix(trackFit, pars);
321 }
322 }
323
324 // returns extrapolated theta position based on helix parameters
325 double trackHelixExtTheta(const Particle* part, const std::vector<double>& pars)
326 {
327 const auto nParams = pars.size();
328 if (nParams != 3 && nParams != 4) {
329 B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtTheta.");
330 }
331
332 B2Vector3D position = getPositionOnHelix(part, pars);
333 if (position == vecNaN) return Const::doubleNaN;
334 return position.Theta();
335 }
336
337 // returns extrapolated phi position based on helix parameters
338 double trackHelixExtPhi(const Particle* part, const std::vector<double>& pars)
339 {
340 const auto nParams = pars.size();
341 if (nParams != 3 && nParams != 4) {
342 B2FATAL("Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtPhi.");
343 }
344
345 B2Vector3D position = getPositionOnHelix(part, pars);
346 if (position == vecNaN) return Const::doubleNaN;
347 return position.Phi();
348 }
349
350 Manager::FunctionPtr trackHelixExtThetaOnDet(const std::vector<std::string>& arguments)
351 {
352 if (arguments.size() != 1 && arguments.size() != 2)
353 B2FATAL("Exactly one (+1 optional) parameter (detector_surface_name, [useHighestProbMass]) is required for helixExtThetaOnDet.");
354
355 std::vector<double> parameters(3);
356 const std::string det = arguments[0];
358 parameters[0] = DetectorSurface::detToSurfBoundaries.at(det).m_rho;
359 parameters[1] = DetectorSurface::detToSurfBoundaries.at(det).m_zfwd;
360 parameters[2] = DetectorSurface::detToSurfBoundaries.at(det).m_zbwd;
362 parameters[0] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_rho;
363 parameters[1] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zfwd;
364 parameters[2] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zbwd;
365 } else
366 B2FATAL("Given detector surface name is not supported.");
367
368 if (arguments.size() == 2)
369 parameters.push_back(std::stod(arguments[1]));
370
371 auto func = [parameters](const Particle * part) -> double {
372
373 B2Vector3D position = getPositionOnHelix(part, parameters);
374 if (position == vecNaN) return Const::doubleNaN;
375 return position.Theta();
376 };
377 return func;
378 }
379
380 Manager::FunctionPtr trackHelixExtPhiOnDet(const std::vector<std::string>& arguments)
381 {
382 if (arguments.size() != 1 && arguments.size() != 2)
383 B2FATAL("Exactly one (+1 optional) parameter (detector_surface_name, [useHighestProbMass]) is required for helixExtPhiOnDet.");
384
385 std::vector<double> parameters(3);
386 const std::string det = arguments[0];
388 parameters[0] = DetectorSurface::detToSurfBoundaries.at(det).m_rho;
389 parameters[1] = DetectorSurface::detToSurfBoundaries.at(det).m_zfwd;
390 parameters[2] = DetectorSurface::detToSurfBoundaries.at(det).m_zbwd;
392 parameters[0] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_rho;
393 parameters[1] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zfwd;
394 parameters[2] = DetectorSurface::detLayerToSurfBoundaries.at(det).m_zbwd;
395 } else
396 B2FATAL("Given detector surface name is not supported.");
397
398 if (arguments.size() == 2)
399 parameters.push_back(std::stod(arguments[1]));
400
401 auto func = [parameters](const Particle * part) -> double {
402
403 B2Vector3D position = getPositionOnHelix(part, parameters);
404 if (position == vecNaN) return Const::doubleNaN;
405 return position.Phi();
406 };
407 return func;
408 }
409
410
411 /***************************************************
412 * Event level tracking quantities
413 */
414
415 // The number of CDC hits in the event not assigned to any track
416 double nExtraCDCHits(const Particle*)
417 {
418 StoreObjPtr<EventLevelTrackingInfo> elti;
419 if (!elti) return Const::doubleNaN;
420 return elti->getNCDCHitsNotAssigned();
421 }
422
423 // The number of CDC hits in the event not assigned to any track nor very
424 // likely beam background (i.e. hits that survive a cleanup selection)
425 double nExtraCDCHitsPostCleaning(const Particle*)
426 {
427 StoreObjPtr<EventLevelTrackingInfo> elti;
428 if (!elti) return Const::doubleNaN;
429 return elti->getNCDCHitsNotAssignedPostCleaning();
430 }
431
432 // Check for the presence of a non-assigned hit in the specified CDC layer
433 double hasExtraCDCHitsInLayer(const Particle*, const std::vector<double>& layer)
434 {
435 StoreObjPtr<EventLevelTrackingInfo> elti;
436 if (!elti) return Const::doubleNaN;
437 int ilayer = std::lround(layer[0]);
438 return elti->hasCDCLayer(ilayer);
439 }
440
441 // Check for the presence of a non-assigned hit in the specified CDC SuperLayer
442 double hasExtraCDCHitsInSuperLayer(const Particle*, const std::vector<double>& layer)
443 {
444 StoreObjPtr<EventLevelTrackingInfo> elti;
445 if (!elti) return Const::doubleNaN;
446 int ilayer = std::lround(layer[0]);
447 return elti->hasCDCSLayer(ilayer);
448 }
449
450 // The number of segments that couldn't be assigned to any track
451 double nExtraCDCSegments(const Particle*)
452 {
453 StoreObjPtr<EventLevelTrackingInfo> elti;
454 if (!elti) return Const::doubleNaN;
455 return elti->getNCDCSegments();
456 }
457
458 // The number of VXD hits not assigned to any track in the specified layer
459 double nExtraVXDHitsInLayer(const Particle*, const std::vector<double>& layer)
460 {
461 StoreObjPtr<EventLevelTrackingInfo> elti;
462 if (!elti) return Const::doubleNaN;
463 int ilayer = std::lround(layer[0]);
464 return elti->getNVXDClustersInLayer(ilayer);
465 }
466
467 // The number of VXD hits not assigned to any track
468 double nExtraVXDHits(const Particle*)
469 {
470 StoreObjPtr<EventLevelTrackingInfo> elti;
471 if (!elti) return Const::doubleNaN;
472 double out = 0.0;
473 for (uint16_t ilayer = 1; ilayer < 7; ++ilayer)
474 out += elti->getNVXDClustersInLayer(ilayer);
475 return out;
476 }
477
478 // time of first SVD sample relative to event T0
479 double svdFirstSampleTime(const Particle*)
480 {
481 StoreObjPtr<EventLevelTrackingInfo> elti;
482 if (!elti) return Const::doubleNaN;
483 return elti->getSVDFirstSampleTime();
484 }
485
486 // A flag set by the tracking if there is reason to assume there was a track
487 // in the event missed by the tracking or the track finding was (partly) aborted
488 // for this event. Further information about this can be obtained from the flagBlock
489 // of the EventLevelTrackingInfo object.
490 double trackFindingFailureFlag(const Particle*)
491 {
492 StoreObjPtr<EventLevelTrackingInfo> elti;
493 if (!elti) return Const::doubleNaN;
494 return elti->hasAnErrorFlag();
495 }
496
497 // Build a Helix from a MCParticle's kinematics. Does NOT check for null pointer!!!
498 Belle2::Helix getMCHelix(const MCParticle* mcparticle)
499 {
500 const ROOT::Math::XYZVector mcProdVertex = mcparticle->getVertex();
501 const ROOT::Math::XYZVector mcMomentum = mcparticle->getMomentum();
502 const double BzAtProdVertex = Belle2::BFieldManager::getFieldInTesla(mcProdVertex).Z();
503 const double mcParticleCharge = mcparticle->getCharge();
504 return Belle2::Helix(mcProdVertex, mcMomentum, mcParticleCharge, BzAtProdVertex);
505 }
506
507 double getMCHelixParameterAtIndex(const Particle* particle, const int index)
508 {
509 if (!particle) return Const::doubleNaN;
510
511 const MCParticle* mcparticle = particle->getMCParticle();
512 if (!mcparticle) return Const::doubleNaN;
513
514 const Belle2::Helix mcHelix(getMCHelix(mcparticle));
515 const std::vector<double> mcHelixPars{mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
516 return mcHelixPars.at(index);
517 }
518
519 double getHelixParameterPullAtIndex(const Particle* particle, const int index)
520 {
521 if (!particle) return Const::doubleNaN;
522
523 const MCParticle* mcparticle = particle->getMCParticle();
524 if (!mcparticle) return Const::doubleNaN;
525
526 const Belle2::TrackFitResult* trackfit = particle->getTrackFitResult();
527 if (!trackfit) return Const::doubleNaN;
528
529 const Belle2::UncertainHelix measHelix = trackfit->getUncertainHelix();
530 const TMatrixDSym& measCovariance = measHelix.getCovariance();
531 const Belle2::Helix mcHelix(getMCHelix(mcparticle));
532
533 const std::vector<double> mcHelixPars = {mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
534 const std::vector<double> measHelixPars = {measHelix.getD0(), measHelix.getPhi0(), measHelix.getOmega(), measHelix.getZ0(), measHelix.getTanLambda()};
535
536 return (mcHelixPars.at(index) - measHelixPars.at(index)) / std::sqrt(measCovariance(index, index));
537 }
538
539 double getHelixMCD0(const Particle* part) { return getMCHelixParameterAtIndex(part, 0); }
540 double getHelixMCPhi0(const Particle* part) { return getMCHelixParameterAtIndex(part, 1); }
541 double getHelixMCOmega(const Particle* part) { return getMCHelixParameterAtIndex(part, 2); }
542 double getHelixMCZ0(const Particle* part) { return getMCHelixParameterAtIndex(part, 3); }
543 double getHelixMCTanLambda(const Particle* part) { return getMCHelixParameterAtIndex(part, 4); }
544
545 double getHelixD0Pull(const Particle* part)
546 {
547 return getHelixParameterPullAtIndex(part, 0);
548 }
549
550 double getHelixPhi0Pull(const Particle* part)
551 {
552 return getHelixParameterPullAtIndex(part, 1);
553 }
554
555 double getHelixOmegaPull(const Particle* part)
556 {
557 return getHelixParameterPullAtIndex(part, 2);
558 }
559
560 double getHelixZ0Pull(const Particle* part)
561 {
562 return getHelixParameterPullAtIndex(part, 3);
563 }
564
565 double getHelixTanLambdaPull(const Particle* part)
566 {
567 return getHelixParameterPullAtIndex(part, 4);
568 }
569
570 double getTrackTime(const Particle* part)
571 {
572 const Track* track = part->getTrack();
573 if (!track) return Const::doubleNaN;
574 return track->getTrackTime();
575 }
576
577 double isTrackFlippedAndRefitted(const Particle* part)
578 {
579 auto track = part->getTrack();
580 if (!track) return Const::doubleNaN;
581 return track->isFlippedAndRefitted() ? 1 : 0;
582 }
583
584 double getTrackLength(const Particle* part)
585 {
586 auto trackFit = part->getTrackFitResult();
587 if (!trackFit) return Const::doubleNaN;
588
589 const double lastCDCLayer = trackLastCDCLayer(part);
590 if (std::isnan(lastCDCLayer) or lastCDCLayer < 0)
591 return Const::doubleNaN;
592
593 const double r = DetectorSurface::cdcWireRadiuses.at((int)lastCDCLayer);
594
595 return trackFit->getHelix().getArcLength2DAtCylindricalR(r);
596 }
597
598
599 VARIABLE_GROUP("Tracking");
600
601 REGISTER_VARIABLE("mcD0", getHelixMCD0, R"DOC(
602Returns the MC value of :math:`d_0`, the signed distance to the
603point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
604
605.. seealso:: :b2:var:`d0`
606
607Returns NaN if the particle is not related to any MCParticle.
608
609)DOC", "cm");
610 REGISTER_VARIABLE("mcPhi0", getHelixMCPhi0, R"DOC(
611Returns the MC value of :math:`\phi_0`, the angle of the transverse momentum
612in the :math:`r-\phi` plane.
613
614.. seealso:: :b2:var:`phi0`
615
616Returns NaN if the particle is not related to any MCParticle.
617
618)DOC", "rad");
619 REGISTER_VARIABLE("mcOmega", getHelixMCOmega, R"DOC(
620Returns the MC value of :math:`\omega`, the curvature of the track.
621
622.. seealso:: :b2:var:`omega`
623
624Returns NaN if the particle is not related to any MCParticle.
625
626)DOC", ":math:`\\text{cm}^{-1}`");
627 REGISTER_VARIABLE("mcZ0", getHelixMCZ0, R"DOC(
628Returns the MC value of :math:`z_0`, the z-coordinate of the
629point-of-closest-approach (POCA).
630
631.. seealso:: :b2:var:`z0`
632
633Returns NaN if the particle is not related to any MCParticle.
634
635)DOC", "cm");
636 REGISTER_VARIABLE("mcTanLambda", getHelixMCTanLambda, R"DOC(
637Returns the MC value of :math:`\tan\lambda`, the slope of the track in the
638:math:`r-z` plane.
639
640.. seealso:: :b2:var:`tanLambda`
641
642Returns NaN if the particle is not related to any MCParticle.
643)DOC");
644
645 REGISTER_VARIABLE("d0Pull", getHelixD0Pull, R"DOC(
646The pull of the tracking parameter :math:`d_0` for the reconstructed
647pattern-recognition track, with respect to the MC track. That is:
648
649.. math::
650
651 \frac{d_0^\textrm{MC} - d_0^\textrm{PR}}{\sigma_{d_0; \textrm{PR}}}
652
653.. seealso:: :b2:var:`d0`, :b2:var:`d0Err`
654
655Returns NaN if no MC particle is related or if called on something other than a
656track-based particle.
657 )DOC");
658 REGISTER_VARIABLE("phi0Pull", getHelixPhi0Pull, R"DOC(
659The pull of the tracking parameter :math:`\phi_0` for the reconstructed
660pattern-recognition track, with respect to the MC track. That is:
661
662.. math::
663
664 \frac{\phi_0^\textrm{MC} - \phi_0^\textrm{PR}}{\sigma_{\phi_0; \textrm{PR}}}
665
666.. seealso:: :b2:var:`phi0`, :b2:var:`phi0Err`
667
668Returns NaN if no MC particle is related or if called on something other than a
669track-based particle.
670 )DOC");
671 REGISTER_VARIABLE("omegaPull", getHelixOmegaPull, R"DOC(
672The pull of the tracking parameter :math:`\omega` for the reconstructed
673pattern-recognition track, with respect to the MC track. That is:
674
675.. math::
676
677 \frac{\omega^\textrm{MC} - \omega^\textrm{PR}}{\sigma_{\omega; \textrm{PR}}}
678
679.. seealso:: :b2:var:`omega`, :b2:var:`omegaErr`
680
681Returns NaN if no MC particle is related or if called on something other than a
682track-based particle.
683 )DOC");
684 REGISTER_VARIABLE("z0Pull", getHelixZ0Pull, R"DOC(
685The pull of the tracking parameter :math:`z_0` for the reconstructed
686pattern-recognition track, with respect to the MC track. That is:
687
688.. math::
689
690 \frac{z_0^\textrm{MC} - z_0^\textrm{PR}}{\sigma_{z_0; \textrm{PR}}}
691
692.. seealso:: :b2:var:`z0`, :b2:var:`z0Err`
693
694Returns NaN if no MC particle is related or if called on something other than a
695track-based particle.
696 )DOC");
697 REGISTER_VARIABLE("tanLambdaPull", getHelixTanLambdaPull, R"DOC(
698The pull of the tracking parameter :math:`\tan\lambda` for the reconstructed
699pattern-recognition track, with respect to the MC track. That is:
700
701.. math::
702
703 \frac{(\tan\lambda)^\textrm{MC} - (\tan\lambda)^\textrm{PR}}{\sigma_{\tan\lambda; \textrm{PR}}}
704
705.. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaErr`
706
707Returns NaN if no MC particle is related or if called on something other than a
708track-based particle.
709 )DOC");
710 REGISTER_VARIABLE("nCDCHits", trackNCDCHits,
711 "The number of CDC hits associated to the track. Returns NaN if called for something other than a track-based particle.");
712 REGISTER_VARIABLE("nSVDHits", trackNSVDHits,
713 "The number of SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
714 REGISTER_VARIABLE("nPXDHits", trackNPXDHits,
715 "The number of PXD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
716 REGISTER_VARIABLE("nVXDHits", trackNVXDHits,
717 "The number of PXD and SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
718 REGISTER_VARIABLE("ndf", trackNDF, R"DOC(
719Returns the number of degrees of freedom of the track fit.
720
721.. note::
722
723 Note that this is not simply the number of hits -5 due to outlier hit
724 rejection.
725
726Returns NaN if called for something other than a track-based particle, or for
727mdst files processed with basf2 versions older than ``release-05-01``.
728 )DOC");
729 REGISTER_VARIABLE("chi2", trackChi2, R"DOC(
730Returns the :math:`\chi^2` of the track fit. This is actually computed based on
731:b2:var:`pValue` and :b2:var:`ndf`.
732
733.. note:: Note that for :b2:var:`pValue` exactly equal to 0 it returns infinity.
734
735Returns NaN if called for something other than a track-based particle, or for
736mdst files processed with basf2 versions older than ``release-05-01``.
737 )DOC");
738 REGISTER_VARIABLE("firstSVDLayer", trackFirstSVDLayer,
739 "The first activated SVD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
740 REGISTER_VARIABLE("firstPXDLayer", trackFirstPXDLayer,
741 "The first activated PXD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
742 REGISTER_VARIABLE("firstCDCLayer", trackFirstCDCLayer,
743 "The first activated CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
744 REGISTER_VARIABLE("lastCDCLayer", trackLastCDCLayer,
745 "The last CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
746 REGISTER_VARIABLE("d0", trackD0, R"DOC(
747Returns the tracking parameter :math:`d_0`, the signed distance to the
748point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
749
750.. note::
751
752 Tracking parameters are with respect to the origin (0,0,0). For the
753 POCA with respect to the measured beam interaction point, see
754 :b2:var:`dr` (you probably want this unless you're doing a tracking
755 study or some debugging) and :b2:var:`d0FromIP`.
756
757Returns NaN if called for something other than a track-based particle.
758
759)DOC", "cm");
760 REGISTER_VARIABLE("phi0", trackPhi0, R"DOC(
761Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
762momentum in the :math:`r-\phi` plane.
763
764.. note::
765
766 Tracking parameters are with respect to the origin (0,0,0). For the
767 POCA with respect to the measured beam interaction point, see
768 :b2:var:`phi0FromIP`.
769
770Returns NaN if called for something other than a track-based particle.
771
772)DOC", "rad");
773 REGISTER_VARIABLE("omega", trackOmega, R"DOC(
774Returns the tracking parameter :math:`\omega`, the curvature of the track.
775
776Returns NaN if called for something other than a track-based particle.
777
778)DOC", ":math:`\\text{cm}^{-1}`");
779 REGISTER_VARIABLE("z0", trackZ0, R"DOC(
780Returns the tracking parameter :math:`z_0`, the z-coordinate of the
781point-of-closest-approach (POCA).
782
783.. note::
784
785 Tracking parameters are with respect to the origin (0,0,0). For the
786 POCA with respect to the measured beam interaction point, see
787 :b2:var:`dz` (you probably want this unless you're doing a tracking
788 study or some debugging) and :b2:var:`z0FromIP`.
789
790Returns NaN if called for something other than a track-based particle.
791
792)DOC", "cm");
793 REGISTER_VARIABLE("tanLambda", trackTanLambda, R"DOC(
794Returns :math:`\tan\lambda`, the slope of the track in the :math:`r-z` plane.
795
796Returns NaN if called for something other than a track-based particle.
797 )DOC");
798 REGISTER_VARIABLE("d0FromIP", trackD0FromIP, R"DOC(
799Returns the tracking parameter :math:`d_0`, the signed distance to the
800point-of-closest-approach (POCA) in the :math:`r-\phi` plane, with respect to the measured beam interaction point.
801
802Returns NaN if called for something other than a track-based particle.
803
804)DOC", "cm");
805 REGISTER_VARIABLE("z0FromIP", trackZ0FromIP, R"DOC(
806Returns the tracking parameter :math:`z_0`, the z-coordinate of the
807point-of-closest-approach (POCA), with respect to the measured beam interaction point.
808
809Returns NaN if called for something other than a track-based particle.
810
811)DOC", "cm");
812 REGISTER_VARIABLE("phi0FromIP", trackPhi0FromIP, R"DOC(
813Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
814momentum in the :math:`r-\phi` plane, with respect to the measured beam interaction point.
815
816Returns NaN if called for something other than a track-based particle.
817
818)DOC", "rad");
819 REGISTER_VARIABLE("d0Err", trackD0Error, R"DOC(
820Returns the uncertainty on :math:`d_0`, the signed distance to the
821point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
822
823.. seealso:: :b2:var:`d0`, :b2:var:`d0Pull`
824
825Returns NaN if called for something other than a track-based particle.
826
827)DOC", "cm");
828 REGISTER_VARIABLE("phi0Err", trackPhi0Error, R"DOC(
829Returns the uncertainty on :math:`\phi_0`, the angle of the transverse momentum
830in the :math:`r-\phi` plane.
831
832.. seealso:: :b2:var:`phi0`, :b2:var:`phi0Pull`
833
834Returns NaN if called for something other than a track-based particle.
835
836)DOC", "rad");
837 REGISTER_VARIABLE("omegaErr", trackOmegaError, R"DOC(
838Returns the uncertainty on :math:`\omega`, the curvature of the track.
839
840.. seealso:: :b2:var:`omega`, :b2:var:`omegaPull`
841
842Returns NaN if called for something other than a track-based particle.
843
844)DOC", ":math:`\\text{cm}^{-1}`");
845 REGISTER_VARIABLE("z0Err", trackZ0Error, R"DOC(
846Returns the uncertainty on :math:`z_0`, the z-coordinate of the
847point-of-closest-approach (POCA).
848
849.. seealso:: :b2:var:`z0`, :b2:var:`z0Pull`
850
851Returns NaN if called for something other than a track-based particle."
852
853)DOC", "cm");
854 REGISTER_VARIABLE("tanLambdaErr", trackTanLambdaError, R"DOC(
855Returns the uncertainty on :math:`\tan\lambda`, the slope of the track in the
856:math:`r-z` plane.
857
858.. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaPull`
859
860Returns NaN if called for something other than a track-based particle.
861 )DOC");
862 REGISTER_VARIABLE("trackFitCovariance(i, j)", trackFitCovariance, R"DOC(
863 The track fit covariance matrix element corresponding to the two indices is returned.
864 This is the association between integers and parameters:
865
866 * 0: :math:`d_0`
867 * 1: :math:`\phi_0`
868 * 2: :math:`\omega`
869 * 3: :math:`z_0`
870 * 4: :math:`\tan\lambda`
871
872 .. note::
873
874 The covariance is returned. This means that the return value can be negative.
875 Furthermore, it's the squared value of the track fit error variables :b2:var:`d0Err`, etc.
876 when selecting the diagonal entries.
877
878 )DOC");
879 REGISTER_VARIABLE("pValue", trackPValue, R"DOC(
880The :math:`\chi^2` probability of the **track** fit.
881
882.. note::
883
884 This is the p-value of the track-fit. It does not get updated after
885 vertex fitting or kinematic fitting, and is meaningless for composite
886 particles.
887
888 See :b2:var:`chiProb` (you probably want this for high-level analysis).
889
890Returns NaN if called for something other than a track-based particle.
891 )DOC");
892 REGISTER_VARIABLE("trackFitHypothesisPDG", trackFitHypothesisPDG, R"DOC(
893Returns the PDG code of the track hypothesis actually used for the fit.
894Returns NaN if called for something other than a track-based particle.
895 )DOC");
896 REGISTER_VARIABLE("trackNECLClusters", trackNECLClusters, R"DOC(
897Returns a count of the number of ECLClusters matched to the track. This is
898always 0 or 1 with newer versions of ECL reconstruction.
899
900.. note::
901
902 For high-level analysis it is recommended to require the presence of a
903 matched ECL cluster along with a minimum energy requirement. A
904 track-based particle will have a clusterE if it is matched (NaN if
905 there is no cluster match for the track.
906
907 .. code-block:: python
908
909 import modularAnalysis as ma
910 # minimum energy of 200 MeV
911 ma.fillParticleList("e+:clusters", "clusterE > 0.2", path)
912
913 # these two are equivalent
914 ma.fillParticleList("e+:unmatched", "isNAN(clusterE) == 1", path)
915 ma.fillParticleList("e+:unmatched2", "trackNECLClusters == 0", path)
916
917Returns NaN if called for something other than a track-based particle.
918 )DOC");
919 REGISTER_VARIABLE("helixExtTheta(radius [cm], z fwd [cm], z bwd [cm], useHighestProbMass=0)", trackHelixExtTheta,
920 R"DOC(Returns theta of extrapolated helix parameters. If ``useHighestProbMass=1`` is set, the extrapolation will
921 use the track fit result for the mass hypothesis with the highest pValue.
922
923 )DOC", "rad");
924 REGISTER_VARIABLE("helixExtPhi(radius, z fwd, z bwd, useHighestProbMass=0)", trackHelixExtPhi,
925 "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",
926 "rad");
927
928 REGISTER_METAVARIABLE("helixExtThetaOnDet(detector_surface_name, useHighestProbMass=0)", trackHelixExtThetaOnDet,
929 R"DOC(Returns theta of extrapolated helix parameters on the given detector surface. The unit of angle is ``rad``.
930 If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.
931 The supported detector surface names are ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
932 Also, the detector name with number of meaningful-layer is supported, e.g. ``'CDC8'``: last superlayer of CDC, ``'ECL1'``: mid-point of ECL.
933
934 ..note:: You can find more information in `modularAnalysis.calculateTrackIsolation`.
935 )DOC", Manager::VariableDataType::c_double);
936 REGISTER_METAVARIABLE("helixExtPhiOnDet(detector_surface_name, useHighestProbMass=0)", trackHelixExtPhiOnDet,
937 R"DOC(Returns phi of extrapolated helix parameters on the given detector surface. The unit of angle is ``rad``.
938 If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.
939 The supported detector surface names are ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
940 Also, the detector name with number of meaningful-layer is supported, e.g. ``'CDC8'``: last superlayer of CDC, ``'ECL1'``: mid-point of ECL.
941
942 ..note:: You can find more information in `modularAnalysis.calculateTrackIsolation`.
943 )DOC", Manager::VariableDataType::c_double);
944
945
946 REGISTER_VARIABLE("nExtraCDCHits", nExtraCDCHits, R"DOC(
947[Eventbased] The number of CDC hits in the event not assigned to any track.
948
949Returns NaN if there is no event-level tracking information available.
950 )DOC");
951 REGISTER_VARIABLE("nExtraCDCHitsPostCleaning", nExtraCDCHitsPostCleaning, R"DOC(
952[Eventbased] Returns a count of the number of CDC hits in the event not assigned
953to any track nor very likely beam background (i.e. hits that survive a cleanup
954selection).
955
956Returns NaN if there is no event-level tracking information available.
957 )DOC");
958 REGISTER_VARIABLE("hasExtraCDCHitsInLayer(i)", hasExtraCDCHitsInLayer, R"DOC(
959[Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC layer,
9600 otherwise.
961
962Returns NaN if there is no event-level tracking information available.
963 )DOC");
964 REGISTER_VARIABLE("hasExtraCDCHitsInSuperLayer(i)", hasExtraCDCHitsInSuperLayer, R"DOC(
965[Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC
966SuperLayer, 0 otherwise.
967
968Returns NaN if there is no event-level tracking information available.
969 )DOC");
970 REGISTER_VARIABLE("nExtraCDCSegments", nExtraCDCSegments, R"DOC(
971[Eventbased] Returns the number of CDC segments not assigned to any track.
972
973Returns NaN if there is no event-level tracking information available.
974 )DOC");
975 // TODO: once the Tracking group fill the dataobject these can be
976 // uncommented - at the moment they are not filled, so leave out
977 //REGISTER_VARIABLE("nExtraVXDHitsInLayer(i)", nExtraVXDHitsInLayer,
978 //"[Eventbased] The number VXD hits not assigned in the specified VXD layer");
979 //REGISTER_VARIABLE("nExtraVXDHits", nExtraVXDHits, "[Eventbased] The number of VXD hits not assigned to any track");
980 //REGISTER_VARIABLE("svdFirstSampleTime", svdFirstSampleTime, "[Eventbased] The time of first SVD sample relatvie to event T0");
981 REGISTER_VARIABLE("trackFindingFailureFlag", trackFindingFailureFlag, R"DOC(
982[Eventbased] Returns a flag set by the tracking if there is reason to assume
983there was a track in the event missed by the tracking, or the track finding was
984(partly) aborted for this event.
985
986Returns NaN if there is no event-level tracking information available.
987 )DOC");
988
989 REGISTER_VARIABLE("isTrackFlippedAndRefitted", isTrackFlippedAndRefitted, R"DOC(
990Returns 1 if the charged final state particle comes from a track that has been flipped and refitted
991at the end of the reconstruction chain, in particular after the outer detector reconstruction.
992 )DOC");
993
994 REGISTER_VARIABLE("trackTime", getTrackTime, R"DOC(
995Returns the time at which the track is produced relative to the time of the collision (given by SVD EventT0).
996Both the time of the collision and the track time are computed using only SVD hits.
997Returns NaN if SVD EventT0 is NaN, or if no SVD Hits are attached to the track.
998For more details, see :ref:`Time Extraction <tracking_eventTimeExtraction>` page.
999
1000)DOC", "ns");
1001
1002 REGISTER_VARIABLE("trackLength", getTrackLength, R"DOC(
1003Returns the arc length of the helix for the TrackFitResult associated with the particle.
1004The arc length is measured from the track origin to the radius of the CDC layer in which the Track has a hit.
1005Returns NaN if the particle has no CDC Hits.
1006
1007)DOC", "cm");
1008
1009
1010 }
1012}
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
Definition: BFieldManager.h:60
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:112
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.