10#include <analysis/variables/TrackVariables.h>
13#include <analysis/VariableManager/Manager.h>
15#include <analysis/dataobjects/Particle.h>
16#include <analysis/utility/DetectorSurface.h>
19#include <framework/datastore/StoreObjPtr.h>
20#include <framework/dataobjects/Helix.h>
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>
32#include <framework/logging/Logger.h>
47 auto trackFit = part->getTrackFitResult();
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();
61 double trackNCDCHits(
const Particle* part)
63 return trackNHits(part, Const::EDetector::CDC);
66 double trackNSVDHits(
const Particle* part)
68 return trackNHits(part, Const::EDetector::SVD);
71 double trackNPXDHits(
const Particle* part)
73 return trackNHits(part, Const::EDetector::PXD);
76 double trackNVXDHits(
const Particle* part)
78 return trackNPXDHits(part) + trackNSVDHits(part);
81 double trackNDF(
const Particle* part)
83 auto trackFit = part->getTrackFitResult();
85 return trackFit->getNDF();
88 double trackChi2(
const Particle* part)
90 auto trackFit = part->getTrackFitResult();
92 return trackFit->getChi2();
95 double trackFirstSVDLayer(
const Particle* part)
97 auto trackFit = part->getTrackFitResult();
99 return trackFit->getHitPatternVXD().getFirstSVDLayer();
102 double trackFirstPXDLayer(
const Particle* part)
104 auto trackFit = part->getTrackFitResult();
106 return trackFit->getHitPatternVXD().getFirstPXDLayer(HitPatternVXD::PXDMode::normal);
109 double trackFirstCDCLayer(
const Particle* part)
111 auto trackFit = part->getTrackFitResult();
113 return trackFit->getHitPatternCDC().getFirstLayer();
116 double trackLastCDCLayer(
const Particle* part)
118 auto trackFit = part->getTrackFitResult();
120 return trackFit->getHitPatternCDC().getLastLayer();
123 double trackD0(
const Particle* part)
125 auto trackFit = part->getTrackFitResult();
127 return trackFit->getD0();
130 double trackPhi0(
const Particle* part)
132 auto trackFit = part->getTrackFitResult();
134 return trackFit->getPhi0();
137 double trackOmega(
const Particle* part)
139 auto trackFit = part->getTrackFitResult();
141 return trackFit->getOmega();
144 double trackZ0(
const Particle* part)
146 auto trackFit = part->getTrackFitResult();
148 return trackFit->getZ0();
151 double trackTanLambda(
const Particle* part)
153 auto trackFit = part->getTrackFitResult();
155 return trackFit->getTanLambda();
158 double trackD0FromIP(
const Particle* part)
160 auto trackFit = part->getTrackFitResult();
162 static DBObjPtr<BeamSpot> beamSpotDB;
163 if (!beamSpotDB.isValid())
165 auto helix = trackFit->getHelix();
166 helix.passiveMoveBy(beamSpotDB->getIPPosition());
167 return helix.getD0();
170 double trackZ0FromIP(
const Particle* part)
172 auto trackFit = part->getTrackFitResult();
174 static DBObjPtr<BeamSpot> beamSpotDB;
175 if (!beamSpotDB.isValid())
177 auto helix = trackFit->getHelix();
178 helix.passiveMoveBy(beamSpotDB->getIPPosition());
179 return helix.getZ0();
182 double trackPhi0FromIP(
const Particle* part)
184 auto trackFit = part->getTrackFitResult();
186 static DBObjPtr<BeamSpot> beamSpotDB;
187 if (!beamSpotDB.isValid())
189 auto helix = trackFit->getHelix();
190 helix.passiveMoveBy(beamSpotDB->getIPPosition());
191 return helix.getPhi0();
194 double trackD0Error(
const Particle* part)
196 auto trackFit = part->getTrackFitResult();
198 double errorSquared = trackFit->getCovariance5()[0][0];
200 return sqrt(errorSquared);
203 double trackPhi0Error(
const Particle* part)
205 auto trackFit = part->getTrackFitResult();
208 double errorSquared = trackFit->getCovariance5()[1][1];
210 return sqrt(errorSquared);
213 double trackOmegaError(
const Particle* part)
215 auto trackFit = part->getTrackFitResult();
218 double errorSquared = trackFit->getCovariance5()[2][2];
220 return sqrt(errorSquared);
223 double trackZ0Error(
const Particle* part)
225 auto trackFit = part->getTrackFitResult();
228 double errorSquared = trackFit->getCovariance5()[3][3];
230 return sqrt(errorSquared);
233 double trackTanLambdaError(
const Particle* part)
235 auto trackFit = part->getTrackFitResult();
238 double errorSquared = trackFit->getCovariance5()[4][4];
240 return sqrt(errorSquared);
243 double trackFitCovariance(
const Particle* particle,
const std::vector<double>& indices)
245 if (indices.size() != 2) {
246 B2FATAL(
"Exactly two indices must be provided to the variable trackFitCovariance!");
248 if (*(std::min_element(indices.begin(), indices.end())) < 0 or *(std::max_element(indices.begin(), indices.end())) > 4) {
249 B2FATAL(
"The indices provided to the variable trackFitCovariance must be in the range 0 - 4!");
251 auto trackFit = particle->getTrackFitResult();
253 return trackFit->getCovariance5()[indices[0]][indices[1]];
256 double trackPValue(
const Particle* part)
258 auto trackFit = part->getTrackFitResult();
260 return trackFit->getPValue();
263 double trackFitHypothesisPDG(
const Particle* part)
265 auto trackFit = part->getTrackFitResult();
267 return trackFit->getParticleType().getPDGCode();
270 double trackNECLClusters(
const Particle* part)
272 const Track* track = part->getTrack();
277 for (
const ECLCluster& cluster : track->getRelationsTo<ECLCluster>())
284 ROOT::Math::XYZVector getPositionOnHelix(
const TrackFitResult* trackFit,
const std::vector<double>& pars)
286 const double r = pars[0];
287 const double zfwd = pars[1];
288 const double zbwd = pars[2];
291 const double z0 = trackFit->getZ0();
292 const double tanlambda = trackFit->getTanLambda();
293 const Helix h = trackFit->getHelix();
296 const double arcLength = h.getArcLength2DAtCylindricalR(r);
297 const double lHelixRadius = arcLength > 0 ? arcLength : std::numeric_limits<double>::max();
300 const double lFWD = (zfwd - z0) / tanlambda > 0 ? (zfwd - z0) / tanlambda : std::numeric_limits<double>::max();
303 const double lBWD = (zbwd - z0) / tanlambda > 0 ? (zbwd - z0) / tanlambda : std::numeric_limits<double>::max();
306 const double l = std::min({lHelixRadius, lFWD, lBWD});
308 return h.getPositionAtArcLength2D(l);
311 ROOT::Math::XYZVector getPositionOnHelix(
const Particle* part,
const std::vector<double>& pars)
313 if (pars.size() == 4 and pars[3]) {
314 const Track* track = part->getTrack();
318 auto highestProbMass = part->getMostLikelyTrackFitResult().first;
319 const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(highestProbMass);
320 if (!trackFit)
return vecNaN;
321 else return getPositionOnHelix(trackFit, pars);
323 const TrackFitResult* trackFit = part->getTrackFitResult();
324 if (!trackFit)
return vecNaN;
325 else return getPositionOnHelix(trackFit, pars);
330 double trackHelixExtTheta(
const Particle* part,
const std::vector<double>& pars)
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 helixExtTheta.");
337 ROOT::Math::XYZVector position = getPositionOnHelix(part, pars);
339 return position.Theta();
343 double trackHelixExtPhi(
const Particle* part,
const std::vector<double>& pars)
345 const auto nParams = pars.size();
346 if (nParams != 3 && nParams != 4) {
347 B2FATAL(
"Exactly three (+1 optional) parameters (r, zfwd, zbwd, [useHighestProbMass]) required for helixExtPhi.");
350 ROOT::Math::XYZVector position = getPositionOnHelix(part, pars);
352 return position.Phi();
357 if (arguments.size() != 1 && arguments.size() != 2)
358 B2FATAL(
"Exactly one (+1 optional) parameter (detector_surface_name, [useHighestProbMass]) is required for helixExtThetaOnDet.");
360 std::vector<double> parameters(3);
361 const std::string det = arguments[0];
371 B2FATAL(
"Given detector surface name is not supported.");
373 if (arguments.size() == 2)
374 parameters.push_back(std::stod(arguments[1]));
376 auto func = [parameters](
const Particle * part) ->
double {
378 ROOT::Math::XYZVector position = getPositionOnHelix(part, parameters);
380 return position.Theta();
387 if (arguments.size() != 1 && arguments.size() != 2)
388 B2FATAL(
"Exactly one (+1 optional) parameter (detector_surface_name, [useHighestProbMass]) is required for helixExtPhiOnDet.");
390 std::vector<double> parameters(3);
391 const std::string det = arguments[0];
401 B2FATAL(
"Given detector surface name is not supported.");
403 if (arguments.size() == 2)
404 parameters.push_back(std::stod(arguments[1]));
406 auto func = [parameters](
const Particle * part) ->
double {
408 ROOT::Math::XYZVector position = getPositionOnHelix(part, parameters);
410 return position.Phi();
421 double nExtraCDCHits(
const Particle*)
423 StoreObjPtr<EventLevelTrackingInfo> elti;
425 return elti->getNCDCHitsNotAssigned();
430 double nExtraCDCHitsPostCleaning(
const Particle*)
432 StoreObjPtr<EventLevelTrackingInfo> elti;
434 return elti->getNCDCHitsNotAssignedPostCleaning();
438 double hasExtraCDCHitsInLayer(
const Particle*,
const std::vector<double>& layer)
440 StoreObjPtr<EventLevelTrackingInfo> elti;
442 int ilayer = std::lround(layer[0]);
443 return elti->hasCDCLayer(ilayer);
447 double hasExtraCDCHitsInSuperLayer(
const Particle*,
const std::vector<double>& layer)
449 StoreObjPtr<EventLevelTrackingInfo> elti;
451 int ilayer = std::lround(layer[0]);
452 return elti->hasCDCSLayer(ilayer);
456 double nExtraCDCSegments(
const Particle*)
458 StoreObjPtr<EventLevelTrackingInfo> elti;
460 return elti->getNCDCSegments();
464 double nExtraVXDHitsInLayer(
const Particle*,
const std::vector<double>& layer)
466 StoreObjPtr<EventLevelTrackingInfo> elti;
468 int ilayer = std::lround(layer[0]);
469 return elti->getNVXDClustersInLayer(ilayer);
473 double nExtraVXDHits(
const Particle*)
475 StoreObjPtr<EventLevelTrackingInfo> elti;
478 for (uint16_t ilayer = 1; ilayer < 7; ++ilayer)
479 out += elti->getNVXDClustersInLayer(ilayer);
484 double svdFirstSampleTime(
const Particle*)
486 StoreObjPtr<EventLevelTrackingInfo> elti;
488 return elti->getSVDFirstSampleTime();
495 double trackFindingFailureFlag(
const Particle*)
497 StoreObjPtr<EventLevelTrackingInfo> elti;
499 return elti->hasAnErrorFlag();
503 Helix getMCHelix(
const MCParticle* mcparticle)
505 const ROOT::Math::XYZVector mcProdVertex = mcparticle->getVertex();
506 const ROOT::Math::XYZVector mcMomentum = mcparticle->getMomentum();
508 const double mcParticleCharge = mcparticle->getCharge();
509 return Helix(mcProdVertex, mcMomentum, mcParticleCharge, BzAtProdVertex);
512 double getMCHelixParameterAtIndex(
const Particle* particle,
const int index)
516 const MCParticle* mcparticle = particle->getMCParticle();
519 const Helix mcHelix(getMCHelix(mcparticle));
520 const std::vector<double> mcHelixPars{mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
521 return mcHelixPars.at(index);
524 double getHelixParameterPullAtIndex(
const Particle* particle,
const int index)
528 const MCParticle* mcparticle = particle->getMCParticle();
531 const TrackFitResult* trackfit = particle->getTrackFitResult();
534 const UncertainHelix measHelix = trackfit->getUncertainHelix();
535 const TMatrixDSym& measCovariance = measHelix.getCovariance();
536 const Helix mcHelix(getMCHelix(mcparticle));
538 const std::vector<double> mcHelixPars = {mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
539 const std::vector<double> measHelixPars = {measHelix.getD0(), measHelix.getPhi0(), measHelix.getOmega(), measHelix.getZ0(), measHelix.getTanLambda()};
541 return (mcHelixPars.at(index) - measHelixPars.at(index)) / std::sqrt(measCovariance(index, index));
544 double getHelixMCD0(
const Particle* part) {
return getMCHelixParameterAtIndex(part, 0); }
545 double getHelixMCPhi0(
const Particle* part) {
return getMCHelixParameterAtIndex(part, 1); }
546 double getHelixMCOmega(
const Particle* part) {
return getMCHelixParameterAtIndex(part, 2); }
547 double getHelixMCZ0(
const Particle* part) {
return getMCHelixParameterAtIndex(part, 3); }
548 double getHelixMCTanLambda(
const Particle* part) {
return getMCHelixParameterAtIndex(part, 4); }
550 double getHelixD0Pull(
const Particle* part)
552 return getHelixParameterPullAtIndex(part, 0);
555 double getHelixPhi0Pull(
const Particle* part)
557 return getHelixParameterPullAtIndex(part, 1);
560 double getHelixOmegaPull(
const Particle* part)
562 return getHelixParameterPullAtIndex(part, 2);
565 double getHelixZ0Pull(
const Particle* part)
567 return getHelixParameterPullAtIndex(part, 3);
570 double getHelixTanLambdaPull(
const Particle* part)
572 return getHelixParameterPullAtIndex(part, 4);
575 double getTrackTime(
const Particle* part)
577 const Track* track = part->getTrack();
579 return track->getTrackTime();
582 double isTrackFlippedAndRefitted(
const Particle* part)
584 auto track = part->getTrack();
586 return track->isFlippedAndRefitted() ? 1 : 0;
589 double getTrackLength(
const Particle* part)
591 auto trackFit = part->getTrackFitResult();
594 const double lastCDCLayer = trackLastCDCLayer(part);
595 if (std::isnan(lastCDCLayer) or lastCDCLayer < 0)
600 return trackFit->getHelix().getArcLength2DAtCylindricalR(r);
604 VARIABLE_GROUP(
"Tracking");
606 REGISTER_VARIABLE(
"mcD0", getHelixMCD0, R
"DOC(
607Returns the MC value of :math:`d_0`, the signed distance to the
608point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
610.. seealso:: :b2:var:`d0`
612Returns NaN if the particle is not related to any MCParticle.
615 REGISTER_VARIABLE(
"mcPhi0", getHelixMCPhi0, R
"DOC(
616Returns the MC value of :math:`\phi_0`, the angle of the transverse momentum
617in the :math:`r-\phi` plane.
619.. seealso:: :b2:var:`phi0`
621Returns NaN if the particle is not related to any MCParticle.
624 REGISTER_VARIABLE(
"mcOmega", getHelixMCOmega, R
"DOC(
625Returns the MC value of :math:`\omega`, the curvature of the track.
627.. seealso:: :b2:var:`omega`
629Returns NaN if the particle is not related to any MCParticle.
631)DOC", ":math:`\\text{cm}^{-1}`");
632 REGISTER_VARIABLE(
"mcZ0", getHelixMCZ0, R
"DOC(
633Returns the MC value of :math:`z_0`, the z-coordinate of the
634point-of-closest-approach (POCA).
636.. seealso:: :b2:var:`z0`
638Returns NaN if the particle is not related to any MCParticle.
641 REGISTER_VARIABLE(
"mcTanLambda", getHelixMCTanLambda, R
"DOC(
642Returns the MC value of :math:`\tan\lambda`, the slope of the track in the
645.. seealso:: :b2:var:`tanLambda`
647Returns NaN if the particle is not related to any MCParticle.
650 REGISTER_VARIABLE("d0Pull", getHelixD0Pull, R
"DOC(
651The pull of the tracking parameter :math:`d_0` for the reconstructed
652pattern-recognition track, with respect to the MC track. That is:
656 \frac{d_0^\textrm{MC} - d_0^\textrm{PR}}{\sigma_{d_0; \textrm{PR}}}
658.. seealso:: :b2:var:`d0`, :b2:var:`d0Err`
660Returns NaN if no MC particle is related or if called on something other than a
663 REGISTER_VARIABLE("phi0Pull", getHelixPhi0Pull, R
"DOC(
664The pull of the tracking parameter :math:`\phi_0` for the reconstructed
665pattern-recognition track, with respect to the MC track. That is:
669 \frac{\phi_0^\textrm{MC} - \phi_0^\textrm{PR}}{\sigma_{\phi_0; \textrm{PR}}}
671.. seealso:: :b2:var:`phi0`, :b2:var:`phi0Err`
673Returns NaN if no MC particle is related or if called on something other than a
676 REGISTER_VARIABLE("omegaPull", getHelixOmegaPull, R
"DOC(
677The pull of the tracking parameter :math:`\omega` for the reconstructed
678pattern-recognition track, with respect to the MC track. That is:
682 \frac{\omega^\textrm{MC} - \omega^\textrm{PR}}{\sigma_{\omega; \textrm{PR}}}
684.. seealso:: :b2:var:`omega`, :b2:var:`omegaErr`
686Returns NaN if no MC particle is related or if called on something other than a
689 REGISTER_VARIABLE("z0Pull", getHelixZ0Pull, R
"DOC(
690The pull of the tracking parameter :math:`z_0` for the reconstructed
691pattern-recognition track, with respect to the MC track. That is:
695 \frac{z_0^\textrm{MC} - z_0^\textrm{PR}}{\sigma_{z_0; \textrm{PR}}}
697.. seealso:: :b2:var:`z0`, :b2:var:`z0Err`
699Returns NaN if no MC particle is related or if called on something other than a
702 REGISTER_VARIABLE("tanLambdaPull", getHelixTanLambdaPull, R
"DOC(
703The pull of the tracking parameter :math:`\tan\lambda` for the reconstructed
704pattern-recognition track, with respect to the MC track. That is:
708 \frac{(\tan\lambda)^\textrm{MC} - (\tan\lambda)^\textrm{PR}}{\sigma_{\tan\lambda; \textrm{PR}}}
710.. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaErr`
712Returns NaN if no MC particle is related or if called on something other than a
715 REGISTER_VARIABLE("nCDCHits", trackNCDCHits,
716 "The number of CDC hits associated to the track. Returns NaN if called for something other than a track-based particle.");
717 REGISTER_VARIABLE(
"nSVDHits", trackNSVDHits,
718 "The number of SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
719 REGISTER_VARIABLE(
"nPXDHits", trackNPXDHits,
720 "The number of PXD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
721 REGISTER_VARIABLE(
"nVXDHits", trackNVXDHits,
722 "The number of PXD and SVD hits associated to the track. Returns NaN if called for something other than a track-based particle.");
723 REGISTER_VARIABLE(
"ndf", trackNDF, R
"DOC(
724Returns the number of degrees of freedom of the track fit.
728 Note that this is not simply the number of hits -5 due to outlier hit
731Returns NaN if called for something other than a track-based particle, or for
732mdst files processed with basf2 versions older than ``release-05-01``.
734 REGISTER_VARIABLE("chi2", trackChi2, R
"DOC(
735Returns the :math:`\chi^2` of the track fit. This is actually computed based on
736:b2:var:`pValue` and :b2:var:`ndf`.
738.. note:: Note that for :b2:var:`pValue` exactly equal to 0 it returns infinity.
740Returns NaN if called for something other than a track-based particle, or for
741mdst files processed with basf2 versions older than ``release-05-01``.
743 REGISTER_VARIABLE("firstSVDLayer", trackFirstSVDLayer,
744 "The first activated SVD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
745 REGISTER_VARIABLE(
"firstPXDLayer", trackFirstPXDLayer,
746 "The first activated PXD layer associated to the track. Returns NaN if called for something other than a track-based particle.");
747 REGISTER_VARIABLE(
"firstCDCLayer", trackFirstCDCLayer,
748 "The first activated CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
749 REGISTER_VARIABLE(
"lastCDCLayer", trackLastCDCLayer,
750 "The last CDC layer associated to the track. Returns NaN if called for something other than a track-based particle.");
751 REGISTER_VARIABLE(
"d0", trackD0, R
"DOC(
752Returns the tracking parameter :math:`d_0`, the signed distance to the
753point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
757 Tracking parameters are with respect to the origin (0,0,0). For the
758 POCA with respect to the measured beam interaction point, see
759 :b2:var:`dr` (you probably want this unless you're doing a tracking
760 study or some debugging) and :b2:var:`d0FromIP`.
762Returns NaN if called for something other than a track-based particle.
765 REGISTER_VARIABLE(
"phi0", trackPhi0, R
"DOC(
766Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
767momentum in the :math:`r-\phi` plane.
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:`phi0FromIP`.
775Returns NaN if called for something other than a track-based particle.
778 REGISTER_VARIABLE(
"omega", trackOmega, R
"DOC(
779Returns the tracking parameter :math:`\omega`, the curvature of the track.
781Returns NaN if called for something other than a track-based particle.
783)DOC", ":math:`\\text{cm}^{-1}`");
784 REGISTER_VARIABLE(
"z0", trackZ0, R
"DOC(
785Returns the tracking parameter :math:`z_0`, the z-coordinate of the
786point-of-closest-approach (POCA).
790 Tracking parameters are with respect to the origin (0,0,0). For the
791 POCA with respect to the measured beam interaction point, see
792 :b2:var:`dz` (you probably want this unless you're doing a tracking
793 study or some debugging) and :b2:var:`z0FromIP`.
795Returns NaN if called for something other than a track-based particle.
798 REGISTER_VARIABLE(
"tanLambda", trackTanLambda, R
"DOC(
799Returns :math:`\tan\lambda`, the slope of the track in the :math:`r-z` plane.
801Returns NaN if called for something other than a track-based particle.
803 REGISTER_VARIABLE("d0FromIP", trackD0FromIP, R
"DOC(
804Returns the tracking parameter :math:`d_0`, the signed distance to the
805point-of-closest-approach (POCA) in the :math:`r-\phi` plane, with respect to the measured beam interaction point.
807Returns NaN if called for something other than a track-based particle.
810 REGISTER_VARIABLE(
"z0FromIP", trackZ0FromIP, R
"DOC(
811Returns the tracking parameter :math:`z_0`, the z-coordinate of the
812point-of-closest-approach (POCA), with respect to the measured beam interaction point.
814Returns NaN if called for something other than a track-based particle.
817 REGISTER_VARIABLE(
"phi0FromIP", trackPhi0FromIP, R
"DOC(
818Returns the tracking parameter :math:`\phi_0`, the angle of the transverse
819momentum in the :math:`r-\phi` plane, with respect to the measured beam interaction point.
821Returns NaN if called for something other than a track-based particle.
824 REGISTER_VARIABLE(
"d0Err", trackD0Error, R
"DOC(
825Returns the uncertainty on :math:`d_0`, the signed distance to the
826point-of-closest-approach (POCA) in the :math:`r-\phi` plane.
828.. seealso:: :b2:var:`d0`, :b2:var:`d0Pull`
830Returns NaN if called for something other than a track-based particle.
833 REGISTER_VARIABLE(
"phi0Err", trackPhi0Error, R
"DOC(
834Returns the uncertainty on :math:`\phi_0`, the angle of the transverse momentum
835in the :math:`r-\phi` plane.
837.. seealso:: :b2:var:`phi0`, :b2:var:`phi0Pull`
839Returns NaN if called for something other than a track-based particle.
842 REGISTER_VARIABLE(
"omegaErr", trackOmegaError, R
"DOC(
843Returns the uncertainty on :math:`\omega`, the curvature of the track.
845.. seealso:: :b2:var:`omega`, :b2:var:`omegaPull`
847Returns NaN if called for something other than a track-based particle.
849)DOC", ":math:`\\text{cm}^{-1}`");
850 REGISTER_VARIABLE(
"z0Err", trackZ0Error, R
"DOC(
851Returns the uncertainty on :math:`z_0`, the z-coordinate of the
852point-of-closest-approach (POCA).
854.. seealso:: :b2:var:`z0`, :b2:var:`z0Pull`
856Returns NaN if called for something other than a track-based particle."
859 REGISTER_VARIABLE(
"tanLambdaErr", trackTanLambdaError, R
"DOC(
860Returns the uncertainty on :math:`\tan\lambda`, the slope of the track in the
863.. seealso:: :b2:var:`tanLambda`, :b2:var:`tanLambdaPull`
865Returns NaN if called for something other than a track-based particle.
867 REGISTER_VARIABLE("trackFitCovariance(i, j)", trackFitCovariance, R
"DOC(
868 The track fit covariance matrix element corresponding to the two indices is returned.
869 This is the association between integers and parameters:
875 * 4: :math:`\tan\lambda`
879 The covariance is returned. This means that the return value can be negative.
880 Furthermore, it's the squared value of the track fit error variables :b2:var:`d0Err`, etc.
881 when selecting the diagonal entries.
884 REGISTER_VARIABLE("pValue", trackPValue, R
"DOC(
885The :math:`\chi^2` probability of the **track** fit.
889 This is the p-value of the track-fit. It does not get updated after
890 vertex fitting or kinematic fitting, and is meaningless for composite
893 See :b2:var:`chiProb` (you probably want this for high-level analysis).
895Returns NaN if called for something other than a track-based particle.
897 REGISTER_VARIABLE("trackFitHypothesisPDG", trackFitHypothesisPDG, R
"DOC(
898Returns the PDG code of the track hypothesis actually used for the fit.
899Returns NaN if called for something other than a track-based particle.
901 REGISTER_VARIABLE("trackNECLClusters", trackNECLClusters, R
"DOC(
902Returns a count of the number of ECLClusters matched to the track. This is
903always 0 or 1 with newer versions of ECL reconstruction.
907 For high-level analysis it is recommended to require the presence of a
908 matched ECL cluster along with a minimum energy requirement. A
909 track-based particle will have a clusterE if it is matched (NaN if
910 there is no cluster match for the track.
912 .. code-block:: python
914 import modularAnalysis as ma
915 # minimum energy of 200 MeV
916 ma.fillParticleList("e+:clusters", "clusterE > 0.2", path)
918 # these two are equivalent
919 ma.fillParticleList("e+:unmatched", "isNAN(clusterE) == 1", path)
920 ma.fillParticleList("e+:unmatched2", "trackNECLClusters == 0", path)
922Returns NaN if called for something other than a track-based particle.
924 REGISTER_VARIABLE("helixExtTheta(radius [cm], z fwd [cm], z bwd [cm], useHighestProbMass=0)", trackHelixExtTheta,
925 R
"DOC(Returns theta of extrapolated helix parameters. If ``useHighestProbMass=1`` is set, the extrapolation will
926 use the track fit result for the mass hypothesis with the highest pValue.
929 REGISTER_VARIABLE(
"helixExtPhi(radius, z fwd, z bwd, useHighestProbMass=0)", trackHelixExtPhi,
930 "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",
933 REGISTER_METAVARIABLE(
"helixExtThetaOnDet(detector_surface_name, useHighestProbMass=0)", trackHelixExtThetaOnDet,
934 R
"DOC(Returns theta of extrapolated helix parameters on the given detector surface. The unit of angle is ``rad``.
935 If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.
936 The supported detector surface names are ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
937 Also, the detector name with number of meaningful-layer is supported, e.g. ``'CDC8'``: last superlayer of CDC, ``'ECL1'``: mid-point of ECL.
939 ..note:: You can find more information in `modularAnalysis.calculateTrackIsolation`.
940 )DOC", Manager::VariableDataType::c_double);
941 REGISTER_METAVARIABLE("helixExtPhiOnDet(detector_surface_name, useHighestProbMass=0)", trackHelixExtPhiOnDet,
942 R
"DOC(Returns phi of extrapolated helix parameters on the given detector surface. The unit of angle is ``rad``.
943 If ``useHighestProbMass=1`` is set, the extrapolation will use the track fit result for the mass hypothesis with the highest pValue.
944 The supported detector surface names are ``{'CDC', 'TOP', 'ARICH', 'ECL', 'KLM'}``.
945 Also, the detector name with number of meaningful-layer is supported, e.g. ``'CDC8'``: last superlayer of CDC, ``'ECL1'``: mid-point of ECL.
947 ..note:: You can find more information in `modularAnalysis.calculateTrackIsolation`.
948 )DOC", Manager::VariableDataType::c_double);
951 REGISTER_VARIABLE("nExtraCDCHits", nExtraCDCHits, R
"DOC(
952[Eventbased] The number of CDC hits in the event not assigned to any track.
954Returns NaN if there is no event-level tracking information available.
956 REGISTER_VARIABLE("nExtraCDCHitsPostCleaning", nExtraCDCHitsPostCleaning, R
"DOC(
957[Eventbased] Returns a count of the number of CDC hits in the event not assigned
958to any track nor very likely beam background (i.e. hits that survive a cleanup
961Returns NaN if there is no event-level tracking information available.
963 REGISTER_VARIABLE("hasExtraCDCHitsInLayer(i)", hasExtraCDCHitsInLayer, R
"DOC(
964[Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC layer,
967Returns NaN if there is no event-level tracking information available.
969 REGISTER_VARIABLE("hasExtraCDCHitsInSuperLayer(i)", hasExtraCDCHitsInSuperLayer, R
"DOC(
970[Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC
971SuperLayer, 0 otherwise.
973Returns NaN if there is no event-level tracking information available.
975 REGISTER_VARIABLE("nExtraCDCSegments", nExtraCDCSegments, R
"DOC(
976[Eventbased] Returns the number of CDC segments not assigned to any track.
978Returns NaN if there is no event-level tracking information available.
986 REGISTER_VARIABLE(
"trackFindingFailureFlag", trackFindingFailureFlag, R
"DOC(
987[Eventbased] Returns a flag set by the tracking if there is reason to assume
988there was a track in the event missed by the tracking, or the track finding was
989(partly) aborted for this event.
991Returns NaN if there is no event-level tracking information available.
994 REGISTER_VARIABLE("isTrackFlippedAndRefitted", isTrackFlippedAndRefitted, R
"DOC(
995Returns 1 if the charged final state particle comes from a track that has been flipped and refitted
996at the end of the tracking chain, in particular before the outer detector reconstruction.
999 REGISTER_VARIABLE("trackTime", getTrackTime, R
"DOC(
1000Returns the time at which the track is produced relative to the time of the collision (given by SVD EventT0).
1001Both the time of the collision and the track time are computed using only SVD hits.
1002Returns NaN if SVD EventT0 is NaN, or if no SVD Hits are attached to the track.
1003For more details, see :ref:`Time Extraction <tracking_eventTimeExtraction>` page.
1007 REGISTER_VARIABLE(
"trackLength", getTrackLength, R
"DOC(
1008Returns the arc length of the helix for the TrackFitResult associated with the particle.
1009The arc length is measured from the track origin to the radius of the CDC layer in which the Track has a hit.
1010Returns NaN if the particle has no CDC Hits.
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
EDetector
Enum for identifying the detector components (detector and subdetector).
static const double doubleNaN
quiet_NaN
@ c_nPhotons
CR is split into n photons (N1)
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
double sqrt(double a)
sqrt for double
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.