10 #include <analysis/variables/TrackVariables.h>
11 #include <analysis/VariableManager/Manager.h>
14 #include <framework/datastore/StoreObjPtr.h>
15 #include <framework/dataobjects/Helix.h>
18 #include <mdst/dataobjects/Track.h>
19 #include <mdst/dataobjects/MCParticle.h>
20 #include <mdst/dataobjects/TrackFitResult.h>
21 #include <mdst/dataobjects/EventLevelTrackingInfo.h>
22 #include <mdst/dataobjects/HitPatternVXD.h>
23 #include <mdst/dataobjects/ECLCluster.h>
26 #include <framework/logging/Logger.h>
37 static const double realNaN = std::numeric_limits<double>::quiet_NaN();
42 auto trackFit = part->getTrackFitResult();
47 if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
48 trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
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();
101 if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
102 trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
104 return trackFit->getHitPatternVXD().getFirstSVDLayer();
107 double trackFirstPXDLayer(
const Particle* part)
109 auto trackFit = part->getTrackFitResult();
113 if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
114 trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
116 return trackFit->getHitPatternVXD().getFirstPXDLayer(HitPatternVXD::PXDMode::normal);
119 double trackFirstCDCLayer(
const Particle* part)
121 auto trackFit = part->getTrackFitResult();
125 if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
126 trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
128 return trackFit->getHitPatternCDC().getFirstLayer();
131 double trackLastCDCLayer(
const Particle* part)
133 auto trackFit = part->getTrackFitResult();
137 if (trackFit->getHitPatternCDC().getNHits() + trackFit->getHitPatternVXD().getNdf() < 1) {
138 trackFit = part->getTrack()->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(part->getPDGCode())));
140 return trackFit->getHitPatternCDC().getLastLayer();
143 double trackD0(
const Particle* part)
145 auto trackFit = part->getTrackFitResult();
147 return trackFit->getD0();
150 double trackPhi0(
const Particle* part)
152 auto trackFit = part->getTrackFitResult();
154 return trackFit->getPhi0();
157 double trackOmega(
const Particle* part)
159 auto trackFit = part->getTrackFitResult();
161 return trackFit->getOmega();
164 double trackZ0(
const Particle* part)
166 auto trackFit = part->getTrackFitResult();
168 return trackFit->getZ0();
171 double trackTanLambda(
const Particle* part)
173 auto trackFit = part->getTrackFitResult();
175 return trackFit->getTanLambda();
178 double trackD0Error(
const Particle* part)
180 auto trackFit = part->getTrackFitResult();
183 double errorSquared = trackFit->getCovariance5()[0][0];
184 if (errorSquared <= 0)
return realNaN;
185 return sqrt(errorSquared);
188 double trackPhi0Error(
const Particle* part)
190 auto trackFit = part->getTrackFitResult();
193 double errorSquared = trackFit->getCovariance5()[1][1];
194 if (errorSquared <= 0)
return realNaN;
195 return sqrt(errorSquared);
198 double trackOmegaError(
const Particle* part)
200 auto trackFit = part->getTrackFitResult();
203 double errorSquared = trackFit->getCovariance5()[2][2];
204 if (errorSquared <= 0)
return realNaN;
205 return sqrt(errorSquared);
208 double trackZ0Error(
const Particle* part)
210 auto trackFit = part->getTrackFitResult();
213 double errorSquared = trackFit->getCovariance5()[3][3];
214 if (errorSquared <= 0)
return realNaN;
215 return sqrt(errorSquared);
218 double trackTanLambdaError(
const Particle* part)
220 auto trackFit = part->getTrackFitResult();
223 double errorSquared = trackFit->getCovariance5()[4][4];
224 if (errorSquared <= 0)
return realNaN;
225 return sqrt(errorSquared);
228 double trackPValue(
const Particle* part)
230 auto trackFit = part->getTrackFitResult();
232 return trackFit->getPValue();
235 double trackFitHypothesisPDG(
const Particle* part)
237 auto trackFit = part->getTrackFitResult();
239 return trackFit->getParticleType().getPDGCode();
242 double trackNECLClusters(
const Particle* part)
244 const Track* track = part->getTrack();
249 for (
const ECLCluster& cluster : track->getRelationsTo<ECLCluster>())
256 TVector3 getPositionOnHelix(
const Particle* part,
const std::vector<double>& pars)
258 if (pars.size() != 3) {
259 B2FATAL(
"Exactly three parameters (r, zfwd, zbwd) required.");
262 const double r = pars[0];
263 const double zfwd = pars[1];
264 const double zbwd = pars[2];
267 auto trackFit = part->getTrackFitResult();
268 if (!trackFit)
return vecNaN;
271 const double z0 = trackFit->getZ0();
272 const double tanlambda = trackFit->getTanLambda();
273 const Helix h = trackFit->getHelix();
276 const double arcLength = h.getArcLength2DAtCylindricalR(r);
277 const double lHelixRadius = arcLength > 0 ? arcLength : std::numeric_limits<double>::max();
280 const double lFWD = (zfwd - z0) / tanlambda > 0 ? (zfwd - z0) / tanlambda : std::numeric_limits<double>::max();
283 const double lBWD = (zbwd - z0) / tanlambda > 0 ? (zbwd - z0) / tanlambda : std::numeric_limits<double>::max();
286 const double l = std::min({lHelixRadius, lFWD, lBWD});
288 return h.getPositionAtArcLength2D(l);
292 double trackHelixExtTheta(
const Particle* part,
const std::vector<double>& pars)
294 if (pars.size() != 3) {
295 B2FATAL(
"Exactly three parameters (r, zfwd, zbwd) required for helixExtTheta.");
297 TVector3 position = getPositionOnHelix(part, pars);
299 return position.Theta();
303 double trackHelixExtPhi(
const Particle* part,
const std::vector<double>& pars)
305 if (pars.size() != 3) {
306 B2FATAL(
"Exactly three parameters (r, zfwd, zbwd) required for helixExtPhi.");
308 TVector3 position = getPositionOnHelix(part, pars);
310 return position.Phi();
319 double nExtraCDCHits(
const Particle*)
321 StoreObjPtr<EventLevelTrackingInfo> elti;
323 return elti->getNCDCHitsNotAssigned();
328 double nExtraCDCHitsPostCleaning(
const Particle*)
330 StoreObjPtr<EventLevelTrackingInfo> elti;
332 return elti->getNCDCHitsNotAssignedPostCleaning();
336 double hasExtraCDCHitsInLayer(
const Particle*,
const std::vector<double>& layer)
338 StoreObjPtr<EventLevelTrackingInfo> elti;
340 int ilayer = std::lround(layer[0]);
341 return elti->hasCDCLayer(ilayer);
345 double hasExtraCDCHitsInSuperLayer(
const Particle*,
const std::vector<double>& layer)
347 StoreObjPtr<EventLevelTrackingInfo> elti;
349 int ilayer = std::lround(layer[0]);
350 return elti->hasCDCSLayer(ilayer);
354 double nExtraCDCSegments(
const Particle*)
356 StoreObjPtr<EventLevelTrackingInfo> elti;
358 return elti->getNCDCSegments();
362 double nExtraVXDHitsInLayer(
const Particle*,
const std::vector<double>& layer)
364 StoreObjPtr<EventLevelTrackingInfo> elti;
366 int ilayer = std::lround(layer[0]);
367 return elti->getNVXDClustersInLayer(ilayer);
371 double nExtraVXDHits(
const Particle*)
373 StoreObjPtr<EventLevelTrackingInfo> elti;
376 for (uint16_t ilayer = 1; ilayer < 7; ++ilayer)
377 out += elti->getNVXDClustersInLayer(ilayer);
382 double svdFirstSampleTime(
const Particle*)
384 StoreObjPtr<EventLevelTrackingInfo> elti;
386 return elti->getSVDFirstSampleTime();
393 double trackFindingFailureFlag(
const Particle*)
395 StoreObjPtr<EventLevelTrackingInfo> elti;
397 return elti->hasAnErrorFlag();
400 double getHelixParameterPullAtIndex(
const Particle* particle,
const int index)
404 const MCParticle* mcparticle = particle->getMCParticle();
405 if (!mcparticle)
return realNaN;
411 const TMatrixDSym measCovariance = measHelix.
getCovariance();
412 const TVector3 mcProdVertex = mcparticle->getVertex();
413 const TVector3 mcMomentum = mcparticle->getMomentum();
416 const double mcParticleCharge = mcparticle->getCharge();
419 const std::vector<double> mcHelixPars = {mcHelix.getD0(), mcHelix.getPhi0(), mcHelix.getOmega(), mcHelix.getZ0(), mcHelix.getTanLambda()};
420 const std::vector<double> measHelixPars = {measHelix.getD0(), measHelix.getPhi0(), measHelix.getOmega(), measHelix.getZ0(), measHelix.getTanLambda()};
421 const std::vector<double> measErrSquare = {measCovariance[0][0], measCovariance[1][1], measCovariance[2][2], measCovariance[3][3], measCovariance[4][4]};
423 return (mcHelixPars.at(index) - measHelixPars.at(index)) / std::sqrt(measErrSquare.at(index));
426 double getHelixD0Pull(
const Particle* part)
428 return getHelixParameterPullAtIndex(part, 0);
431 double getHelixPhi0Pull(
const Particle* part)
433 return getHelixParameterPullAtIndex(part, 1);
436 double getHelixOmegaPull(
const Particle* part)
438 return getHelixParameterPullAtIndex(part, 2);
441 double getHelixZ0Pull(
const Particle* part)
443 return getHelixParameterPullAtIndex(part, 3);
445 double getHelixTanLambdaPull(
const Particle* part)
447 return getHelixParameterPullAtIndex(part, 4);
451 VARIABLE_GROUP(
"Tracking");
452 REGISTER_VARIABLE(
"d0Pull", getHelixD0Pull,
"(mc-meas)/err_meas for d0");
453 REGISTER_VARIABLE(
"phi0Pull", getHelixPhi0Pull,
"(mc-meas)/err_meas for phi0");
454 REGISTER_VARIABLE(
"omegaPull", getHelixOmegaPull,
"(mc-meas)/err_meas for omega");
455 REGISTER_VARIABLE(
"z0Pull", getHelixZ0Pull,
"(mc-meas)/err_meas for z0");
456 REGISTER_VARIABLE(
"tanLambdaPull", getHelixTanLambdaPull,
"(mc-meas)/err_meas for tanLambda");
458 REGISTER_VARIABLE(
"nCDCHits", trackNCDCHits,
"Number of CDC hits associated to the track");
459 REGISTER_VARIABLE(
"nSVDHits", trackNSVDHits,
"Number of SVD hits associated to the track");
460 REGISTER_VARIABLE(
"nPXDHits", trackNPXDHits,
"Number of PXD hits associated to the track");
461 REGISTER_VARIABLE(
"nVXDHits", trackNVXDHits,
"Number of PXD and SVD hits associated to the track");
462 REGISTER_VARIABLE(
"ndf", trackNDF,
463 R
"DOC(Number of degrees of freedom of the track fit. Note that it is not NHIT-5 due to outlier hit rejection.
464 For mdst versions < 5.1, returns quiet_NaN().)DOC"
466 REGISTER_VARIABLE("chi2", trackChi2,
467 R
"DOC(Chi2 of the track fit.
468 Computed based on pValue and ndf. Note that for pValue exactly equal to 0 it returns infinity().
469 For mdst versions < 5.1, returns quiet_NaN().)DOC");
470 REGISTER_VARIABLE("firstSVDLayer", trackFirstSVDLayer,
"First activated SVD layer associated to the track");
471 REGISTER_VARIABLE(
"firstPXDLayer", trackFirstPXDLayer,
"First activated PXD layer associated to the track");
472 REGISTER_VARIABLE(
"firstCDCLayer", trackFirstCDCLayer,
"First activated CDC layer associated to the track");
473 REGISTER_VARIABLE(
"lastCDCLayer", trackLastCDCLayer,
"Last CDC layer associated to the track");
474 REGISTER_VARIABLE(
"d0", trackD0,
"Signed distance to the POCA in the r-phi plane");
475 REGISTER_VARIABLE(
"phi0", trackPhi0,
"Angle of the transverse momentum in the r-phi plane");
476 REGISTER_VARIABLE(
"omega", trackOmega,
"Curvature of the track");
477 REGISTER_VARIABLE(
"z0", trackZ0,
"z coordinate of the POCA");
478 REGISTER_VARIABLE(
"tanLambda", trackTanLambda,
"Slope of the track in the r-z plane");
479 REGISTER_VARIABLE(
"d0Err", trackD0Error,
"Error of signed distance to the POCA in the r-phi plane");
480 REGISTER_VARIABLE(
"phi0Err", trackPhi0Error,
"Error of angle of the transverse momentum in the r-phi plane");
481 REGISTER_VARIABLE(
"omegaErr", trackOmegaError,
"Error of curvature of the track");
482 REGISTER_VARIABLE(
"z0Err", trackZ0Error,
"Error of z coordinate of the POCA");
483 REGISTER_VARIABLE(
"tanLambdaErr", trackTanLambdaError,
"Error of slope of the track in the r-z plane");
484 REGISTER_VARIABLE(
"pValue", trackPValue,
"chi2 probability of the track fit");
485 REGISTER_VARIABLE(
"trackFitHypothesisPDG", trackFitHypothesisPDG,
"PDG code of the track hypothesis actually used for the fit");
486 REGISTER_VARIABLE(
"trackNECLClusters", trackNECLClusters,
487 "Number ecl clusters matched to the track. This is always 0 or 1 with newer versions of ECL reconstruction.");
488 REGISTER_VARIABLE(
"helixExtTheta", trackHelixExtTheta,
489 "Returns theta of extrapolated helix parameters (parameters (in cm): radius, z fwd, z bwd)");
490 REGISTER_VARIABLE(
"helixExtPhi", trackHelixExtPhi,
491 "Returns phi of extrapolated helix parameters (parameters (in cm): radius, z fwd, z bwd)");
493 REGISTER_VARIABLE(
"nExtraCDCHits", nExtraCDCHits,
"[Eventbased] The number of CDC hits in the event not assigned to any track");
494 REGISTER_VARIABLE(
"nExtraCDCHitsPostCleaning", nExtraCDCHitsPostCleaning,
495 "[Eventbased] The number of CDC hits in the event not assigned to any track nor very likely beam background (i.e. hits that survive a cleanup selection)");
496 REGISTER_VARIABLE(
"hasExtraCDCHitsInLayer(i)", hasExtraCDCHitsInLayer,
497 "[Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC layer");
498 REGISTER_VARIABLE(
"hasExtraCDCHitsInSuperLayer(i)", hasExtraCDCHitsInSuperLayer,
499 "[Eventbased] Returns 1 if a non-assigned hit exists in the specified CDC SuperLayer");
500 REGISTER_VARIABLE(
"nExtraCDCSegments", nExtraCDCSegments,
"[Eventbased] The number of CDC segments not assigned to any track");
507 REGISTER_VARIABLE(
"trackFindingFailureFlag", trackFindingFailureFlag,
508 "[Eventbased] A flag set by the tracking if there is reason to assume there was a track in the event missed by the tracking, "
509 "or the track finding was (partly) aborted for this event.");
DataType Z() const
access variable Z (= .at(2) without boundary check)
static B2Vector3D getFieldInTesla(const B2Vector3D &pos)
return the magnetic field at a given position in Tesla.
EDetector
Enum for identifying the detector components (detector and subdetector).
@ 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.
static const double realNaN
shortcut for NaN of double type
static const TVector3 vecNaN(realNaN, realNaN, realNaN)
vector with NaN entries
Abstract base class for different kinds of events.