10 #include <analysis/variables/FlavorTaggingVariables.h>
11 #include <analysis/variables/MCTruthVariables.h>
12 #include <analysis/variables/KLMClusterVariables.h>
13 #include <analysis/utility/PCmsLabTransform.h>
15 #include <analysis/ClusterUtility/ClusterUtils.h>
17 #include <analysis/utility/MCMatching.h>
20 #include <framework/datastore/StoreObjPtr.h>
23 #include <analysis/dataobjects/Particle.h>
24 #include <analysis/dataobjects/RestOfEvent.h>
25 #include <analysis/dataobjects/ParticleList.h>
26 #include <analysis/dataobjects/FlavorTaggerInfo.h>
27 #include <analysis/ContinuumSuppression/Thrust.h>
29 #include <mdst/dataobjects/MCParticle.h>
30 #include <mdst/dataobjects/Track.h>
31 #include <mdst/dataobjects/ECLCluster.h>
32 #include <mdst/dataobjects/KLMCluster.h>
33 #include <mdst/dataobjects/PIDLikelihood.h>
37 #include <framework/gearbox/Const.h>
38 #include <framework/logging/Logger.h>
40 #include <TLorentzVector.h>
55 auto& labToCms = PCmsLabTransform::labToCms;
56 static const double realNaN = std::numeric_limits<double>::quiet_NaN();
61 double momentumMissingTagSide(
const Particle*)
63 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
64 if (!roe.isValid())
return 0;
66 TLorentzVector roeCMSVec;
68 const auto& roeChargedParticles = roe->getChargedParticles();
69 for (
auto roeChargedParticle : roeChargedParticles) {
70 roeCMSVec += labToCms(roeChargedParticle->get4Vector());
73 double missMom = -roeCMSVec.P();
77 double cosTPTO(
const Particle* part)
79 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
80 if (!roe.isValid())
return 0;
82 std::vector<TVector3> p3_cms_roe;
83 static const double P_MAX(3.2);
87 const auto& roeTracks = roe->getChargedParticles();
88 for (
auto& roeChargedParticle : roeTracks) {
91 TLorentzVector p_cms = labToCms(roeChargedParticle->get4Vector());
92 if (p_cms != p_cms)
continue;
93 if (p_cms.Rho() > P_MAX)
continue;
94 p3_cms_roe.push_back(p_cms.Vect());
98 const auto& roePhotons = roe->getPhotons();
99 for (
auto& roePhoton : roePhotons) {
100 if (roePhoton->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons) {
101 TLorentzVector p_lab = roePhoton->get4Vector();
102 if (p_lab != p_lab)
continue;
103 if (p_lab.Rho() < 0.05)
continue;
104 TLorentzVector p_cms = labToCms(p_lab);
105 if (p_cms != p_cms)
continue;
106 if (p_cms.Rho() > P_MAX)
continue;
107 p3_cms_roe.push_back(p_cms.Vect());
111 const auto& roeKlongs = roe->getHadrons();
112 for (
auto& roeKlong : roeKlongs) {
113 if (nKLMClusterTrackMatches(roeKlong) == 0 && !(roeKlong->getKLMCluster()->getAssociatedEclClusterFlag())) {
114 TLorentzVector p_lab = roeKlong->get4Vector();
115 if (p_lab != p_lab)
continue;
116 if (p_lab.Rho() < 0.05)
continue;
117 TLorentzVector p_cms = labToCms(p_lab);
118 if (p_cms != p_cms)
continue;
119 if (p_cms.Rho() > P_MAX)
continue;
120 p3_cms_roe.push_back(p_cms.Vect());
124 const TVector3 thrustO = Thrust::calculateThrust(p3_cms_roe);
125 const TVector3 pAxis = labToCms(part->get4Vector()).Vect();
128 if (pAxis == pAxis) result = abs(cos(pAxis.Angle(thrustO)));
133 double lambdaFlavor(
const Particle* particle)
135 if (particle->getPDGCode() == Const::Lambda.getPDGCode())
return 1.0;
136 else if (particle->getPDGCode() == Const::antiLambda.getPDGCode())
return -1.0;
140 double isLambda(
const Particle* particle)
142 const MCParticle* mcparticle = particle->getMCParticle();
143 if (!mcparticle)
return 0.0;
144 return (abs(mcparticle->getPDG()) == Const::Lambda.getPDGCode());
147 double lambdaZError(
const Particle* particle)
151 TMatrixFSym ErrorPositionMatrix = particle->getVertexErrorMatrix();
152 return ErrorPositionMatrix[2][2];
155 double momentumOfSecondDaughter(
const Particle* part)
157 if (!part->getDaughter(1))
return 0.0;
158 return part->getDaughter(1)->getP();
161 double momentumOfSecondDaughterCMS(
const Particle* part)
163 if (!part->getDaughter(1))
return 0.0;
164 TLorentzVector vec = labToCms(part->getDaughter(1)->get4Vector());
168 double chargeTimesKaonLiklihood(
const Particle*)
170 StoreObjPtr<ParticleList> KaonList(
"K+:inRoe");
171 if (!KaonList.isValid())
return 0;
173 double maximumKaonid = 0;
174 double maximum_charge = 0;
175 for (
unsigned int i = 0; i < KaonList->getListSize(); ++i) {
176 const Particle* p = KaonList->getParticle(i);
177 double Kid = p->getRelatedTo<PIDLikelihood>()->getProbability(Const::kaon, Const::pion);
178 if (Kid > maximumKaonid) {
180 maximum_charge = p->getCharge();
183 return maximumKaonid * maximum_charge;
186 double transverseMomentumOfChargeTracksInRoe(
const Particle* part)
188 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
189 if (!roe.isValid())
return 0;
193 for (
const auto& track : roe->getChargedParticles()) {
194 if (part->isCopyOf(track,
true))
continue;
195 sum += track->getMomentum().Perp2();
202 double NumberOfKShortsInRoe(
const Particle* particle)
204 StoreObjPtr<ParticleList> KShortList(
"K_S0:inRoe");
205 if (!KShortList.isValid())
206 B2FATAL(
"NumberOfKShortsInRoe cannot be calculated because the required particleList K_S0:inRoe could not be found or is not valid");
210 for (
unsigned int i = 0; i < KShortList->getListSize(); ++i) {
211 if (!particle->overlapsWith(KShortList->getParticle(i)))
219 double isInElectronOrMuonCat(
const Particle* particle)
222 StoreObjPtr<ParticleList> MuonList(
"mu+:inRoe");
223 const Track* trackTargetMuon =
nullptr;
224 if (MuonList.isValid()) {
225 double maximumProbMuon = 0;
226 for (
unsigned int i = 0; i < MuonList->getListSize(); ++i) {
227 Particle* pMuon = MuonList->getParticle(i);
228 double probMuon = pMuon->getExtraInfo(
"isRightTrack(Muon)");
229 if (probMuon > maximumProbMuon) {
230 maximumProbMuon = probMuon;
231 trackTargetMuon = pMuon -> getTrack();
235 if (particle->getTrack() == trackTargetMuon)
240 StoreObjPtr<ParticleList> ElectronList(
"e+:inRoe");
241 const Track* trackTargetElectron =
nullptr;
242 if (ElectronList.isValid()) {
243 double maximumProbElectron = 0;
244 for (
unsigned int i = 0; i < ElectronList->getListSize(); ++i) {
245 Particle* pElectron = ElectronList->getParticle(i);
246 double probElectron = pElectron->getExtraInfo(
"isRightTrack(Electron)");
247 if (probElectron > maximumProbElectron) {
248 maximumProbElectron = probElectron;
249 trackTargetElectron = pElectron -> getTrack();
253 if (particle->getTrack() == trackTargetElectron)
260 static int getB0flavourMC(
const MCParticle* mcParticle)
263 if (mcParticle->getPDG() == 511) {
265 }
else if (mcParticle->getPDG() == -511) {
268 mcParticle = mcParticle->getMother();
275 double isMajorityInRestOfEventFromB0(
const Particle*)
277 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
278 if (!roe.isValid())
return 0;
281 for (
auto& track : roe->getChargedParticles()) {
282 const MCParticle* mcParticle = track->getMCParticle();
283 vote += getB0flavourMC(mcParticle);
289 double isMajorityInRestOfEventFromB0bar(
const Particle*)
291 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
292 if (!roe.isValid())
return 0;
295 for (
auto& track : roe->getChargedParticles()) {
296 const MCParticle* mcParticle = track->getMCParticle();
297 vote += getB0flavourMC(mcParticle);
303 double hasRestOfEventTracks(
const Particle* part)
305 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
306 return (roe && roe-> getNTracks() > 0);
309 double isRelatedRestOfEventB0Flavor(
const Particle* particle)
311 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
314 const MCParticle* BcpMC = particle->getMCParticle();
315 if (!BcpMC)
return 0;
316 if (Variable::isSignal(particle) <= 0)
return 0;
318 const MCParticle* Y4S = BcpMC->getMother();
324 for (
auto& roeChargedParticle : roe->getChargedParticles()) {
325 const MCParticle* mcParticle = roeChargedParticle->
getMCParticle();
327 if (mcParticle->getMother() == Y4S) {
328 if (mcParticle == BcpMC) {
329 if (mcParticle->getPDG() > 0) BcpFlavor = 2;
331 }
else if (BtagFlavor == 0) {
332 if (abs(mcParticle->getPDG()) == 511 || abs(mcParticle->getPDG()) == 521) {
333 if (mcParticle->getPDG() > 0) BtagFlavor = 1;
334 else BtagFlavor = -1;
335 }
else BtagFlavor = 5;
341 if (BcpFlavor != 0 || BtagFlavor == 5)
break;
345 return (BcpFlavor != 0) ? BcpFlavor : BtagFlavor;
348 double isRestOfEventB0Flavor(
const Particle*)
350 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
351 if (!roe.isValid())
return 0;
353 const Particle* Bcp = roe->getRelated<Particle>();
354 return Variable::isRelatedRestOfEventB0Flavor(Bcp);
357 double ancestorHasWhichFlavor(
const Particle* particle)
359 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
360 if (!roe.isValid())
return 0;
362 const MCParticle* BcpMC = roe->
getRelated<Particle>()->getMCParticle();
363 const MCParticle* Y4S = BcpMC->getMother();
364 const MCParticle* mcParticle = particle->getMCParticle();
366 int outputB0tagQ = 0;
368 if (mcParticle->getMother() == Y4S) {
369 if (mcParticle != BcpMC && abs(mcParticle -> getPDG()) == 511) {
370 if (mcParticle -> getPDG() == 511) outputB0tagQ = 1;
371 else outputB0tagQ = -1;
372 }
else if (mcParticle == BcpMC) {
373 if (mcParticle -> getPDG() == 511) outputB0tagQ = 2;
374 else outputB0tagQ = -2;
375 }
else outputB0tagQ = 5;
378 mcParticle = mcParticle->getMother();
384 double B0mcErrors(
const Particle*)
386 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
387 if (!roe.isValid())
return -1;
389 const Particle* Bcp = roe->getRelated<Particle>();
390 const MCParticle* BcpMC = roe->
getRelated<Particle>()->getMCParticle();
391 return MCMatching::getMCErrors(Bcp, BcpMC);
395 double isRelatedRestOfEventMajorityB0Flavor(
const Particle* part)
397 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
402 if (roe->getNTracks() > 0) {
403 for (
auto& track : roe->getChargedParticles()) {
404 const MCParticle* mcParticle = track->getMCParticle();
405 q_MC += getB0flavourMC(mcParticle);
407 }
else if (roe->getNECLClusters() > 0) {
408 for (
auto& cluster : roe->getPhotons()) {
409 if (cluster->getECLClusterEHypothesisBit() != ECLCluster::EHypothesisBit::c_nPhotons)
continue;
410 const MCParticle* mcParticle = cluster->getMCParticle();
411 q_MC += getB0flavourMC(mcParticle);
413 }
else if (roe->getNKLMClusters() > 0) {
414 for (
auto& klmcluster : roe->getHadrons()) {
416 q_MC += getB0flavourMC(mcParticle);
426 double isRestOfEventMajorityB0Flavor(
const Particle*)
428 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
429 if (!roe.isValid())
return -2;
431 const Particle* Bcp = roe->getRelated<Particle>();
432 return Variable::isRelatedRestOfEventMajorityB0Flavor(Bcp);
435 double mcFlavorOfOtherB(
const Particle* particle)
438 if (std::abs(particle->getPDGCode()) != 511 && std::abs(particle->getPDGCode()) != 521) {
439 B2ERROR(
"MCFlavorOfOtherB: this variable works only for B mesons.\n"
440 "The given particle with PDG code " << particle->getPDGCode() <<
441 " is not a B-meson candidate (PDG code 511 or 521). ");
445 const MCParticle* mcParticle = particle->getMCParticle();
446 if (!mcParticle)
return realNaN;
448 const MCParticle* mcMother = mcParticle->getMother();
451 if (Variable::isSignal(particle) < 1.0)
return 0;
453 for (
auto& upsilon4SDaughter : mcMother->getDaughters()) {
454 if (upsilon4SDaughter == mcParticle)
continue;
455 return (upsilon4SDaughter->getPDG() > 0) ? 1 : -1;
466 Manager::FunctionPtr BtagToWBosonVariables(
const std::vector<std::string>& arguments)
468 if (arguments.size() == 1) {
469 auto requestedVariable = arguments[0];
470 auto func = [requestedVariable](
const Particle * particle) ->
double {
471 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
472 if (!roe.isValid())
return 0;
474 TLorentzVector momXChargedTracks;
476 const auto& roeChargedParticles = roe->getChargedParticles();
477 for (
auto& roeChargedParticle : roeChargedParticles)
479 if (roeChargedParticle->isCopyOf(particle,
true))
continue;
480 momXChargedTracks += roeChargedParticle->get4Vector();
483 TLorentzVector momXNeutralClusters = roe->get4VectorNeutralECLClusters();
485 const auto& klongs = roe->getHadrons();
486 for (
auto& klong : klongs)
488 if (nKLMClusterTrackMatches(klong) == 0 && !(klong->getKLMCluster()->getAssociatedEclClusterFlag())) {
489 momXNeutralClusters += klong->get4Vector();
493 TLorentzVector momX = PCmsLabTransform::labToCms(momXChargedTracks + momXNeutralClusters);
494 TLorentzVector momTarget = PCmsLabTransform::labToCms(particle->get4Vector());
495 TLorentzVector momMiss = -(momX + momTarget);
498 if (requestedVariable ==
"recoilMass") output = momX.M();
499 else if (requestedVariable ==
"recoilMassSqrd") output = momX.M2();
500 else if (requestedVariable ==
"pMissCMS") output = momMiss.Vect().Mag();
501 else if (requestedVariable ==
"cosThetaMissCMS") output = TMath::Cos(momTarget.Angle(momMiss.Vect()));
502 else if (requestedVariable ==
"EW90")
505 TLorentzVector momW = momTarget + momMiss;
508 const auto& photons = roe->getPhotons();
509 for (
auto& photon : photons) {
510 if (PCmsLabTransform::labToCms(photon->get4Vector()).Vect().Dot(momW.Vect()) > 0) {
511 E_W_90 += photon->getECLClusterEnergy();
514 for (
auto& roeChargedParticle : roeChargedParticles) {
515 if (!roeChargedParticle->isCopyOf(particle,
true)) {
516 for (
const ECLCluster& chargedCluster : roeChargedParticle->getTrack()->getRelationsWith<ECLCluster>()) {
518 if (!chargedCluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
520 float iEnergy = chargedCluster.getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
521 if (iEnergy == iEnergy) {
522 if (PCmsLabTransform::labToCms(ClusterUtils().Get4MomentumFromCluster(&chargedCluster,
523 ECLCluster::EHypothesisBit::c_nPhotons)).Vect().Dot(momW.Vect()) > 0)
532 B2FATAL(
"Wrong variable " << requestedVariable <<
533 " requested. The possibilities are recoilMass, recoilMassSqrd, pMissCMS, cosThetaMissCMS or EW90");
540 B2FATAL(
"Wrong number of arguments (1 required) for meta function BtagToWBosonVariables");
544 Manager::FunctionPtr KaonPionVariables(
const std::vector<std::string>& arguments)
546 if (arguments.size() != 1)
547 B2FATAL(
"Wrong number of arguments (1 required) for meta function KaonPionVariables");
550 auto requestedVariable = arguments[0];
551 auto func = [requestedVariable](
const Particle * particle) ->
double {
553 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
556 if ((requestedVariable !=
"HaveOpositeCharges") && (requestedVariable !=
"cosKaonPion"))
557 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are cosKaonPion or HaveOpositeCharges");
560 TLorentzVector momTargetSlowPion;
561 double chargeTargetSlowPion = 0;
562 if (SlowPionList.isValid())
564 double maximumProbSlowPion = 0;
565 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
566 Particle* pSlowPion = SlowPionList->getParticle(i);
567 if (!pSlowPion)
continue;
568 if (!pSlowPion->hasExtraInfo(
"isRightCategory(SlowPion)"))
continue;
570 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
571 if (probSlowPion > maximumProbSlowPion) {
572 maximumProbSlowPion = probSlowPion;
573 chargeTargetSlowPion = pSlowPion->getCharge();
574 momTargetSlowPion = labToCms(pSlowPion->get4Vector());
581 double chargeTargetKaon = particle->getCharge();
582 if (requestedVariable ==
"HaveOpositeCharges")
584 if (chargeTargetKaon * chargeTargetSlowPion == -1)
588 else if (requestedVariable ==
"cosKaonPion")
590 TLorentzVector momTargetKaon = labToCms(particle->get4Vector());
591 if (momTargetKaon == momTargetKaon && momTargetSlowPion == momTargetSlowPion)
592 output = cos(momTargetKaon.Angle(momTargetSlowPion.Vect()));
600 Manager::FunctionPtr FSCVariables(
const std::vector<std::string>& arguments)
602 if (arguments.size() != 1)
603 B2FATAL(
"Wrong number of arguments (1 required) for meta function FSCVariables");
606 auto requestedVariable = arguments[0];
607 auto func = [requestedVariable](
const Particle * particle) ->
double {
608 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
609 if (!FastParticleList.isValid())
return 0;
612 if ((requestedVariable !=
"pFastCMS") && (requestedVariable !=
"cosSlowFast") && (requestedVariable !=
"cosTPTOFast") && (requestedVariable !=
"SlowFastHaveOpositeCharges"))
613 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are pFastCMS, cosSlowFast, cosTPTOFast or SlowFastHaveOpositeCharges");
616 double maximumProbFastest = 0;
617 TLorentzVector momFastParticle;
618 Particle* TargetFastParticle =
nullptr;
619 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i)
621 Particle* particlei = FastParticleList->getParticle(i);
622 if (!particlei)
continue;
624 TLorentzVector momParticlei = labToCms(particlei->get4Vector());
625 if (momParticlei != momParticlei)
continue;
627 double probFastest = momParticlei.P();
628 if (probFastest > maximumProbFastest) {
629 maximumProbFastest = probFastest;
630 TargetFastParticle = particlei;
631 momFastParticle = momParticlei;
636 if (!TargetFastParticle)
return 0;
641 if (requestedVariable ==
"cosTPTOFast")
642 output = Variable::Manager::Instance().getVariable(
"cosTPTO")->function(TargetFastParticle);
644 TLorentzVector momSlowPion = labToCms(particle->get4Vector());
645 if (momSlowPion == momSlowPion)
647 if (requestedVariable ==
"cosSlowFast") {
648 output = cos(momSlowPion.Angle(momFastParticle.Vect()));
649 }
else if (requestedVariable ==
"SlowFastHaveOpositeCharges") {
650 if (particle->getCharge()*TargetFastParticle->getCharge() == -1) {
654 output = momFastParticle.P();
663 Manager::FunctionPtr hasHighestProbInCat(
const std::vector<std::string>& arguments)
665 if (arguments.size() != 2) {
666 B2FATAL(
"Wrong number of arguments (2 required) for meta function hasHighestProbInCat");
670 auto extraInfoName = arguments[1];
671 auto func = [
particleListName, extraInfoName](
const Particle * particle) ->
double {
672 if (!(extraInfoName ==
"isRightTrack(Electron)" || extraInfoName ==
"isRightTrack(IntermediateElectron)" || extraInfoName ==
"isRightTrack(Muon)" || extraInfoName ==
"isRightTrack(IntermediateMuon)"
673 || extraInfoName ==
"isRightTrack(KinLepton)" || extraInfoName ==
"isRightTrack(IntermediateKinLepton)" || extraInfoName ==
"isRightTrack(Kaon)"
674 || extraInfoName ==
"isRightTrack(SlowPion)" || extraInfoName ==
"isRightTrack(FastHadron)" || extraInfoName ==
"isRightTrack(MaximumPstar)" || extraInfoName ==
"isRightTrack(Lambda)"
675 || extraInfoName ==
"isRightCategory(Electron)" || extraInfoName ==
"isRightCategory(IntermediateElectron)" || extraInfoName ==
"isRightCategory(Muon)" || extraInfoName ==
"isRightCategory(IntermediateMuon)"
676 || extraInfoName ==
"isRightCategory(KinLepton)" || extraInfoName ==
"isRightCategory(IntermediateKinLepton)" || extraInfoName ==
"isRightCategory(Kaon)"
677 || extraInfoName ==
"isRightCategory(SlowPion)" || extraInfoName ==
"isRightCategory(FastHadron)" || extraInfoName ==
"isRightCategory(KaonPion)" || extraInfoName ==
"isRightCategory(Lambda)"
678 || extraInfoName ==
"isRightCategory(MaximumPstar)" || extraInfoName ==
"isRightCategory(FSC)"))
680 B2FATAL(
"hasHighestProbInCat: Not available category" << extraInfoName <<
681 ". The possibilities for isRightTrack() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda."
683 "The possibilities for isRightCategory() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
687 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
688 if (!ListOfParticles.isValid())
return 0;
690 double maximumProb = 0;
691 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
693 const Particle* particlei = ListOfParticles->getParticle(i);
694 if (!particlei)
continue;
697 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
698 TLorentzVector momParticlei = labToCms(particlei -> get4Vector());
699 if (momParticlei == momParticlei) {
700 prob = momParticlei.P();
703 if (particlei->hasExtraInfo(extraInfoName)) {
704 prob = particlei->getExtraInfo(extraInfoName);
707 if (prob > maximumProb) {
714 if ((extraInfoName ==
"isRightTrack(MaximumPstar)") && (labToCms(particle->get4Vector()).P() == maximumProb))
717 }
else if (extraInfoName !=
"isRightTrack(MaximumPstar)" && particle->hasExtraInfo(extraInfoName))
719 if (particle->getExtraInfo(extraInfoName) == maximumProb) output = 1.0;
727 Manager::FunctionPtr HighestProbInCat(
const std::vector<std::string>& arguments)
729 if (arguments.size() != 2) {
730 B2FATAL(
"Wrong number of arguments (2 required) for meta function HighestProbInCat");
734 auto extraInfoName = arguments[1];
736 if (!(extraInfoName ==
"isRightTrack(Electron)" || extraInfoName ==
"isRightTrack(IntermediateElectron)" || extraInfoName ==
"isRightTrack(Muon)" || extraInfoName ==
"isRightTrack(IntermediateMuon)"
737 || extraInfoName ==
"isRightTrack(KinLepton)" || extraInfoName ==
"isRightTrack(IntermediateKinLepton)" || extraInfoName ==
"isRightTrack(Kaon)"
738 || extraInfoName ==
"isRightTrack(SlowPion)" || extraInfoName ==
"isRightTrack(FastHadron)" || extraInfoName ==
"isRightTrack(MaximumPstar)" || extraInfoName ==
"isRightTrack(Lambda)"
739 || extraInfoName ==
"isRightCategory(Electron)" || extraInfoName ==
"isRightCategory(IntermediateElectron" || extraInfoName ==
"isRightCategory(Muon)" || extraInfoName ==
"isRightCategory(IntermediateMuon)"
740 || extraInfoName ==
"isRightCategory(KinLepton)" || extraInfoName ==
"isRightCategory(IntermediateKinLepton)" || extraInfoName ==
"isRightCategory(Kaon)"
741 || extraInfoName ==
"isRightCategory(SlowPion)" || extraInfoName ==
"isRightCategory(FastHadron)" || extraInfoName ==
"isRightCategory(KaonPion)" || extraInfoName ==
"isRightCategory(Lambda)"
742 || extraInfoName ==
"isRightCategory(MaximumPstar)" || extraInfoName ==
"isRightCategory(FSC)"))
744 B2FATAL(
"HighestProbInCat: Not available category" << extraInfoName <<
745 ". The possibilities for isRightTrack() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda."
747 "The possibilities for isRightCategory() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
751 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
752 if (!ListOfParticles.isValid())
return 0;
754 double maximumProb = 0;
755 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
757 const Particle* particlei = ListOfParticles->getParticle(i);
758 if (!particlei)
continue;
761 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
762 TLorentzVector momParticlei = labToCms(particlei -> get4Vector());
763 if (momParticlei == momParticlei) {
764 prob = momParticlei.P();
767 if (particlei->hasExtraInfo(extraInfoName)) {
768 prob = particlei->getExtraInfo(extraInfoName);
771 maximumProb = max(maximumProb, prob);
782 const std::vector<int> charmMesons = { 411, 421, 10411, 10421, 413, 423, 10413, 10423, 20413, 20423, 415, 425, 431, 10431, 433, 10433, 20433, 435};
784 const std::vector<int> charmBaryons = { 4122, 4222, 4212, 4112, 4224, 4214, 4114, 4232, 4132, 4322, 4312, 4324, 4314, 4332, 4334, 4412, 4422,
785 4414, 4424, 4432, 4434, 4444
788 const std::vector<int> qqbarMesons = {
789 111, 9000111, 100111, 10111, 200111, 113, 10113, 20113, 9000113, 100113, 9010113, 9020113, 30113, 9030113, 9040113,
790 115, 10115, 100115, 9000115, 117, 9000117, 9010117, 119,
792 221, 331, 9000221, 9010221, 100221, 10221, 100331, 9020221, 10331, 200221, 9030221, 9040221, 9050221, 9060221, 9070221, 223, 333, 10223, 20223,
793 10333, 20333, 100223, 9000223, 9010223, 30223, 100333, 225, 9000225, 335, 9010225, 9020225, 10225, 9030225, 10335, 9040225, 100225, 100335,
794 9050225, 9060225, 9070225, 227, 337, 229, 9000339, 9000229,
796 441, 10441, 100441, 443, 10443, 20443, 100443, 30443, 9000443, 9010443, 9020443, 445, 9000445
799 const std::vector<int> flavorConservingMesons = {
800 9000211, 100211, 10211, 200211, 213, 10213, 20213, 9000213, 100213, 9010213, 9020213, 30213, 9030213, 9040213,
801 215, 10215, 100215, 9000215, 217, 9000217, 9010217, 219,
803 30343, 10311, 10321, 100311, 100321, 200311, 200321, 9000311, 9000321, 313, 323, 10313, 10323, 20313, 20323, 100313, 100323,
804 9000313, 9000323, 30313, 30323, 315, 325, 9000315, 9000325, 10315, 10325, 20315, 20325, 100315, 100325, 9010315,
805 9010325, 317, 327, 9010317, 9010327, 319, 329, 9000319, 9000329
808 Manager::FunctionPtr isRightTrack(
const std::vector<std::string>& arguments)
810 if (arguments.size() != 1) {
811 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightTrack");
817 std::vector<std::string> names = {
"Electron",
818 "IntermediateElectron",
822 "IntermediateKinLepton",
830 unsigned index = std::find(names.begin(), names.end(), particleName) - names.begin();
831 if (index == names.size()) {
832 B2FATAL(
"isRightTrack: Not available category " << particleName <<
833 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron and Lambda");
836 auto func = [index](
const Particle * particle) ->
double {
838 const MCParticle* mcParticle = particle->getMCParticle();
839 if (!mcParticle)
return -2.0;
841 int mcPDG = abs(mcParticle->getPDG());
844 std::vector<int> mothersPDG;
845 std::vector<const MCParticle*> mothersPointers;
847 const MCParticle* mcMother = mcParticle->getMother();
850 mothersPDG.push_back(abs(mcMother->getPDG()));
851 if (index == 8) mothersPointers.push_back(mcMother);
852 if (abs(mcMother->getPDG()) == 511)
break;
853 mcMother = mcMother -> getMother();
856 if (mothersPDG.size() == 0)
return -2.0;
859 if (index == 10)
return 1.0;
863 bool isCharmedMesonInChain =
false;
864 if ((index == 6) && mothersPDG.size() > 1)
866 for (
auto& iMCMotherPDG : mothersPDG) {
867 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
868 isCharmedMesonInChain =
true;
876 bool isCharmedBaryonInChain =
false;
877 if ((index == 6 || index == 9) && mothersPDG.size() > 1)
879 for (
auto& iMCMotherPDG : mothersPDG) {
880 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
881 isCharmedBaryonInChain =
true;
889 bool isQQbarMesonInChain =
false;
890 if ((index == 1 || index == 3 || index == 5 || index == 6 || index == 8) && mothersPDG.size() > 1)
892 for (
auto& iMCMotherPDG : mothersPDG) {
893 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
894 isQQbarMesonInChain =
true;
902 bool isB0DaughterConservingFlavor =
false;
903 if ((index == 8) && mothersPDG.size() > 1)
905 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
906 mothersPDG.rbegin()[1]) != flavorConservingMesons.end()) {
907 isB0DaughterConservingFlavor =
true;
913 bool isHadronSingleTauDaughter =
false;
914 if (index == 8 && mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
916 int numberOfChargedDaughters = 0;
917 for (
auto& tauDaughter : mothersPointers.rbegin()[1] -> getDaughters()) {
918 if (tauDaughter -> getCharge() != 0) numberOfChargedDaughters += 1;
920 if (numberOfChargedDaughters == 1) isHadronSingleTauDaughter =
true;
925 && mcPDG == Const::electron.getPDGCode()
926 && mothersPDG[0] == 511)
930 }
else if (index == 1
931 && mcPDG == Const::electron.getPDGCode() && mothersPDG.size() > 1
932 && isQQbarMesonInChain ==
false)
936 }
else if (index == 2
937 && mcPDG == Const::muon.getPDGCode() && mothersPDG[0] == 511)
941 }
else if (index == 3
942 && mcPDG == Const::muon.getPDGCode() && mothersPDG.size() > 1
943 && isQQbarMesonInChain ==
false)
947 }
else if (index == 4
948 && (mcPDG == Const::muon.getPDGCode() || mcPDG == Const::electron.getPDGCode()) && mothersPDG[0] == 511)
952 }
else if (index == 5
953 && (mcPDG == Const::muon.getPDGCode() || mcPDG == Const::electron.getPDGCode()) && mothersPDG.size() > 1
954 && isQQbarMesonInChain ==
false)
958 }
else if (index == 6
959 && mcPDG == Const::kaon.getPDGCode() && isQQbarMesonInChain ==
false && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
963 }
else if (index == 7
964 && mcPDG == Const::pion.getPDGCode() && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
968 }
else if (index == 8
969 && (mcPDG == Const::pion.getPDGCode() || mcPDG == Const::kaon.getPDGCode()) && isQQbarMesonInChain ==
false && (mothersPDG[0] == 511 || (mothersPDG.rbegin()[0] == 511
970 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
974 }
else if (index == 9 && mcPDG == Const::Lambda.getPDGCode() && isCharmedBaryonInChain ==
true)
982 Manager::FunctionPtr isRightCategory(
const std::vector<std::string>& arguments)
984 if (arguments.size() != 1) {
985 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightCategory");
991 const std::vector<std::string> names = {
"Electron",
992 "IntermediateElectron",
996 "IntermediateKinLepton",
1007 unsigned index = find(names.begin(), names.end(), particleName) - names.begin();
1008 if (index == names.size()) {
1009 B2FATAL(
"isRightCategory: Not available category " << particleName <<
1010 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1013 auto func = [index](
const Particle * particle) ->
double {
1015 Particle* nullParticle =
nullptr;
1016 double qTarget = particle -> getCharge();
1017 double qMC = Variable::isRestOfEventB0Flavor(nullParticle);
1019 const MCParticle* mcParticle = particle->getMCParticle();
1020 if (!mcParticle)
return -2.0;
1022 int mcPDG = abs(mcParticle->getPDG());
1025 std::vector<int> mothersPDG;
1026 std::vector<const MCParticle*> mothersPointers;
1028 const MCParticle* mcMother = mcParticle->getMother();
1031 mothersPDG.push_back(abs(mcMother->getPDG()));
1032 if (index == 8 || index == 9) mothersPointers.push_back(mcMother);
1033 if (abs(mcMother->getPDG()) == 511)
break;
1034 mcMother = mcMother->getMother();
1037 if (mothersPDG.size() == 0)
return -2.0;
1039 if (index == 13)
return 1.0;
1043 bool isCharmedMesonInChain =
false;
1044 if ((index == 6) && mothersPDG.size() > 1)
1046 for (
auto& iMCMotherPDG : mothersPDG) {
1047 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1048 isCharmedMesonInChain =
true;
1056 bool isCharmedBaryonInChain =
false;
1057 if ((index == 6 || index == 12) && mothersPDG.size() > 1)
1059 for (
auto& iMCMotherPDG : mothersPDG) {
1060 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1061 isCharmedBaryonInChain =
true;
1069 bool isQQbarMesonInChain =
false;
1070 if ((index == 1 || index == 3 || index == 5 || index == 6 || index == 8 || index == 11) && mothersPDG.size() > 1)
1072 for (
auto& iMCMotherPDG : mothersPDG) {
1073 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1074 isQQbarMesonInChain =
true;
1082 bool isB0DaughterConservingFlavor =
false;
1083 if ((index == 8) && mothersPDG.size() > 1)
1085 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1086 mothersPDG.rbegin()[1]) != flavorConservingMesons.end()) {
1087 isB0DaughterConservingFlavor =
true;
1094 bool isHadronSingleTauDaughter =
false;
1095 if (index == 8 && mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1097 int numberOfChargedDaughters = 0;
1098 for (
auto& tauDaughter : mothersPointers.rbegin()[1] -> getDaughters()) {
1099 if (tauDaughter -> getCharge() != 0) numberOfChargedDaughters += 1;
1101 if (numberOfChargedDaughters == 1) isHadronSingleTauDaughter =
true;
1105 bool haveKaonPionSameMother =
false;
1109 const MCParticle* mcSlowPionMother =
nullptr;
1110 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
1111 Particle* targetSlowPion =
nullptr;
1112 if (SlowPionList.isValid()) {
1113 double mcProbSlowPion = 0;
1114 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
1115 Particle* pSlowPion = SlowPionList->getParticle(i);
1116 if (!pSlowPion)
continue;
1117 if (pSlowPion -> hasExtraInfo(
"isRightCategory(SlowPion)")) {
1118 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
1119 if (probSlowPion > mcProbSlowPion) {
1120 mcProbSlowPion = probSlowPion;
1121 targetSlowPion = pSlowPion;
1125 if (targetSlowPion !=
nullptr) {
1126 const MCParticle* mcSlowPion = targetSlowPion ->
getMCParticle();
1128 if (mcSlowPion !=
nullptr && mcSlowPion->getMother() !=
nullptr
1129 && abs(mcSlowPion->getPDG()) == Const::pion.getPDGCode() && abs(mcSlowPion->getMother()->getPDG()) == 413) {
1130 mcSlowPionMother = mcSlowPion->
getMother();
1135 if (std::find(mothersPointers.begin(), mothersPointers.end(), mcSlowPionMother) != mothersPointers.end())
1136 haveKaonPionSameMother =
true;
1141 int FastParticlePDGMother = 0;
1146 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
1147 Particle* targetFastParticle =
nullptr;
1148 if (FastParticleList.isValid()) {
1149 double mcProbFastest = 0;
1150 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i) {
1151 Particle* particlei = FastParticleList->getParticle(i);
1152 if (!particlei)
continue;
1154 TLorentzVector momParticlei = labToCms(particlei -> get4Vector());
1155 if (momParticlei == momParticlei) {
1156 double probFastest = momParticlei.P();
1157 if (probFastest > mcProbFastest) {
1158 mcProbFastest = probFastest;
1159 targetFastParticle = particlei;
1163 if (targetFastParticle !=
nullptr) {
1164 const MCParticle* mcFastParticle = targetFastParticle ->
getMCParticle();
1166 if (mcFastParticle !=
nullptr && mcFastParticle->getMother() !=
nullptr) {
1167 FastParticlePDGMother = abs(mcFastParticle->getMother()->getPDG());
1168 qFSC = mcFastParticle->getCharge();
1176 && qTarget == qMC && mcPDG == Const::electron.getPDGCode() && mothersPDG[0] == 511)
1179 }
else if (index == 1
1180 && qTarget != qMC && mcPDG == Const::electron.getPDGCode() && mothersPDG.size() > 1
1181 && isQQbarMesonInChain ==
false)
1184 }
else if (index == 2
1185 && qTarget == qMC && mcPDG == Const::muon.getPDGCode() && mothersPDG[0] == 511)
1188 }
else if (index == 3
1189 && qTarget != qMC && mcPDG == Const::muon.getPDGCode() && mothersPDG.size() > 1
1190 && isQQbarMesonInChain ==
false)
1193 }
else if (index == 4
1194 && qTarget == qMC && (mcPDG == Const::electron.getPDGCode() || mcPDG == Const::muon.getPDGCode()) && mothersPDG[0] == 511)
1197 }
else if (index == 5
1198 && qTarget != qMC && (mcPDG == Const::electron.getPDGCode() || mcPDG == Const::muon.getPDGCode()) && mothersPDG.size() > 1
1199 && isQQbarMesonInChain ==
false)
1202 }
else if (index == 6 && qTarget == qMC
1203 && mcPDG == Const::kaon.getPDGCode() && isQQbarMesonInChain ==
false && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1206 }
else if (index == 7 && qTarget != qMC
1207 && mcPDG == Const::pion.getPDGCode() && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1210 }
else if (index == 8 && qTarget == qMC
1211 && (mcPDG == Const::pion.getPDGCode() || mcPDG == Const::kaon.getPDGCode()) && isQQbarMesonInChain ==
false && (mothersPDG[0] == 511 || (mothersPDG.rbegin()[0] == 511
1212 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1215 }
else if (index == 9 && qTarget == qMC
1216 && mcPDG == Const::kaon.getPDGCode() && haveKaonPionSameMother ==
true)
1219 }
else if (index == 10 && qTarget == qMC)
1222 }
else if (index == 11 && qTarget != qMC && mothersPDG.size() > 1 && qFSC == qMC
1223 && mcPDG == Const::pion.getPDGCode() && FastParticlePDGMother == 511 && isQQbarMesonInChain ==
false)
1226 }
else if (index == 12 && (particle->getPDGCode() / abs(particle->getPDGCode())) != qMC
1227 && mcPDG == Const::Lambda.getPDGCode() && isCharmedBaryonInChain ==
true)
1240 std::vector<std::string> availableExtraInfos = {
"isRightTrack(Electron)",
1241 "isRightTrack(IntermediateElectron)",
1242 "isRightTrack(Muon)",
1243 "isRightTrack(IntermediateMuon)",
1244 "isRightTrack(KinLepton)",
1245 "isRightTrack(IntermediateKinLepton)",
1246 "isRightTrack(Kaon)",
1247 "isRightTrack(SlowPion)",
1248 "isRightTrack(FastHadron)",
1249 "isRightTrack(MaximumPstar)",
1250 "isRightTrack(Lambda)",
1251 "isRightCategory(Electron)",
1252 "isRightCategory(IntermediateElectron)",
1253 "isRightCategory(Muon)",
1254 "isRightCategory(IntermediateMuon)",
1255 "isRightCategory(KinLepton)",
1256 "isRightCategory(IntermediateKinLepton)",
1257 "isRightCategory(Kaon)",
1258 "isRightCategory(SlowPion)",
1259 "isRightCategory(FastHadron)",
1260 "isRightCategory(MaximumPstar)",
1261 "isRightCategory(Lambda)",
1262 "isRightCategory(KaonPion)",
1263 "isRightCategory(FSC)",
1266 Manager::FunctionPtr QpOf(
const std::vector<std::string>& arguments)
1268 if (arguments.size() != 3) {
1269 B2FATAL(
"Wrong number of arguments (3 required) for meta function QpOf");
1274 auto outputExtraInfo = arguments[1];
1275 auto rankingExtraInfo = arguments[2];
1277 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1278 rankingExtraInfo) - availableExtraInfos.begin();
1279 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1280 outputExtraInfo) - availableExtraInfos.begin();
1282 if (indexRanking == availableExtraInfos.size()) {
1283 B2FATAL(
"QpOf: Not available category " << rankingExtraInfo <<
1284 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1286 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1289 if (indexOutput == availableExtraInfos.size()) {
1290 B2FATAL(
"QpOf: Not available category " << outputExtraInfo <<
1291 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1293 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1297 auto func = [
particleListName, indexOutput, indexRanking](
const Particle*) ->
double {
1298 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1299 if (!ListOfParticles.isValid())
return 0;
1301 Particle* target =
nullptr;
1302 double maximumTargetProb = 0;
1303 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1305 Particle* particlei = ListOfParticles->getParticle(i);
1306 if (!particlei)
continue;
1308 double target_prob = 0;
1309 if (indexRanking == 9 || indexRanking == 20) {
1310 TLorentzVector momParticlei = labToCms(particlei -> get4Vector());
1311 if (momParticlei == momParticlei) {
1312 target_prob = momParticlei.P();
1315 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
1316 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
1320 if (target_prob > maximumTargetProb) {
1321 maximumTargetProb = target_prob;
1327 if (!target)
return 0;
1331 if (indexRanking == 10 || indexRanking == 21)
1333 qTarget = (-1) * target->getPDGCode() / abs(target->getPDGCode());
1335 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1336 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18)
1338 qTarget = (-1) * target -> getCharge();
1340 qTarget = target -> getCharge();
1344 double prob = target -> getExtraInfo(availableExtraInfos[indexOutput]);
1348 return qTarget * prob;
1353 Manager::FunctionPtr weightedQpOf(
const std::vector<std::string>& arguments)
1355 if (arguments.size() != 3) {
1356 B2FATAL(
"Wrong number of arguments (3 required) for meta function weightedQpOf");
1362 auto outputExtraInfo = arguments[1];
1363 auto rankingExtraInfo = arguments[2];
1366 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1367 rankingExtraInfo) - availableExtraInfos.begin();
1368 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1369 outputExtraInfo) - availableExtraInfos.begin();
1372 if (indexRanking == availableExtraInfos.size()) {
1373 B2FATAL(
"weightedQpOf: Not available category " << rankingExtraInfo <<
1374 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1376 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1379 if (indexOutput == availableExtraInfos.size()) {
1380 B2FATAL(
"weightedQpOf: Not available category " << outputExtraInfo <<
1381 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1383 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1386 auto func = [
particleListName, indexOutput, indexRanking, rankingExtraInfo](
const Particle*) ->
double {
1388 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1389 if (!ListOfParticles)
return 0;
1390 if (ListOfParticles->getListSize() == 0)
return 0;
1393 auto compare = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1396 if (part1->hasExtraInfo(rankingExtraInfo)) info1 = part1->getExtraInfo(rankingExtraInfo);
1397 if (part2->hasExtraInfo(rankingExtraInfo)) info2 = part2->getExtraInfo(rankingExtraInfo);
1398 return (info1 > info2);
1401 auto compareMomentum = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1402 double info1 = labToCms(part1 -> get4Vector()).P();
1403 double info2 = labToCms(part2 -> get4Vector()).P();
1404 return (info1 > info2);
1407 std::vector<const Particle*> ParticleVector(ListOfParticles->getListSize());
1408 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1410 ParticleVector[i] = ListOfParticles->getParticle(i);
1413 if (indexRanking == 9 || indexRanking == 20)
1414 std::sort(ParticleVector.begin(), ParticleVector.end(), compareMomentum);
1416 std::sort(ParticleVector.begin(), ParticleVector.end(),
compare);
1419 double final_value = 0.0;
1420 if (ParticleVector.size() != 0) final_value = 1.0;
1423 int Limit = min(3,
int(ParticleVector.size()));
1426 for (
int i = 0; i < Limit; ++i)
1428 if (ParticleVector[i]->hasExtraInfo(availableExtraInfos[indexOutput])) {
1429 double flavor = 0.0;
1430 if (indexRanking == 10 || indexRanking == 21) {
1431 flavor = - copysign(1, ParticleVector[i]->getPDGCode());
1433 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1434 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18) {
1435 flavor = - ParticleVector[i]->getCharge();
1437 flavor = + ParticleVector[i]->getCharge();
1440 double p = ParticleVector[i]->getExtraInfo(availableExtraInfos[indexOutput]);
1443 double qp = (flavor * p);
1448 final_value = (val1 - val2) / (val1 + val2);
1455 Manager::FunctionPtr variableOfTarget(
const std::vector<std::string>& arguments)
1458 if (arguments.size() != 3)
1459 B2FATAL(
"Wrong number of arguments (3 required) for meta function variableOfTarget");
1462 std::string inputVariable = arguments[1];
1463 std::string rankingExtraInfo = arguments[2];
1465 int indexRanking = -1;
1467 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1468 if (rankingExtraInfo == availableExtraInfos[i]) {indexRanking = i;
break;}
1471 if (indexRanking == -1) {
1472 B2FATAL(
"variableOfTarget: category " << rankingExtraInfo <<
"not available" <<
1473 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1475 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1479 auto func = [
particleListName, inputVariable, indexRanking](
const Particle*) ->
double {
1480 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1481 if (!ListOfParticles.isValid())
return realNaN;
1483 Particle* target =
nullptr;
1485 double maximumTargetProb = 0;
1486 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1488 Particle* particlei = ListOfParticles->getParticle(i);
1489 if (!particlei)
continue;
1491 double target_prob = 0;
1492 if (indexRanking == 9 || indexRanking == 20) {
1493 TLorentzVector momParticlei = labToCms(particlei->get4Vector());
1494 if (momParticlei == momParticlei) {
1495 target_prob = momParticlei.P();
1498 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
1499 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
1502 if (target_prob > maximumTargetProb) {
1503 maximumTargetProb = target_prob;
1511 Variable::Manager& manager = Variable::Manager::Instance();
1512 double output = manager.getVariable(inputVariable)->function(target);
1518 Manager::FunctionPtr hasTrueTarget(
const std::vector<std::string>& arguments)
1520 if (arguments.size() != 1) {
1521 B2FATAL(
"Wrong number of arguments (1 required) for meta function hasTrueTarget");
1524 auto categoryName = arguments[0];
1525 auto func = [categoryName](
const Particle*) ->
double {
1526 if (!(categoryName ==
"Electron" || categoryName ==
"IntermediateElectron" || categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton" || categoryName ==
"Kaon"
1527 || categoryName ==
"SlowPion" || categoryName ==
"FastHadron" || categoryName ==
"KaonPion" || categoryName ==
"Lambda" || categoryName ==
"MaximumPstar" || categoryName ==
"FSC"))
1529 B2FATAL(
"hasTrueTarget: Not available category" << categoryName <<
1530 ". The possibilities for the category name are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1535 std::string trackTargetName = categoryName;
1537 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron")
particleListName =
"e+:inRoe";
1538 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton")
particleListName =
"mu+:inRoe";
1539 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {
particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
1543 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
1545 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1546 if (!ListOfParticles.isValid())
return realNaN;
1548 Variable::Manager& manager = Variable::Manager::Instance();
1551 bool particlesHaveMCAssociated =
false;
1553 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1555 Particle* iParticle = ListOfParticles->getParticle(i);
1556 if (!iParticle)
continue;
1558 double targetFlag = 0;
1559 if (categoryName ==
"MaximumPstar") {
1560 targetFlag = manager.getVariable(
"hasHighestProbInCat(pi+:inRoe, isRightTrack(MaximumPstar))")->
function(iParticle);
1562 targetFlag = manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->
function(iParticle);
1564 if (targetFlag != -2) particlesHaveMCAssociated =
true;
1565 if (targetFlag == 1) {
1570 if (!particlesHaveMCAssociated) output =
realNaN;
1571 if (nTargets > 0) output = 1;
1580 Manager::FunctionPtr isTrueCategory(
const std::vector<std::string>& arguments)
1582 if (arguments.size() != 1) {
1583 B2FATAL(
"Wrong number of arguments (1 required) for meta function isTrueCategory");
1586 auto categoryName = arguments[0];
1587 auto func = [categoryName](
const Particle*) ->
double {
1588 if (!(categoryName ==
"Electron" || categoryName ==
"IntermediateElectron" || categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton" || categoryName ==
"Kaon"
1589 || categoryName ==
"SlowPion" || categoryName ==
"FastHadron" || categoryName ==
"KaonPion" || categoryName ==
"Lambda" || categoryName ==
"MaximumPstar" || categoryName ==
"FSC"))
1591 B2FATAL(
"isTrueCategory: Not available category" << categoryName <<
1592 ". The possibilities for the category name are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1597 std::string trackTargetName = categoryName;
1599 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron")
particleListName =
"e+:inRoe";
1600 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton")
particleListName =
"mu+:inRoe";
1601 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {
particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
1605 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
1607 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1608 if (!ListOfParticles.isValid())
return realNaN;
1610 std::vector<Particle*> targetParticles;
1611 std::vector<Particle*> targetParticlesCategory;
1612 Variable::Manager& manager = Variable::Manager::Instance();
1617 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1619 Particle* iParticle = ListOfParticles->getParticle(i);
1620 if (!iParticle)
continue;
1622 double targetFlag = 0;
1623 if (categoryName ==
"MaximumPstar") {
1624 targetFlag = manager.getVariable(
"hasHighestProbInCat(pi+:inRoe, isRightTrack(MaximumPstar))")->
function(iParticle);
1626 targetFlag = manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->
function(iParticle);
1628 if (targetFlag == 1) {
1629 targetParticles.push_back(iParticle);
1633 for (
const auto& targetParticle : targetParticles)
1635 double isTargetOfRightCategory = manager.getVariable(
"isRightCategory(" + categoryName +
")")->
function(targetParticle);
1636 if (isTargetOfRightCategory == 1) {
1638 nTargets += 1; targetParticlesCategory.push_back(targetParticle);
1639 }
else if (isTargetOfRightCategory == -2 && output != 1)
1663 Manager::FunctionPtr qrOutput(
const std::vector<std::string>& arguments)
1665 if (arguments.size() != 1)
1666 B2FATAL(
"Wrong number of arguments for meta function qrOutput");
1668 std::string combinerMethod = arguments[0];
1669 auto func = [combinerMethod](
const Particle * particle) ->
double {
1672 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
1674 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1675 output = flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined();
1682 Manager::FunctionPtr qOutput(
const std::vector<std::string>& arguments)
1684 if (arguments.size() != 1)
1685 B2FATAL(
"Wrong number of arguments for meta function qOutput");
1687 std::string combinerMethod = arguments[0];
1688 auto func = [combinerMethod](
const Particle * particle) ->
double {
1691 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
1693 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1694 output = TMath::Sign(1, flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
1701 Manager::FunctionPtr rBinBelle(
const std::vector<std::string>& arguments)
1703 if (arguments.size() != 1)
1704 B2FATAL(
"Wrong number of arguments for meta function rBinBelle");
1707 std::string combinerMethod = arguments[0];
1708 auto func = [combinerMethod](
const Particle * particle) ->
double {
1710 int output = std::numeric_limits<int>::quiet_NaN();
1711 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
1713 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1715 double r = std::abs(flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
1716 if (r < 0.1) output = 0;
1717 if (r > 0.1 && r < 0.25) output = 1;
1718 if (r > 0.25 && r < 0.5) output = 2;
1719 if (r > 0.5 && r < 0.625) output = 3;
1720 if (r > 0.625 && r < 0.75) output = 4;
1721 if (r > 0.75 && r < 0.875) output = 5;
1722 if (r > 0.875 && r < 1.10) output = 6;
1730 Manager::FunctionPtr qpCategory(
const std::vector<std::string>& arguments)
1732 if (arguments.size() != 1)
1733 B2FATAL(
"Wrong number of arguments for meta function qpCategory");
1735 std::string categoryName = arguments[0];
1736 auto func = [categoryName](
const Particle * particle) ->
double {
1739 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
1741 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1743 std::map<std::string, float> iQpCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getQpCategory();
1744 if (iQpCategories.find(categoryName) != iQpCategories.end()) output = iQpCategories.at(categoryName);
1745 else if (iQpCategories.size() != 0) B2FATAL(
"qpCategory: Category with name " << categoryName
1746 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
1753 Manager::FunctionPtr isTrueFTCategory(
const std::vector<std::string>& arguments)
1755 if (arguments.size() != 1)
1756 B2FATAL(
"Wrong number of arguments for meta function isTrueFTCategory");
1758 std::string categoryName = arguments[0];
1759 auto func = [categoryName](
const Particle * particle) ->
double {
1762 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
1764 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1766 std::map<std::string, float> iIsTrueCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getIsTrueCategory();
1767 if (iIsTrueCategories.find(categoryName) != iIsTrueCategories.end()) output = iIsTrueCategories.at(categoryName);
1768 else if (iIsTrueCategories.size() != 0) B2FATAL(
"isTrueFTCategory: Category with name " << categoryName
1769 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
1777 Manager::FunctionPtr hasTrueTargets(
const std::vector<std::string>& arguments)
1779 if (arguments.size() != 1)
1780 B2FATAL(
"Wrong number of arguments for meta function hasTrueTargets");
1782 std::string categoryName = arguments[0];
1783 auto func = [categoryName](
const Particle * particle) ->
double {
1786 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
1788 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1790 std::map<std::string, float> iHasTrueTargets = flavorTaggerInfo->getMethodMap(
"FBDT")->getHasTrueTarget();
1791 if (iHasTrueTargets.find(categoryName) != iHasTrueTargets.end()) output = iHasTrueTargets.at(categoryName);
1792 else if (iHasTrueTargets.size() != 0) B2FATAL(
"hasTrueTargets: Category with name " << categoryName
1793 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
1801 VARIABLE_GROUP(
"Flavor Tagger Expert Variables");
1803 REGISTER_VARIABLE(
"pMissTag", momentumMissingTagSide,
1804 "[Expert] Calculates the missing momentum for a given particle on the tag side.");
1805 REGISTER_VARIABLE(
"cosTPTO" , cosTPTO ,
1806 "[Expert] Returns cosine of angle between thrust axis of given particle and thrust axis of ROE.");
1807 REGISTER_VARIABLE(
"lambdaFlavor", lambdaFlavor,
1808 "[Expert] Returns 1.0 if particle is ``Lambda0``, -1.0 in case of ``anti-Lambda0``, 0.0 otherwise.");
1809 REGISTER_VARIABLE(
"isLambda", isLambda,
"[Expert] Returns 1.0 if particle is truth-matched to ``Lambda0``, 0.0 otherwise.");
1810 REGISTER_VARIABLE(
"lambdaZError", lambdaZError,
"[Expert] Returns the variance of the z-component of the decay vertex.");
1811 REGISTER_VARIABLE(
"momentumOfSecondDaughter", momentumOfSecondDaughter,
1812 "[Expert] Returns the momentum of second daughter if exists, 0. otherwise.");
1813 REGISTER_VARIABLE(
"momentumOfSecondDaughterCMS", momentumOfSecondDaughterCMS,
1814 "[Expert] Returns the momentum of the second daughter in the centre-of-mass system, 0. if this daughter doesn't exist.");
1815 REGISTER_VARIABLE(
"chargeTimesKaonLiklihood", chargeTimesKaonLiklihood,
1816 "[Expert] Returns ``q*(highest PID_Likelihood for Kaons)``, 0. otherwise.");
1817 REGISTER_VARIABLE(
"ptTracksRoe", transverseMomentumOfChargeTracksInRoe,
1818 "[Expert] Returns the transverse momentum of all charged tracks of the ROE related to the given particle, 0.0 if particle has no related ROE.");
1819 REGISTER_VARIABLE(
"NumberOfKShortsInRoe", NumberOfKShortsInRoe,
1820 "[Expert] Returns the number of ``K_S0`` in the rest of event. The particle list ``K_S0:inRoe`` has to be filled beforehand.");
1822 REGISTER_VARIABLE(
"isInElectronOrMuonCat", isInElectronOrMuonCat,
1823 "[Expert] Returns 1.0 if the particle has been selected as target in the Muon or Electron Category, 0.0 otherwise.");
1825 REGISTER_VARIABLE(
"isMajorityInRestOfEventFromB0", isMajorityInRestOfEventFromB0,
1826 "[Eventbased][Expert] Checks if the majority of the tracks in the current RestOfEvent are from a ``B0``.");
1827 REGISTER_VARIABLE(
"isMajorityInRestOfEventFromB0bar", isMajorityInRestOfEventFromB0bar,
1828 "[Eventbased][Expert] Check if the majority of the tracks in the current RestOfEvent are from a ``anti-B0``.");
1829 REGISTER_VARIABLE(
"hasRestOfEventTracks", hasRestOfEventTracks,
1830 "[Expert] Returns the amount of tracks in the RestOfEvent related to the given Particle. -2 if the RestOfEvent is empty.");
1832 REGISTER_VARIABLE(
"qrCombined", isRestOfEventB0Flavor, R
"DOC(
1833 [Eventbased][Expert] Returns -1 (1) if current RestOfEvent is related to a ``anti-B0`` (``B0``).
1834 The ``MCError`` bit of Breco has to be 0, 1, 2, 16 or 1024.
1835 The output of the variable is 0 otherwise.
1836 If one particle in the RestOfEvent is found to belong to the reconstructed ``B0``, the output is -2(2) for a ``anti-B0`` (``B0``) on the reconstructed side.");
1838 REGISTER_VARIABLE("ancestorHasWhichFlavor", ancestorHasWhichFlavor,
1839 "[Expert] Checks the decay chain of the given particle upwards up to the ``Upsilon(4S)`` resonance and outputs 0 (1) if an ancestor is found to be a ``anti-B0`` (``B0``), if not -2.");
1840 REGISTER_VARIABLE(
"B0mcErrors", B0mcErrors,
"[Expert] Returns MC-matching flag, see :b2:var:`mcErrors` for the particle, e.g. ``B0`` .");
1841 REGISTER_VARIABLE(
"isRelatedRestOfEventMajorityB0Flavor", isRelatedRestOfEventMajorityB0Flavor,
1842 "[Expert] Returns 0 (1) if the majority of tracks and clusters of the RestOfEvent related to the given Particle are related to a ``anti-B0`` (``B0``).");
1843 REGISTER_VARIABLE(
"isRestOfEventMajorityB0Flavor", isRestOfEventMajorityB0Flavor,
1844 "[Expert] Returns 0 (1) if the majority of tracks and clusters of the current RestOfEvent are related to a ``anti-B0`` (``B0``).");
1845 REGISTER_VARIABLE(
"mcFlavorOfOtherB", mcFlavorOfOtherB, R
"DOC(
1846 [Expert] Returns the MC flavor (+1 or -1) of the accompanying tag-side B meson if the given particle is a correctly truth-matched B candidate, 0 otherwise.
1847 In other words, this variable checks the generated flavor of the other generated ``Upsilon(4S)`` daughter.");
1851 REGISTER_VARIABLE("BtagToWBosonVariables(requestedVariable)", BtagToWBosonVariables, R
"DOC(
1852 [Eventbased][Expert] Returns values of FlavorTagging-specific kinematical variables assuming a semileptonic decay with the given particle as target.
1853 The input values of ``requestedVariable`` can be the following: recoilMass, pMissCMS, cosThetaMissCMS and EW90.
1855 REGISTER_VARIABLE("KaonPionVariables(requestedVariable)" , KaonPionVariables , R
"DOC(
1856 [Expert] Returns values of FlavorTagging-specific kinematical variables for ``KaonPion`` category.
1857 The input values of ``requestedVariable`` can be the following: cosKaonPion, HaveOpositeCharges.
1859 REGISTER_VARIABLE("FSCVariables(requestedVariable)", FSCVariables, R
"DOC(
1860 [Eventbased][Expert] Returns values of FlavorTagging-specific kinematical variables for ``FastSlowCorrelated`` category.
1861 The input values of ``requestedVariable`` can be the following: pFastCMS, cosSlowFast, SlowFastHaveOpositeCharges, or cosTPTOFast.
1863 REGISTER_VARIABLE("hasHighestProbInCat(particleListName, extraInfoName)", hasHighestProbInCat, R
"DOC(
1864 [Expert] Returns 1.0 if the given Particle is classified as target track, i.e. if it has the highest target track probability in particleListName.
1865 The probability is accessed via ``extraInfoName``, which can have the following input values:
1867 * isRightTrack(Electron),
1868 * isRightTrack(IntermediateElectron),
1869 * isRightTrack(Muon),
1870 * isRightTrack(IntermediateMuon),
1871 * isRightTrack(KinLepton),
1872 * isRightTrack(IntermediateKinLepton),
1873 * isRightTrack(Kaon),
1874 * isRightTrack(SlowPion),
1875 * isRightTrack(FastHadron),
1876 * isRightTrack(MaximumPstar),
1877 * isRightTrack(Lambda),
1878 * isRightCategory(Electron),
1879 * isRightCategory(IntermediateElectron),
1880 * isRightCategory(Muon),
1881 * isRightCategory(IntermediateMuon),
1882 * isRightCategory(KinLepton),
1883 * isRightCategory(IntermediateKinLepton),
1884 * isRightCategory(Kaon),
1885 * isRightCategory(SlowPion),
1886 * isRightCategory(FastHadron),
1887 * isRightCategory(MaximumPstar),
1888 * isRightCategory(Lambda),
1889 * isRightCategory(KaonPion),
1890 * isRightCategory(FSC).
1893 REGISTER_VARIABLE("HighestProbInCat(particleListName, extraInfoName)", HighestProbInCat,
1894 "[Expert] Returns the highest target track probability value for the given category, for allowed input values for ``extraInfoName`` see :b2:var:`hasHighestProbInCat`.");
1896 REGISTER_VARIABLE(
"isRightTrack(particleName)", isRightTrack, R
"DOC(
1897 [Expert] Returns 1.0 if the given particle was really from a B-meson depending on category provided in ``particleName`` argument, 0.0 otherwise.
1898 Allowed input values for ``particleName`` argument in this variable are the following:
1901 * IntermediateElectron,
1905 * IntermediateKinLepton,
1913 REGISTER_VARIABLE("isRightCategory(particleName)", isRightCategory, R
"DOC(
1914 [Expert] Returns 1.0 if the class track by ``particleName`` category has the same flavor as the MC target track, 0.0 otherwise.
1915 Allowed input values for ``particleName`` argument in this variable are the following:
1918 * IntermediateElectron,
1922 * IntermediateKinLepton
1933 REGISTER_VARIABLE("QpOf(particleListName, outputExtraInfo, rankingExtraInfo)", QpOf, R
"DOC(
1934 [Eventbased][Expert] Returns the :math:`q*p` value for a given particle list provided as the 1st argument,
1935 where math:`p` is the probability of a category stored as extraInfo, provided as the 2nd argument,
1936 allowed values are same as in :b2:var:`hasHighestProbInCat`.
1937 The particle is selected after ranking according to a flavor tagging extraInfo, provided as the 3rd argument,
1938 allowed values are same as in :b2:var:`hasHighestProbInCat`.
1940 REGISTER_VARIABLE("weightedQpOf(particleListName, outputExtraInfo, rankingExtraInfo)", weightedQpOf, R
"DOC(
1941 [Eventbased][Expert] Returns the weighted :math:`q*p` value for a given particle list, provided as the 1st argument,
1942 where math:`p` is the probability of a category stored as extraInfo, provided in the 2nd argument,
1943 allowed values are same as in :b2:var:`hasHighestProbInCat`.
1944 The particles in the list are ranked according to a flavor tagging extraInfo, provided as the 3rd argument,
1945 allowed values are same as in :b2:var:`hasHighestProbInCat`.
1946 The values for the three top particles is combined into an effective (weighted) output.
1948 REGISTER_VARIABLE("variableOfTarget(particleListName, inputVariable, rankingExtraInfo)", variableOfTarget, R
"DOC(
1949 [Eventbased][Expert] Returns the value of an input variable provided as the 2nd argument for a particle selected from the given list provided as the 1st argument.
1950 The particles are ranked according to a flavor tagging extraInfo, provided as the 2nd argument,
1951 allowed values are same as in :b2:var:`hasHighestProbInCat`.
1954 REGISTER_VARIABLE("hasTrueTarget(categoryName)", hasTrueTarget,
1955 "[Expert] Returns 1 if the given category has a target, 0 otherwise.");
1956 REGISTER_VARIABLE(
"isTrueCategory(categoryName)", isTrueCategory,
1957 "[Expert] Returns 1 if the given category tags the B0 MC flavor correctly, 0 otherwise.");
1959 REGISTER_VARIABLE(
"qpCategory(categoryName)", qpCategory, R
"DOC(
1960 [Expert] Returns the output :math:`q` (charge of target track) times :math:`p` (probability that this is the right category) of the category with the given name.
1961 The allowed categories are the official Flavor Tagger Category Names.
1963 REGISTER_VARIABLE("isTrueFTCategory(categoryName)", isTrueFTCategory, R
"DOC(
1964 [Expert] Returns 1 if the target particle (checking the decay chain) of the category with the given name is found in the MC particles,
1965 and if it provides the right flavor. The allowed categories are the official Flavor Tagger Category Names.
1967 REGISTER_VARIABLE("hasTrueTargets(categoryName)", hasTrueTargets, R
"DOC(
1968 [Expert] Returns 1 if target particles (checking only the decay chain) of the category with the given name is found in the MC particles.
1969 The allowed categories are the official Flavor Tagger Category Names.
1972 VARIABLE_GROUP("Flavor Tagger Analysis Variables")
1974 REGISTER_VARIABLE("rBinBelle(combinerMethod)", rBinBelle, R"DOC(
1975 Returns the corresponding :math:`r` (dilution) bin according to the Belle binning for the given ``combinerMethod``.
1976 The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
1977 The return values and the corresponding dilution ranges are the following:
1979 * 0: :math:`0.000 < r < 0.100`;
1980 * 1: :math:`0.100 < r < 0.250`;
1981 * 2: :math:`0.250 < r < 0.500`;
1982 * 3: :math:`0.500 < r < 0.625`;
1983 * 4: :math:`0.625 < r < 0.750`;
1984 * 5: :math:`0.750 < r < 0.875`;
1985 * 6: :math:`0.875 < r < 1.000`.
1987 .. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
1988 .. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
1990 REGISTER_VARIABLE("qrOutput(combinerMethod)", qrOutput, R"DOC(
1991 Returns the output of the flavorTagger, flavor tag :math:`q` times the dilution factor :math:`r`, for the given combiner method.
1992 The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
1994 .. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
1995 .. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
1997 REGISTER_VARIABLE("qOutput(combinerMethod)", qOutput, R"DOC(
1998 Returns the flavor tag :math:`q` output of the flavorTagger for the given combinerMethod.
1999 The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2001 .. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2002 .. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2004 REGISTER_VARIABLE("isRelatedRestOfEventB0Flavor", isRelatedRestOfEventB0Flavor, R"DOC(
2005 Returns -1 (1) if the RestOfEvent related to the given particle is related to a ``anti-B0`` (``B0``).
2006 The ``MCError`` bit of Breco has to be 0, 1, 2, 16 or 1024.
2007 The output of the variable is 0 otherwise.
2008 If one particle in the RestOfEvent is found to belong to the reconstructed ``B0``, the output is -2(2) for a ``anti-B0`` (``B0``) on the reconstructed side.
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
static const double realNaN
shortcut for NaN of double type
MCParticle * getMother() const
Returns a pointer to the mother particle.
std::string particleName(int pdgCode)
Returns the name of a particle with given pdg code.
std::string particleListName(int pdgCode, const std::string &label)
Returns the name of the particle ParticleList for particles with given pdg code and with given label.
Abstract base class for different kinds of events.