10 #include <analysis/variables/Variables.h>
13 #include <analysis/VariableManager/Manager.h>
15 #include <analysis/utility/PCmsLabTransform.h>
16 #include <analysis/utility/ReferenceFrame.h>
17 #include <analysis/utility/MCMatching.h>
18 #include <analysis/ClusterUtility/ClusterUtils.h>
21 #include <framework/datastore/StoreArray.h>
22 #include <framework/datastore/StoreObjPtr.h>
25 #include <analysis/dataobjects/Particle.h>
26 #include <analysis/dataobjects/ParticleList.h>
27 #include <framework/dataobjects/EventExtraInfo.h>
28 #include <analysis/dataobjects/EventShapeContainer.h>
30 #include <mdst/dataobjects/MCParticle.h>
31 #include <mdst/dataobjects/Track.h>
32 #include <mdst/dataobjects/ECLCluster.h>
33 #include <mdst/dataobjects/V0.h>
35 #include <mdst/dbobjects/BeamSpot.h>
38 #include <framework/logging/Logger.h>
39 #include <framework/geometry/B2Vector3.h>
40 #include <framework/geometry/BFieldManager.h>
41 #include <framework/gearbox/Const.h>
42 #include <framework/utilities/Conversion.h>
44 #include <Math/Vector4D.h>
63 double particleP(
const Particle* part)
65 const auto& frame = ReferenceFrame::GetCurrent();
66 return frame.getMomentum(part).P();
69 double particleE(
const Particle* part)
71 const auto& frame = ReferenceFrame::GetCurrent();
72 return frame.getMomentum(part).E();
75 double particleClusterEUncertainty(
const Particle* part)
77 const ECLCluster* cluster = part->getECLCluster();
79 const auto EPhiThetaCov = cluster->getCovarianceMatrix3x3();
80 return std::sqrt(EPhiThetaCov[0][0]);
82 return std::numeric_limits<double>::quiet_NaN();
85 double particlePx(
const Particle* part)
87 const auto& frame = ReferenceFrame::GetCurrent();
88 return frame.getMomentum(part).Px();
91 double particlePy(
const Particle* part)
93 const auto& frame = ReferenceFrame::GetCurrent();
94 return frame.getMomentum(part).Py();
97 double particlePz(
const Particle* part)
99 const auto& frame = ReferenceFrame::GetCurrent();
100 return frame.getMomentum(part).Pz();
103 double particlePt(
const Particle* part)
105 const auto& frame = ReferenceFrame::GetCurrent();
106 return frame.getMomentum(part).Pt();
109 double covMatrixElement(
const Particle* part,
const std::vector<double>& element)
111 int elementI = int(std::lround(element[0]));
112 int elementJ = int(std::lround(element[1]));
114 if (elementI < 0 || elementI > 6) {
115 B2WARNING(
"Requested particle's momentumVertex covariance matrix element is out of boundaries [0 - 6]:" <<
LogVar(
"i", elementI));
116 return std::numeric_limits<double>::quiet_NaN();
118 if (elementJ < 0 || elementJ > 6) {
119 B2WARNING(
"Requested particle's momentumVertex covariance matrix element is out of boundaries [0 - 6]:" <<
LogVar(
"j", elementJ));
120 return std::numeric_limits<double>::quiet_NaN();
123 return part->getMomentumVertexErrorMatrix()(elementI, elementJ);
126 double particleEUncertainty(
const Particle* part)
128 const auto& frame = ReferenceFrame::GetCurrent();
130 double errorSquared = frame.getMomentumErrorMatrix(part)(3, 3);
132 if (errorSquared >= 0.0)
133 return sqrt(errorSquared);
135 return std::numeric_limits<double>::quiet_NaN();
138 double particlePErr(
const Particle* part)
140 TMatrixD jacobianRot(3, 3);
143 double cosPhi = cos(particlePhi(part));
144 double sinPhi = sin(particlePhi(part));
145 double cosTheta = particleCosTheta(part);
146 double sinTheta = sin(acos(cosTheta));
147 double p = particleP(part);
149 jacobianRot(0, 0) = sinTheta * cosPhi;
150 jacobianRot(0, 1) = sinTheta * sinPhi;
151 jacobianRot(1, 0) = cosTheta * cosPhi / p;
152 jacobianRot(1, 1) = cosTheta * sinPhi / p;
153 jacobianRot(0, 2) = cosTheta;
154 jacobianRot(2, 0) = -sinPhi / sinTheta / p;
155 jacobianRot(1, 2) = -sinTheta / p;
156 jacobianRot(2, 1) = cosPhi / sinTheta / p;
158 const auto& frame = ReferenceFrame::GetCurrent();
160 double errorSquared = frame.getMomentumErrorMatrix(part).GetSub(0, 2, 0, 2,
" ").Similarity(jacobianRot)(0, 0);
162 if (errorSquared >= 0.0)
163 return sqrt(errorSquared);
165 return std::numeric_limits<double>::quiet_NaN();
168 double particlePxErr(
const Particle* part)
170 const auto& frame = ReferenceFrame::GetCurrent();
172 double errorSquared = frame.getMomentumErrorMatrix(part)(0, 0);
174 if (errorSquared >= 0.0)
175 return sqrt(errorSquared);
177 return std::numeric_limits<double>::quiet_NaN();
180 double particlePyErr(
const Particle* part)
182 const auto& frame = ReferenceFrame::GetCurrent();
183 double errorSquared = frame.getMomentumErrorMatrix(part)(1, 1);
185 if (errorSquared >= 0.0)
186 return sqrt(errorSquared);
188 return std::numeric_limits<double>::quiet_NaN();
191 double particlePzErr(
const Particle* part)
193 const auto& frame = ReferenceFrame::GetCurrent();
194 double errorSquared = frame.getMomentumErrorMatrix(part)(2, 2);
196 if (errorSquared >= 0.0)
197 return sqrt(errorSquared);
199 return std::numeric_limits<double>::quiet_NaN();
202 double particlePtErr(
const Particle* part)
204 TMatrixD jacobianRot(3, 3);
207 double px = particlePx(part);
208 double py = particlePy(part);
209 double pt = particlePt(part);
211 jacobianRot(0, 0) = px / pt;
212 jacobianRot(0, 1) = py / pt;
213 jacobianRot(1, 0) = -py / (pt * pt);
214 jacobianRot(1, 1) = px / (pt * pt);
215 jacobianRot(2, 2) = 1;
217 const auto& frame = ReferenceFrame::GetCurrent();
218 double errorSquared = frame.getMomentumErrorMatrix(part).GetSub(0, 2, 0, 2,
" ").Similarity(jacobianRot)(0, 0);
220 if (errorSquared >= 0.0)
221 return sqrt(errorSquared);
223 return std::numeric_limits<double>::quiet_NaN();
226 double momentumDeviationChi2(
const Particle* part)
228 double result = std::numeric_limits<double>::quiet_NaN();
231 if (part->getPValue() < 0.0)
240 result += TMath::Power(part->getPx() - mcp->getMomentum().X(), 2.0) / part->getMomentumVertexErrorMatrix()(0, 0);
241 result += TMath::Power(part->getPy() - mcp->getMomentum().Y(), 2.0) / part->getMomentumVertexErrorMatrix()(1, 1);
242 result += TMath::Power(part->getPz() - mcp->getMomentum().Z(), 2.0) / part->getMomentumVertexErrorMatrix()(2, 2);
247 double particleTheta(
const Particle* part)
249 const auto& frame = ReferenceFrame::GetCurrent();
250 return frame.getMomentum(part).Theta();
253 double particleThetaErr(
const Particle* part)
255 TMatrixD jacobianRot(3, 3);
258 double cosPhi = cos(particlePhi(part));
259 double sinPhi = sin(particlePhi(part));
260 double cosTheta = particleCosTheta(part);
261 double sinTheta = sin(acos(cosTheta));
262 double p = particleP(part);
264 jacobianRot(0, 0) = sinTheta * cosPhi;
265 jacobianRot(0, 1) = sinTheta * sinPhi;
266 jacobianRot(1, 0) = cosTheta * cosPhi / p;
267 jacobianRot(1, 1) = cosTheta * sinPhi / p;
268 jacobianRot(0, 2) = cosTheta;
269 jacobianRot(2, 0) = -sinPhi / sinTheta / p;
270 jacobianRot(1, 2) = -sinTheta / p;
271 jacobianRot(2, 1) = cosPhi / sinTheta / p;
273 const auto& frame = ReferenceFrame::GetCurrent();
274 double errorSquared = frame.getMomentumErrorMatrix(part).GetSub(0, 2, 0, 2,
" ").Similarity(jacobianRot)(1, 1);
276 if (errorSquared >= 0.0)
277 return sqrt(errorSquared);
279 return std::numeric_limits<double>::quiet_NaN();
282 double particleCosTheta(
const Particle* part)
284 const auto& frame = ReferenceFrame::GetCurrent();
285 return cos(frame.getMomentum(part).Theta());
288 double particleCosThetaErr(
const Particle* part)
290 return fabs(particleThetaErr(part) * sin(particleTheta(part)));
293 double particlePhi(
const Particle* part)
295 const auto& frame = ReferenceFrame::GetCurrent();
296 return frame.getMomentum(part).Phi();
299 double particlePhiErr(
const Particle* part)
301 TMatrixD jacobianRot(3, 3);
304 double px = particlePx(part);
305 double py = particlePy(part);
306 double pt = particlePt(part);
308 jacobianRot(0, 0) = px / pt;
309 jacobianRot(0, 1) = py / pt;
310 jacobianRot(1, 0) = -py / (pt * pt);
311 jacobianRot(1, 1) = px / (pt * pt);
312 jacobianRot(2, 2) = 1;
314 const auto& frame = ReferenceFrame::GetCurrent();
315 double errorSquared = frame.getMomentumErrorMatrix(part).GetSub(0, 2, 0, 2,
" ").Similarity(jacobianRot)(1, 1);
317 if (errorSquared >= 0.0)
318 return sqrt(errorSquared);
320 return std::numeric_limits<double>::quiet_NaN();
323 double particleXp(
const Particle* part)
326 ROOT::Math::PxPyPzEVector p4 = part -> get4Vector();
327 ROOT::Math::PxPyPzEVector p4CMS = T.rotateLabToCms() * p4;
328 float s = T.getCMSEnergy();
329 float M = part->getMass();
330 return p4CMS.P() / TMath::Sqrt(s * s / 4 - M * M);
333 int particlePDGCode(
const Particle* part)
335 return part->getPDGCode();
338 double cosAngleBetweenMomentumAndVertexVectorInXYPlane(
const Particle* part)
340 static DBObjPtr<BeamSpot> beamSpotDB;
341 double px = part->getPx();
342 double py = part->getPy();
344 double xV = part->getX();
345 double yV = part->getY();
347 double xIP = (beamSpotDB->getIPPosition()).X();
348 double yIP = (beamSpotDB->getIPPosition()).Y();
353 double cosangle = (px * x + py * y) / (sqrt(px * px + py * py) * sqrt(x * x + y * y));
357 double cosAngleBetweenMomentumAndVertexVector(
const Particle* part)
359 static DBObjPtr<BeamSpot> beamSpotDB;
360 return cos((
B2Vector3D(part->getVertex()) - beamSpotDB->getIPPosition()).Angle(
B2Vector3D(part->getMomentum())));
363 double cosThetaBetweenParticleAndNominalB(
const Particle* part)
366 int particlePDG = abs(part->getPDGCode());
367 if (particlePDG != 511 and particlePDG != 521)
368 B2FATAL(
"The Variables cosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
371 double e_Beam = T.getCMSEnergy() / 2.0;
372 double m_B = part->getPDGMass();
374 if (e_Beam * e_Beam - m_B * m_B < 0) {
375 e_Beam = 1.0579400E+1 / 2.0;
377 double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
379 ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * part->get4Vector();
384 double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
389 double cosToThrustOfEvent(
const Particle* part)
391 StoreObjPtr<EventShapeContainer> evtShape;
393 B2WARNING(
"Cannot find thrust of event information, did you forget to load the event shape calculation?");
394 return std::numeric_limits<float>::quiet_NaN();
398 B2Vector3D particleMomentum = (T.rotateLabToCms() * part -> get4Vector()).Vect();
399 return std::cos(th.Angle(particleMomentum));
402 double ImpactXY(
const Particle* particle)
404 static DBObjPtr<BeamSpot> beamSpotDB;
406 ROOT::Math::XYZVector mom = particle->getMomentum();
408 ROOT::Math::XYZVector r = particle->getVertex() - ROOT::Math::XYZVector(beamSpotDB->getIPPosition());
410 ROOT::Math::XYZVector Bfield = BFieldManager::getInstance().getFieldInTesla(ROOT::Math::XYZVector(beamSpotDB->getIPPosition()));
412 ROOT::Math::XYZVector curvature = - Bfield * Const::speedOfLight * particle->getCharge();
413 double T = TMath::Sqrt(mom.Perp2() - 2.0 * curvature.Dot(r.Cross(mom)) + curvature.Mag2() * r.Perp2());
415 return TMath::Abs((-2 * r.Cross(mom).Z() + curvature.R() * r.Perp2()) / (T + mom.Rho()));
418 double ArmenterosLongitudinalMomentumAsymmetry(
const Particle* part)
420 const auto& frame = ReferenceFrame::GetCurrent();
421 int nDaughters = part -> getNDaughters();
423 B2FATAL(
"You are trying to use an Armenteros variable. The mother particle is required to have exactly two daughters");
425 const auto& daughters = part -> getDaughters();
426 B2Vector3D motherMomentum = frame.getMomentum(part).Vect();
427 B2Vector3D daughter1Momentum = frame.getMomentum(daughters[0]).Vect();
428 B2Vector3D daughter2Momentum = frame.getMomentum(daughters[1]).Vect();
430 int daughter1Charge = daughters[0] -> getCharge();
431 int daughter2Charge = daughters[1] -> getCharge();
432 double daughter1Ql = daughter1Momentum.Dot(motherMomentum) / motherMomentum.Mag();
433 double daughter2Ql = daughter2Momentum.Dot(motherMomentum) / motherMomentum.Mag();
436 if (daughter2Charge > daughter1Charge)
437 Arm_alpha = (daughter2Ql - daughter1Ql) / (daughter2Ql + daughter1Ql);
439 Arm_alpha = (daughter1Ql - daughter2Ql) / (daughter1Ql + daughter2Ql);
444 double ArmenterosDaughter1Qt(
const Particle* part)
446 const auto& frame = ReferenceFrame::GetCurrent();
447 int nDaughters = part -> getNDaughters();
449 B2FATAL(
"You are trying to use an Armenteros variable. The mother particle is required to have exactly two daughters.");
451 const auto& daughters = part -> getDaughters();
452 B2Vector3D motherMomentum = frame.getMomentum(part).Vect();
453 B2Vector3D daughter1Momentum = frame.getMomentum(daughters[0]).Vect();
454 double qt = daughter1Momentum.
Perp(motherMomentum);
459 double ArmenterosDaughter2Qt(
const Particle* part)
461 const auto& frame = ReferenceFrame::GetCurrent();
462 int nDaughters = part -> getNDaughters();
464 B2FATAL(
"You are trying to use an Armenteros variable. The mother particle is required to have exactly two daughters.");
466 const auto& daughters = part -> getDaughters();
467 B2Vector3D motherMomentum = frame.getMomentum(part).Vect();
468 B2Vector3D daughter2Momentum = frame.getMomentum(daughters[1]).Vect();
469 double qt = daughter2Momentum.
Perp(motherMomentum);
477 double particleMass(
const Particle* part)
479 return part->getMass();
482 double particleDMass(
const Particle* part)
484 return part->getMass() - part->getPDGMass();
487 double particleInvariantMassFromDaughters(
const Particle* part)
489 const std::vector<Particle*> daughters = part->getDaughters();
490 if (daughters.size() > 0) {
491 ROOT::Math::PxPyPzEVector sum;
492 for (
auto daughter : daughters)
493 sum += daughter->get4Vector();
497 return part->getMass();
501 double particleInvariantMassFromDaughtersDisplaced(
const Particle* part)
503 ROOT::Math::XYZVector vertex = part->getVertex();
504 if (part->getParticleSource() != Particle::EParticleSourceObject::c_V0
505 && vertex.Rho() < 0.5)
return particleInvariantMassFromDaughters(part);
507 const std::vector<Particle*> daughters = part->getDaughters();
508 if (daughters.size() == 0)
return particleInvariantMassFromDaughters(part);
510 const double bField = BFieldManager::getFieldInTesla(vertex).Z();
511 ROOT::Math::PxPyPzMVector sum;
512 for (
auto daughter : daughters) {
513 const TrackFitResult* tfr = daughter->getTrackFitResult();
515 sum += daughter->get4Vector();
518 Helix helix = tfr->getHelix();
519 helix.passiveMoveBy(vertex);
520 double scalingFactor = daughter->getEffectiveMomentumScale();
521 double momX = scalingFactor * helix.getMomentumX(bField);
522 double momY = scalingFactor * helix.getMomentumY(bField);
523 double momZ = scalingFactor * helix.getMomentumZ(bField);
524 float mPDG = daughter->getPDGMass();
525 sum += ROOT::Math::PxPyPzMVector(momX, momY, momZ, mPDG);
530 double particleInvariantMassLambda(
const Particle* part)
532 const std::vector<Particle*> daughters = part->getDaughters();
533 if (daughters.size() == 2) {
534 ROOT::Math::PxPyPzEVector dt1;
535 ROOT::Math::PxPyPzEVector dt2;
536 ROOT::Math::PxPyPzEVector dtsum;
537 double mpi = Const::pionMass;
538 double mpr = Const::protonMass;
539 dt1 = daughters[0]->get4Vector();
540 dt2 = daughters[1]->get4Vector();
541 double E1 = hypot(mpi, dt1.P());
542 double E2 = hypot(mpr, dt2.P());
544 return sqrt((E1 + E2) * (E1 + E2) - dtsum.P() * dtsum.P());
547 return part->getMass();
551 double particleInvariantMassError(
const Particle* part)
553 float invMass = part->getMass();
554 TMatrixFSym covarianceMatrix = part->getMomentumErrorMatrix();
556 TVectorF jacobian(Particle::c_DimMomentum);
557 jacobian[0] = -1.0 * part->getPx() / invMass;
558 jacobian[1] = -1.0 * part->getPy() / invMass;
559 jacobian[2] = -1.0 * part->getPz() / invMass;
560 jacobian[3] = 1.0 * part->getEnergy() / invMass;
562 double result = jacobian * (covarianceMatrix * jacobian);
565 return std::numeric_limits<double>::quiet_NaN();
567 return TMath::Sqrt(result);
570 double particleInvariantMassSignificance(
const Particle* part)
572 return particleDMass(part) / particleInvariantMassError(part);
575 double particleMassSquared(
const Particle* part)
577 ROOT::Math::PxPyPzEVector p4 = part->get4Vector();
581 double b2bTheta(
const Particle* part)
584 ROOT::Math::PxPyPzEVector pcms = T.rotateLabToCms() * part->get4Vector();
585 ROOT::Math::PxPyPzEVector b2bcms(-pcms.Px(), -pcms.Py(), -pcms.Pz(), pcms.E());
586 ROOT::Math::PxPyPzEVector b2blab = T.rotateCmsToLab() * b2bcms;
587 return b2blab.Theta();
590 double b2bPhi(
const Particle* part)
593 ROOT::Math::PxPyPzEVector pcms = T.rotateLabToCms() * part->get4Vector();
594 ROOT::Math::PxPyPzEVector b2bcms(-pcms.Px(), -pcms.Py(), -pcms.Pz(), pcms.E());
595 ROOT::Math::PxPyPzEVector b2blab = T.rotateCmsToLab() * b2bcms;
599 double b2bClusterTheta(
const Particle* part)
602 const ECLCluster* cluster = part->getECLCluster();
603 if (!cluster)
return std::numeric_limits<float>::quiet_NaN();
604 const ECLCluster::EHypothesisBit clusterHypothesis = part->getECLClusterEHypothesisBit();
608 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, clusterHypothesis);
612 ROOT::Math::PxPyPzEVector pcms = T.rotateLabToCms() * p4Cluster;
613 ROOT::Math::PxPyPzEVector b2bcms(-pcms.Px(), -pcms.Py(), -pcms.Pz(), pcms.E());
614 ROOT::Math::PxPyPzEVector b2blab = T.rotateCmsToLab() * b2bcms;
615 return b2blab.Theta();
618 double b2bClusterPhi(
const Particle* part)
621 const ECLCluster* cluster = part->getECLCluster();
622 if (!cluster)
return std::numeric_limits<float>::quiet_NaN();
623 const ECLCluster::EHypothesisBit clusterHypothesis = part->getECLClusterEHypothesisBit();
627 ROOT::Math::PxPyPzEVector p4Cluster = clutls.Get4MomentumFromCluster(cluster, clusterHypothesis);
631 ROOT::Math::PxPyPzEVector pcms = T.rotateLabToCms() * p4Cluster;
632 ROOT::Math::PxPyPzEVector b2bcms(-pcms.Px(), -pcms.Py(), -pcms.Pz(), pcms.E());
633 ROOT::Math::PxPyPzEVector b2blab = T.rotateCmsToLab() * b2bcms;
640 double particleQ(
const Particle* part)
642 float m = part->getMass();
643 for (
unsigned i = 0; i < part->getNDaughters(); i++) {
644 const Particle* child = part->getDaughter(i);
646 m -= child->getMass();
651 double particleDQ(
const Particle* part)
653 float m = part->getMass() - part->getPDGMass();
654 for (
unsigned i = 0; i < part->getNDaughters(); i++) {
655 const Particle* child = part->getDaughter(i);
657 m -= (child->getMass() - child->getPDGMass());
664 double particleMbc(
const Particle* part)
667 ROOT::Math::PxPyPzEVector vec = T.rotateLabToCms() * part->get4Vector();
668 double E = T.getCMSEnergy() / 2;
669 double m2 = E * E - vec.P2();
670 double mbc = m2 >= 0 ? sqrt(m2) : std::numeric_limits<double>::quiet_NaN();
674 double particleDeltaE(
const Particle* part)
677 ROOT::Math::PxPyPzEVector vec = T.rotateLabToCms() * part->get4Vector();
678 return vec.E() - T.getCMSEnergy() / 2;
684 void printParticleInternal(
const Particle* p,
int depth)
687 for (
int i = 0; i < depth; i++) {
690 s << p->getPDGCode();
691 const MCParticle* mcp = p->getMCParticle();
693 unsigned int flags = MCMatching::getMCErrors(p, mcp);
694 s <<
" -> MC: " << mcp->getPDG() <<
", mcErrors: " << flags <<
" ("
695 << MCMatching::explainFlags(flags) <<
")";
696 s <<
", mc-index " << mcp->getIndex();
698 s <<
" (no MC match)";
700 s <<
", mdst-source " << p->getMdstSource();
702 for (
const auto* daughter : p->getDaughters()) {
703 printParticleInternal(daughter, depth + 1);
707 bool printParticle(
const Particle* p)
709 printParticleInternal(p, 0);
714 double particleMCMomentumTransfer2(
const Particle* part)
720 return std::numeric_limits<double>::quiet_NaN();
722 ROOT::Math::PxPyPzEVector pB = mcB->get4Vector();
724 std::vector<MCParticle*> mcDaug = mcB->getDaughters();
727 return std::numeric_limits<double>::quiet_NaN();
731 ROOT::Math::PxPyPzEVector pX;
733 for (
auto mcTemp : mcDaug) {
734 if (abs(mcTemp->getPDG()) <= 16)
737 pX += mcTemp->get4Vector();
740 ROOT::Math::PxPyPzEVector q = pB - pX;
746 double recoilPx(
const Particle* particle)
751 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
754 const auto& frame = ReferenceFrame::GetCurrent();
755 return frame.getMomentum(pIN - particle->get4Vector()).Px();
758 double recoilPy(
const Particle* particle)
763 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
766 const auto& frame = ReferenceFrame::GetCurrent();
767 return frame.getMomentum(pIN - particle->get4Vector()).Py();
770 double recoilPz(
const Particle* particle)
775 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
778 const auto& frame = ReferenceFrame::GetCurrent();
779 return frame.getMomentum(pIN - particle->get4Vector()).Pz();
782 double recoilMomentum(
const Particle* particle)
787 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
790 const auto& frame = ReferenceFrame::GetCurrent();
791 return frame.getMomentum(pIN - particle->get4Vector()).P();
794 double recoilMomentumTheta(
const Particle* particle)
799 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
802 const auto& frame = ReferenceFrame::GetCurrent();
803 return frame.getMomentum(pIN - particle->get4Vector()).Theta();
806 double recoilMomentumPhi(
const Particle* particle)
811 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
814 const auto& frame = ReferenceFrame::GetCurrent();
815 return frame.getMomentum(pIN - particle->get4Vector()).Phi();
818 double recoilEnergy(
const Particle* particle)
823 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
826 const auto& frame = ReferenceFrame::GetCurrent();
827 return frame.getMomentum(pIN - particle->get4Vector()).E();
830 double recoilMass(
const Particle* particle)
835 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
838 const auto& frame = ReferenceFrame::GetCurrent();
839 return frame.getMomentum(pIN - particle->get4Vector()).M();
842 double recoilMassSquared(
const Particle* particle)
847 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
850 const auto& frame = ReferenceFrame::GetCurrent();
851 return frame.getMomentum(pIN - particle->get4Vector()).M2();
854 double m2RecoilSignalSide(
const Particle* part)
857 double beamEnergy = T.getCMSEnergy() / 2.;
858 if (part->getNDaughters() != 2)
return std::numeric_limits<double>::quiet_NaN();
859 ROOT::Math::PxPyPzEVector tagVec = T.rotateLabToCms() * part->getDaughter(0)->get4Vector();
860 ROOT::Math::PxPyPzEVector sigVec = T.rotateLabToCms() * part->getDaughter(1)->get4Vector();
861 tagVec.SetE(-beamEnergy);
862 return (-tagVec - sigVec).M2();
865 double recoilMCDecayType(
const Particle* particle)
867 auto* mcp = particle->getMCParticle();
870 return std::numeric_limits<double>::quiet_NaN();
872 MCParticle* mcMother = mcp->getMother();
875 return std::numeric_limits<double>::quiet_NaN();
877 std::vector<MCParticle*> daughters = mcMother->getDaughters();
879 if (daughters.size() != 2)
880 return std::numeric_limits<double>::quiet_NaN();
882 MCParticle* recoilMC =
nullptr;
883 if (daughters[0]->getArrayIndex() == mcp->getArrayIndex())
884 recoilMC = daughters[1];
886 recoilMC = daughters[0];
888 if (!recoilMC->hasStatus(MCParticle::c_PrimaryParticle))
889 return std::numeric_limits<double>::quiet_NaN();
892 checkMCParticleDecay(recoilMC, decayType,
false);
895 checkMCParticleDecay(recoilMC, decayType,
true);
900 void checkMCParticleDecay(MCParticle* mcp,
int& decayType,
bool recursive)
902 int nHadronicParticles = 0;
903 int nPrimaryParticleDaughters = 0;
904 std::vector<MCParticle*> daughters = mcp->getDaughters();
907 for (
auto& daughter : daughters) {
908 if (!daughter->hasStatus(MCParticle::c_PrimaryParticle))
911 nPrimaryParticleDaughters++;
912 if (abs(daughter->getPDG()) > Const::photon.getPDGCode())
913 nHadronicParticles++;
916 if (nPrimaryParticleDaughters > 1) {
917 for (
auto& daughter : daughters) {
918 if (!daughter->hasStatus(MCParticle::c_PrimaryParticle))
921 if (abs(daughter->getPDG()) == 12 or abs(daughter->getPDG()) == 14 or abs(daughter->getPDG()) == 16) {
923 if (nHadronicParticles == 0) {
937 checkMCParticleDecay(daughter, decayType, recursive);
942 int nRemainingTracksInEvent(
const Particle* particle)
945 StoreArray<Track> tracks;
946 int event_tracks = tracks.getEntries();
949 const auto& daughters = particle->getFinalStateDaughters();
950 for (
const auto& daughter : daughters) {
951 int pdg = abs(daughter->getPDGCode());
952 if (pdg == Const::electron.getPDGCode() or pdg == Const::muon.getPDGCode() or pdg == Const::pion.getPDGCode()
953 or pdg == Const::kaon.getPDGCode() or pdg == Const::proton.getPDGCode())
956 return event_tracks - par_tracks;
959 double trackMatchType(
const Particle* particle)
962 double result = std::numeric_limits<double>::quiet_NaN();
964 const ECLCluster* cluster = particle->getECLCluster();
968 if (cluster->isTrack()) {
977 bool False(
const Particle*)
982 bool True(
const Particle*)
987 double infinity(
const Particle*)
989 double inf = std::numeric_limits<double>::infinity();
993 double random(
const Particle*)
995 return gRandom->Uniform(0, 1);
998 double eventRandom(
const Particle*)
1000 std::string key =
"__eventRandom";
1001 StoreObjPtr<EventExtraInfo> eventExtraInfo;
1002 if (not eventExtraInfo.isValid())
1003 eventExtraInfo.create();
1004 if (eventExtraInfo->hasExtraInfo(key)) {
1005 return eventExtraInfo->getExtraInfo(key);
1007 double value = gRandom->Uniform(0, 1);
1008 eventExtraInfo->addExtraInfo(key, value);
1013 Manager::FunctionPtr particleDistToClosestExtTrk(
const std::vector<std::string>& arguments)
1015 if (arguments.size() != 3 && arguments.size() != 4) {
1016 B2ERROR(
"Wrong number of arguments (3 or 4 required) for meta variable minET2ETDist");
1019 bool useHighestProbMassForExt(
true);
1020 if (arguments.size() == 4) {
1022 useHighestProbMassForExt =
static_cast<bool>(Belle2::convertString<int>(arguments[3]));
1023 }
catch (std::invalid_argument& e) {
1024 B2ERROR(
"Fourth (optional) argument of minET2ETDist must be an integer flag.");
1029 std::string detName = arguments[0];
1030 std::string detLayer = arguments[1];
1031 std::string referenceListName = arguments[2];
1032 std::string extraSuffix = (useHighestProbMassForExt) ?
"__useHighestProbMassForExt" :
"";
1034 std::string extraInfo =
"distToClosestTrkAt" + detName + detLayer +
"_VS_" + referenceListName + extraSuffix;
1036 auto func = [ = ](
const Particle * part) ->
double {
1037 auto dist = (part->hasExtraInfo(extraInfo)) ? part->getExtraInfo(extraInfo) : std::numeric_limits<float>::quiet_NaN();
1046 Manager::FunctionPtr particleDistToClosestExtTrkVar(
const std::vector<std::string>& arguments)
1048 if (arguments.size() != 4) {
1049 B2ERROR(
"Wrong number of arguments (4 required) for meta variable minET2ETDistVar");
1053 std::string detName = arguments[0];
1054 std::string detLayer = arguments[1];
1055 std::string referenceListName = arguments[2];
1056 std::string variableName = arguments[3];
1058 std::string extraInfo =
"idxOfClosestPartAt" + detName + detLayer +
"In_" + referenceListName;
1060 auto func = [ = ](
const Particle * part) ->
double {
1062 StoreObjPtr<ParticleList> refPartList(referenceListName);
1063 if (!refPartList.isValid())
1065 B2FATAL(
"Invalid Listname " << referenceListName <<
" given to minET2ETDistVar!");
1068 if (!part->hasExtraInfo(extraInfo))
1070 return std::numeric_limits<float>::quiet_NaN();
1073 const Variable::Manager::Var* var = Manager::Instance().getVariable(variableName);
1074 auto refPart = refPartList->getParticleWithMdstIdx(part->getExtraInfo(extraInfo));
1076 return std::get<double>(var->function(refPart));
1083 Manager::FunctionPtr particleExtTrkIsoScoreVar(
const std::vector<std::string>& arguments)
1086 if (arguments.size() < 3) {
1087 B2ERROR(
"Wrong number of arguments (at least 3 required) for meta variable minET2ETIsoScore");
1091 std::string referenceListName = arguments[0];
1092 bool useHighestProbMassForExt;
1094 useHighestProbMassForExt =
static_cast<bool>(Belle2::convertString<int>(arguments[1]));
1095 }
catch (std::invalid_argument& e) {
1096 B2ERROR(
"Second argument must be an integer flag.");
1099 std::string extraSuffix = (useHighestProbMassForExt) ?
"__useHighestProbMassForExt" :
"";
1101 std::vector<std::string> detectorNames(arguments.begin() + 2, arguments.end());
1103 auto func = [ = ](
const Particle * part) ->
double {
1105 StoreObjPtr<ParticleList> refPartList(referenceListName);
1106 if (!refPartList.isValid())
1108 B2FATAL(
"Invalid Listname " << referenceListName <<
" given to minET2ETIsoScore!");
1111 double scoreSum(0.0);
1112 for (
auto& detName : detectorNames)
1114 std::string extraInfo =
"trkIsoScore" + detName +
"_VS_" + referenceListName + extraSuffix;
1115 if (!part->hasExtraInfo(extraInfo)) {
1116 return std::numeric_limits<float>::quiet_NaN();
1118 auto scoreDet = part->getExtraInfo(extraInfo);
1119 if (std::isnan(scoreDet)) {
1120 return std::numeric_limits<float>::quiet_NaN();
1122 scoreSum += scoreDet;
1127 auto maxScore = detectorNames.size();
1128 return (scoreSum - minScore) / (maxScore - minScore);
1135 VARIABLE_GROUP(
"Kinematics");
1136 REGISTER_VARIABLE(
"p", particleP,
"momentum magnitude",
"GeV/c");
1137 REGISTER_VARIABLE(
"E", particleE,
"energy",
"GeV");
1139 REGISTER_VARIABLE(
"E_uncertainty", particleEUncertainty, R
"DOC(energy uncertainty (:math:`\sqrt{\sigma^2}`))DOC", "GeV");
1140 REGISTER_VARIABLE(
"ECLClusterE_uncertainty", particleClusterEUncertainty,
1141 "energy uncertainty as given by the underlying ECL cluster",
"GeV");
1142 REGISTER_VARIABLE(
"px", particlePx,
"momentum component x",
"GeV/c");
1143 REGISTER_VARIABLE(
"py", particlePy,
"momentum component y",
"GeV/c");
1144 REGISTER_VARIABLE(
"pz", particlePz,
"momentum component z",
"GeV/c");
1145 REGISTER_VARIABLE(
"pt", particlePt,
"transverse momentum",
"GeV/c");
1146 REGISTER_VARIABLE(
"xp", particleXp,
1147 "scaled momentum: the momentum of the particle in the CMS as a fraction of its maximum available momentum in the collision");
1148 REGISTER_VARIABLE(
"pErr", particlePErr,
"error of momentum magnitude",
"GeV/c");
1149 REGISTER_VARIABLE(
"pxErr", particlePxErr,
"error of momentum component x",
"GeV/c");
1150 REGISTER_VARIABLE(
"pyErr", particlePyErr,
"error of momentum component y",
"GeV/c");
1151 REGISTER_VARIABLE(
"pzErr", particlePzErr,
"error of momentum component z",
"GeV/c");
1152 REGISTER_VARIABLE(
"ptErr", particlePtErr,
"error of transverse momentum",
"GeV/c");
1153 REGISTER_VARIABLE(
"momVertCovM(i,j)", covMatrixElement,
1154 "returns the (i,j)-th element of the MomentumVertex Covariance Matrix (7x7).\n"
1155 "Order of elements in the covariance matrix is: px, py, pz, E, x, y, z.",
"GeV/c, GeV/c, GeV/c, GeV, cm, cm, cm");
1156 REGISTER_VARIABLE(
"momDevChi2", momentumDeviationChi2, R
"DOC(
1157 momentum deviation :math:`\chi^2` value calculated as :math:`\chi^2 = \sum_i (p_i - mc(p_i))^2/\sigma(p_i)^2`,
1158 where :math:`\sum` runs over i = px, py, pz and :math:`mc(p_i)` is the mc truth value and :math:`\sigma(p_i)` is the estimated error of i-th component of momentum vector
1160 REGISTER_VARIABLE("theta", particleTheta,
"polar angle",
"rad");
1161 REGISTER_VARIABLE(
"thetaErr", particleThetaErr,
"error of polar angle",
"rad");
1162 REGISTER_VARIABLE(
"cosTheta", particleCosTheta,
"momentum cosine of polar angle");
1163 REGISTER_VARIABLE(
"cosThetaErr", particleCosThetaErr,
"error of momentum cosine of polar angle");
1164 REGISTER_VARIABLE(
"phi", particlePhi,
"momentum azimuthal angle",
"rad");
1165 REGISTER_VARIABLE(
"phiErr", particlePhiErr,
"error of momentum azimuthal angle",
"rad");
1166 REGISTER_VARIABLE(
"PDG", particlePDGCode,
"PDG code");
1167 REGISTER_VARIABLE(
"cosAngleBetweenMomentumAndVertexVectorInXYPlane",
1168 cosAngleBetweenMomentumAndVertexVectorInXYPlane,
1169 "cosine of the angle between momentum and vertex vector (vector connecting ip and fitted vertex) of this particle in xy-plane");
1170 REGISTER_VARIABLE(
"cosAngleBetweenMomentumAndVertexVector",
1171 cosAngleBetweenMomentumAndVertexVector,
1172 "cosine of the angle between momentum and vertex vector (vector connecting ip and fitted vertex) of this particle");
1173 REGISTER_VARIABLE(
"cosThetaBetweenParticleAndNominalB",
1174 cosThetaBetweenParticleAndNominalB,
1175 "cosine of the angle in CMS between momentum the particle and a nominal B particle. It is somewhere between -1 and 1 if only a massless particle like a neutrino is missing in the reconstruction.");
1176 REGISTER_VARIABLE(
"cosToThrustOfEvent", cosToThrustOfEvent,
1177 "Returns the cosine of the angle between the particle and the thrust axis of the event, as calculate by the EventShapeCalculator module. buildEventShape() must be run before calling this variable");
1179 REGISTER_VARIABLE(
"ImpactXY" , ImpactXY ,
"The impact parameter of the given particle in the xy plane",
"cm");
1181 REGISTER_VARIABLE(
"M", particleMass, R
"DOC(
1182 The particle's mass.
1184 Note that this is context-dependent variable and can take different values depending on the situation. This should be the "best" value possible with the information provided.
1186 - If this particle is track- or cluster- based, then this is the value of the mass hypothesis.
1187 - If this particle is an MC particle then this is the mass of that particle.
1188 - If this particle is composite, then *initially* this takes the value of the invariant mass of the daughters.
1189 - If this particle is composite and a *mass or vertex fit* has been performed then this may be updated by the fit.
1191 * You will see a difference between this mass and the :b2:var:`InvM`.
1192 )DOC", "GeV/:math:`\\text{c}^2`");
1193 REGISTER_VARIABLE(
"dM", particleDMass,
"mass minus nominal mass",
"GeV/:math:`\\text{c}^2`");
1194 REGISTER_VARIABLE(
"Q", particleQ,
"energy released in decay",
"GeV");
1195 REGISTER_VARIABLE(
"dQ", particleDQ,
":b2:var:`Q` minus nominal energy released in decay",
"GeV");
1196 REGISTER_VARIABLE(
"Mbc", particleMbc,
"beam constrained mass",
"GeV/:math:`\\text{c}^2`");
1197 REGISTER_VARIABLE(
"deltaE", particleDeltaE,
"difference between :b2:var:`E` and half the center of mass energy",
"GeV");
1198 REGISTER_VARIABLE(
"M2", particleMassSquared,
"The particle's mass squared.",
":math:`[\\text{GeV}/\\text{c}^2]^2`");
1200 REGISTER_VARIABLE(
"InvM", particleInvariantMassFromDaughtersDisplaced,
1201 "invariant mass (determined from particle's daughter 4-momentum vectors). If this particle is V0 or decays at rho > 5 mm, its daughter 4-momentum vectors at fitted vertex are taken.\n"
1202 "If this particle has no daughters, defaults to :b2:var:`M`.",
"GeV/:math:`\\text{c}^2`");
1203 REGISTER_VARIABLE(
"InvMLambda", particleInvariantMassLambda,
1204 "Invariant mass (determined from particle's daughter 4-momentum vectors), assuming the first daughter is a pion and the second daughter is a proton.\n"
1205 "If the particle has not 2 daughters, it returns just the mass value.",
"GeV/:math:`\\text{c}^2`");
1207 REGISTER_VARIABLE(
"ErrM", particleInvariantMassError,
1208 "uncertainty of invariant mass",
"GeV/:math:`\\text{c}^2`");
1209 REGISTER_VARIABLE(
"SigM", particleInvariantMassSignificance,
1210 "signed deviation of particle's invariant mass from its nominal mass in units of the uncertainty on the invariant mass (:b2:var:`dM`/:b2:var:`ErrM`)");
1212 REGISTER_VARIABLE(
"pxRecoil", recoilPx,
1213 "component x of 3-momentum recoiling against given Particle",
"GeV/c");
1214 REGISTER_VARIABLE(
"pyRecoil", recoilPy,
1215 "component y of 3-momentum recoiling against given Particle",
"GeV/c");
1216 REGISTER_VARIABLE(
"pzRecoil", recoilPz,
1217 "component z of 3-momentum recoiling against given Particle",
"GeV/c");
1219 REGISTER_VARIABLE(
"pRecoil", recoilMomentum,
1220 "magnitude of 3 - momentum recoiling against given Particle",
"GeV/c");
1221 REGISTER_VARIABLE(
"pRecoilTheta", recoilMomentumTheta,
1222 "Polar angle of a particle's missing momentum",
"rad");
1223 REGISTER_VARIABLE(
"pRecoilPhi", recoilMomentumPhi,
1224 "Azimuthal angle of a particle's missing momentum",
"rad");
1225 REGISTER_VARIABLE(
"eRecoil", recoilEnergy,
1226 "energy recoiling against given Particle",
"GeV");
1227 REGISTER_VARIABLE(
"mRecoil", recoilMass,
1228 "Invariant mass of the system recoiling against given Particle",
"GeV/:math:`\\text{c}^2`");
1229 REGISTER_VARIABLE(
"m2Recoil", recoilMassSquared,
1230 "invariant mass squared of the system recoiling against given Particle",
":math:`[\\text{GeV}/\\text{c}^2]^2`");
1231 REGISTER_VARIABLE(
"m2RecoilSignalSide", m2RecoilSignalSide,
1232 "Squared recoil mass of the signal side which is calculated in the CMS frame under the assumption that the signal and tag side are produced back to back and the tag side energy equals the beam energy. The variable must be applied to the Upsilon and the tag side must be the first, the signal side the second daughter",
1233 ":math:`[\\text{GeV}/\\text{c}^2]^2`");
1235 REGISTER_VARIABLE(
"b2bTheta", b2bTheta,
1236 "Polar angle in the lab system that is back-to-back to the particle in the CMS. Useful for low multiplicity studies.",
"rad");
1237 REGISTER_VARIABLE(
"b2bPhi", b2bPhi,
1238 "Azimuthal angle in the lab system that is back-to-back to the particle in the CMS. Useful for low multiplicity studies.",
"rad");
1239 REGISTER_VARIABLE(
"b2bClusterTheta", b2bClusterTheta,
1240 "Polar angle in the lab system that is back-to-back to the particle's associated ECLCluster in the CMS. Returns NAN if no cluster is found. Useful for low multiplicity studies.",
1242 REGISTER_VARIABLE(
"b2bClusterPhi", b2bClusterPhi,
1243 "Azimuthal angle in the lab system that is back-to-back to the particle's associated ECLCluster in the CMS. Returns NAN if no cluster is found. Useful for low multiplicity studies.",
1245 REGISTER_VARIABLE(
"ArmenterosLongitudinalMomentumAsymmetry", ArmenterosLongitudinalMomentumAsymmetry,
1246 "Longitudinal momentum asymmetry of V0's daughters.\n"
1247 "The mother (V0) is required to have exactly two daughters");
1248 REGISTER_VARIABLE(
"ArmenterosDaughter1Qt", ArmenterosDaughter1Qt,
1249 "Transverse momentum of the first daughter with respect to the V0 mother.\n"
1250 "The mother is required to have exactly two daughters",
"GeV/c");
1251 REGISTER_VARIABLE(
"ArmenterosDaughter2Qt", ArmenterosDaughter2Qt,
1252 "Transverse momentum of the second daughter with respect to the V0 mother.\n"
1253 "The mother is required to have exactly two daughters",
"GeV/c");
1255 VARIABLE_GROUP(
"Miscellaneous");
1256 REGISTER_VARIABLE(
"nRemainingTracksInEvent", nRemainingTracksInEvent,
1257 "Number of tracks in the event - Number of tracks( = charged FSPs) of particle.");
1258 REGISTER_VARIABLE(
"trackMatchType", trackMatchType, R
"DOC(
1260 * -1 particle has no ECL cluster
1261 * 0 particle has no associated track
1262 * 1 there is a matched track called connected - region(CR) track match
1265 Use better variables like `trackNECLClusters`, `clusterTrackMatch`, and `nECLClusterTrackMatches`.)DOC");
1267 REGISTER_VARIABLE("decayTypeRecoil", recoilMCDecayType,
1268 "type of the particle decay(no related mcparticle = -1, hadronic = 0, direct leptonic = 1, direct semileptonic = 2,"
1269 "lower level leptonic = 3.");
1271 REGISTER_VARIABLE(
"printParticle", printParticle,
1272 "For debugging, print Particle and daughter PDG codes, plus MC match. Returns 0.");
1273 REGISTER_VARIABLE(
"mcMomTransfer2", particleMCMomentumTransfer2,
1274 "Return the true momentum transfer to lepton pair in a B(semi -) leptonic B meson decay.",
"GeV/c");
1275 REGISTER_VARIABLE(
"False", False,
1276 "returns always 0, used for testing and debugging.");
1277 REGISTER_VARIABLE(
"True", True,
1278 "returns always 1, used for testing and debugging.");
1279 REGISTER_VARIABLE(
"infinity", infinity,
1280 "returns std::numeric_limits<double>::infinity()");
1281 REGISTER_VARIABLE(
"random", random,
1282 "return a random number between 0 and 1 for each candidate. Can be used, e.g. for picking a random"
1283 "candidate in the best candidate selection.");
1284 REGISTER_VARIABLE(
"eventRandom", eventRandom,
1285 "[Eventbased] Returns a random number between 0 and 1 for this event. Can be used, e.g. for applying an event prescale.");
1286 REGISTER_METAVARIABLE(
"minET2ETDist(detName, detLayer, referenceListName, useHighestProbMassForExt=1)", particleDistToClosestExtTrk,
1287 R
"DOC(Returns the distance in [cm] between the particle and the nearest particle in the reference list at the given detector layer surface.
1288 The definition is based on the track helices extrapolation.
1290 * The first argument is the name of the detector to consider.
1291 * The second argument is the detector layer on whose surface we search for the nearest neighbour.
1292 * The third argument is the reference particle list name used to search for the nearest neighbour.
1293 * The fourth (optional) argument is an integer ("boolean") flag: if 1 (the default, if nothing is set), it is assumed the extrapolation was done with the most probable mass hypothesis for the track fit;
1294 if 0, it is assumed the mass hypothesis matching the particle lists' PDG was used.
1297 This variable requires to run the ``TrackIsoCalculator`` module first.
1298 Note that the choice of input parameters of this metafunction must correspond to the settings used to configure the module!
1300 Manager::VariableDataType::c_double);
1302 REGISTER_METAVARIABLE("minET2ETDistVar(detName, detLayer, referenceListName, variableName)", particleDistToClosestExtTrkVar,
1303 R
"DOC(Returns the value of the variable for the nearest neighbour to this particle as taken from the reference list at the given detector layer surface.
1304 , according to the distance definition of `minET2ETDist`.
1306 * The first argument is the name of the detector to consider.
1307 * The second argument is the detector layer on whose surface we search for the nearest neighbour.
1308 * The third argument is the reference particle list name used to search for the nearest neighbour.
1309 * The fourth argument is a variable name, e.g. `nCDCHits`.
1312 This variable requires to run the ``TrackIsoCalculator`` module first.
1313 Note that the choice of input parameters of this metafunction must correspond to the settings used to configure the module!
1315 Manager::VariableDataType::c_double);
1317 REGISTER_METAVARIABLE("minET2ETIsoScore(referenceListName, useHighestProbMassForExt, detectorList)", particleExtTrkIsoScoreVar,
1318 R
"DOC(Returns the particle's isolation score based on:
1320 * The number of detector layers where a close-enough neighbour to this particle is found, according to the distance definition of `minET2ETDist` and a set of thresholds defined in the ``TrackIsoCalculator`` module.
1321 * A set of per-detector weights quantifying the impact of each detector on the PID for this particle type.
1323 The score is normalised in [0, 1], where values closer to 1 indicates a well-isolated particle.
1326 The detector weights are considered for the score definition only if ``excludePIDDetWeights=false`` in the ``TrackIsoCalculator`` module configuration.
1328 * The first argument is the reference particle list name used to search for the nearest neighbour.
1329 * The second argument is an integer ("boolean") flag: if 1, it is assumed the extrapolation was done with the most probable mass hypothesis for the track fit;
1330 if 0, it is assumed the mass hypothesis matching the particle lists' PDG was used.
1331 * The remaining arguments are a comma-separated list of detector names. At least one must be chosen among {CDC, TOP, ARICH, ECL, KLM}.
1334 This variable requires to run the ``TrackIsoCalculator`` module first.
1335 Note that the choice of input parameters of this metafunction must correspond to the settings used to configure the module!
1337 Manager::VariableDataType::c_double);
DataType Perp() const
The transverse component (R in cylindrical coordinate system).
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
Class to store variables with their name which were sent to the logging service.
#define MAKE_DEPRECATED(name, make_fatal, version, description)
Registers a variable as deprecated.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Abstract base class for different kinds of events.