Belle II Software light-2406-ragdoll
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
35namespace 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(
594Returns the MC value of :math:`d_0`, the signed distance to the
595point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
596
597.. seealso:: :b2:var:`d0`
598
599Returns NaN if the particle is not related to any MCParticle.
600
601)DOC", "cm");
602 REGISTER_VARIABLE("mcPhi0", getHelixMCPhi0, R"DOC(
603Returns the MC value of :math:`\phi_0`, the angle of the transverse momentum
604in the :math:`r-\phi` plane.
605
606.. seealso:: :b2:var:`phi0`
607
608Returns NaN if the particle is not related to any MCParticle.
609
610)DOC", "rad");
611 REGISTER_VARIABLE("mcOmega", getHelixMCOmega, R"DOC(
612Returns the MC value of :math:`\omega`, the curvature of the track.
613
614.. seealso:: :b2:var:`omega`
615
616Returns NaN if the particle is not related to any MCParticle.
617
618)DOC", ":math:`\\text{cm}^{-1}`");
619 REGISTER_VARIABLE("mcZ0", getHelixMCZ0, R"DOC(
620Returns the MC value of :math:`z_0`, the z-coordinate of the
621point-of-closest-approach (POCA).
622
623.. seealso:: :b2:var:`z0`
624
625Returns NaN if the particle is not related to any MCParticle.
626
627)DOC", "cm");
628 REGISTER_VARIABLE("mcTanLambda", getHelixMCTanLambda, R"DOC(
629Returns 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
634Returns NaN if the particle is not related to any MCParticle.
635)DOC");
636
637 REGISTER_VARIABLE("d0Pull", getHelixD0Pull, R"DOC(
638The pull of the tracking parameter :math:`d_0` for the reconstructed
639pattern-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
647Returns NaN if no MC particle is related or if called on something other than a
648track-based particle.
649 )DOC");
650 REGISTER_VARIABLE("phi0Pull", getHelixPhi0Pull, R"DOC(
651The pull of the tracking parameter :math:`\phi_0` for the reconstructed
652pattern-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
660Returns NaN if no MC particle is related or if called on something other than a
661track-based particle.
662 )DOC");
663 REGISTER_VARIABLE("omegaPull", getHelixOmegaPull, R"DOC(
664The pull of the tracking parameter :math:`\omega` for the reconstructed
665pattern-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
673Returns NaN if no MC particle is related or if called on something other than a
674track-based particle.
675 )DOC");
676 REGISTER_VARIABLE("z0Pull", getHelixZ0Pull, R"DOC(
677The pull of the tracking parameter :math:`z_0` for the reconstructed
678pattern-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
686Returns NaN if no MC particle is related or if called on something other than a
687track-based particle.
688 )DOC");
689 REGISTER_VARIABLE("tanLambdaPull", getHelixTanLambdaPull, R"DOC(
690The pull of the tracking parameter :math:`\tan\lambda` for the reconstructed
691pattern-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
699Returns NaN if no MC particle is related or if called on something other than a
700track-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(
711Returns 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
718Returns NaN if called for something other than a track-based particle, or for
719mdst files processed with basf2 versions older than ``release-05-01``.
720 )DOC");
721 REGISTER_VARIABLE("chi2", trackChi2, R"DOC(
722Returns 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
727Returns NaN if called for something other than a track-based particle, or for
728mdst 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(
739Returns the tracking parameter :math:`d_0`, the signed distance to the
740point-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
749Returns NaN if called for something other than a track-based particle.
750
751)DOC", "cm");
752 REGISTER_VARIABLE("phi0", trackPhi0, R"DOC(
753Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
754momentum in the :math:`r-\phi` plane.
755
756Returns NaN if called for something other than a track-based particle.
757
758)DOC", "rad");
759 REGISTER_VARIABLE("omega", trackOmega, R"DOC(
760Returns the tracking parameter :math:`\omega`, the curvature of the track.
761
762Returns 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(
766Returns the tracking parameter :math:`z_0`, the z-coordinate of the
767point-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
776Returns NaN if called for something other than a track-based particle.
777
778)DOC", "cm");
779 REGISTER_VARIABLE("tanLambda", trackTanLambda, R"DOC(
780Returns :math:`\tan\lambda`, the slope of the track in the :math:`r-z` plane.
781
782Returns NaN if called for something other than a track-based particle.
783 )DOC");
784 REGISTER_VARIABLE("d0Err", trackD0Error, R"DOC(
785Returns the uncertainty on :math:`d_0`, the signed distance to the
786point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
787
788.. seealso:: :b2:var:`d0`, :b2:var:`d0Pull`
789
790Returns NaN if called for something other than a track-based particle.
791
792)DOC", "cm");
793 REGISTER_VARIABLE("phi0Err", trackPhi0Error, R"DOC(
794Returns the uncertainty on :math:`\phi_0`, the angle of the transverse momentum
795in the :math:`r-\phi` plane.
796
797.. seealso:: :b2:var:`phi0`, :b2:var:`phi0Pull`
798
799Returns NaN if called for something other than a track-based particle.
800
801)DOC", "rad");
802 REGISTER_VARIABLE("omegaErr", trackOmegaError, R"DOC(
803Returns the uncertainty on :math:`\omega`, the curvature of the track.
804
805.. seealso:: :b2:var:`omega`, :b2:var:`omegaPull`
806
807Returns 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(
811Returns the uncertainty on :math:`z_0`, the z-coordinate of the
812point-of-closest-approach (POCA).
813
814.. seealso:: :b2:var:`z0`, :b2:var:`z0Pull`
815
816Returns NaN if called for something other than a track-based particle."
817
818)DOC", "cm");
819 REGISTER_VARIABLE("tanLambdaErr", trackTanLambdaError, R"DOC(
820Returns 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
825Returns 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(
845The :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
855Returns NaN if called for something other than a track-based particle.
856 )DOC");
857 REGISTER_VARIABLE("trackFitHypothesisPDG", trackFitHypothesisPDG, R"DOC(
858Returns the PDG code of the track hypothesis actually used for the fit.
859Returns NaN if called for something other than a track-based particle.
860 )DOC");
861 REGISTER_VARIABLE("trackNECLClusters", trackNECLClusters, R"DOC(
862Returns a count of the number of ECLClusters matched to the track. This is
863always 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
882Returns 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
914Returns 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
918to any track nor very likely beam background (i.e. hits that survive a cleanup
919selection).
920
921Returns 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,
9250 otherwise.
926
927Returns 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
931SuperLayer, 0 otherwise.
932
933Returns 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
938Returns 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
948there was a track in the event missed by the tracking, or the track finding was
949(partly) aborted for this event.
950
951Returns NaN if there is no event-level tracking information available.
952 )DOC");
953
954 REGISTER_VARIABLE("isTrackFlippedAndRefitted", isTrackFlippedAndRefitted, R"DOC(
955Returns 1 if the charged final state particle comes from a track that has been flipped and refitted
956at the end of the reconstruction chain, in particular after the outer detector reconstruction.
957 )DOC");
958
959 REGISTER_VARIABLE("trackTime", getTrackTime, R"DOC(
960Returns the time at which the track is produced relative to the time of the collision (given by SVD EventT0).
961Both the time of the collision and the track time are computed using only SVD hits.
962Returns NaN if SVD EventT0 is NaN, or if no SVD Hits are attached to the track.
963For more details, see :ref:`Time Extraction <tracking_eventTimeExtraction>` page.
964
965)DOC", "ns");
966
967 REGISTER_VARIABLE("trackLength", getTrackLength, R"DOC(
968Returns the arc length of the helix for the TrackFitResult associated with the particle.
969The arc length is measured from the track origin to the radius of the CDC layer in which the Track has a hit.
970Returns 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:703
@ 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.