12 #include <analysis/variables/FlavorTaggingVariables.h>
13 #include <analysis/variables/MCTruthVariables.h>
14 #include <analysis/utility/PCmsLabTransform.h>
16 #include <analysis/ClusterUtility/ClusterUtils.h>
18 #include <analysis/utility/MCMatching.h>
21 #include <framework/datastore/StoreObjPtr.h>
24 #include <analysis/dataobjects/Particle.h>
25 #include <analysis/dataobjects/RestOfEvent.h>
26 #include <analysis/dataobjects/ParticleList.h>
27 #include <analysis/dataobjects/FlavorTaggerInfo.h>
28 #include <analysis/ContinuumSuppression/Thrust.h>
30 #include <mdst/dataobjects/MCParticle.h>
31 #include <mdst/dataobjects/Track.h>
32 #include <mdst/dataobjects/ECLCluster.h>
33 #include <mdst/dataobjects/KLMCluster.h>
34 #include <mdst/dataobjects/PIDLikelihood.h>
38 #include <framework/gearbox/Const.h>
39 #include <framework/logging/Logger.h>
41 #include <TLorentzVector.h>
61 double momentumMissingTagSide(
const Particle*)
63 TLorentzVector trackiCMSVec;
64 TLorentzVector roeCMSVec;
65 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
67 const auto& tracks = roe->getTracks();
68 for (
auto track : tracks) {
69 const PIDLikelihood* trackiPidLikelihood = track->getRelated<PIDLikelihood>();
70 const Const::ChargedStable trackiChargedStable = trackiPidLikelihood ? trackiPidLikelihood->getMostLikely() : Const::pion;
71 double trackiMassHypothesis = trackiChargedStable.getMass();
72 const TrackFitResult* tracki = track->getTrackFitResultWithClosestMass(trackiChargedStable);
73 if (tracki ==
nullptr)
continue;
74 double energy = sqrt(trackiMassHypothesis * trackiMassHypothesis + (tracki->getMomentum()).Dot(tracki->getMomentum()));
75 TLorentzVector trackiVec(tracki->getMomentum(), energy);
76 trackiCMSVec = PCmsLabTransform::labToCms(trackiVec);
77 roeCMSVec += trackiCMSVec;
80 double missMom = -roeCMSVec.P();
84 double cosTPTO(
const Particle* part)
86 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
88 std::vector<TVector3> p3_cms_roe;
90 static const double P_MAX(3.2);
104 const auto& roeTracks = roe->getTracks();
105 for (
auto& track : roeTracks) {
106 if (track ==
nullptr)
continue;
110 const PIDLikelihood* iPidLikelihood = track->getRelated<PIDLikelihood>();
111 const Const::ChargedStable charged = iPidLikelihood ? iPidLikelihood->getMostLikely() : Const::pion;
113 if (track->getTrackFitResultWithClosestMass(charged)->getChargeSign() == 0)
continue;
114 Particle particle(track, charged);
115 if (particle.getParticleSource() == Particle::c_Track) {
116 TLorentzVector p_cms = T.rotateLabToCms() * particle.get4Vector();
117 if (p_cms != p_cms)
continue;
118 if (p_cms.Rho() > P_MAX)
continue;
119 p3_cms_roe.push_back(p_cms.Vect());
124 const auto& roeECLClusters = roe->getECLClusters();
125 for (
auto& cluster : roeECLClusters) {
126 if (cluster ==
nullptr)
continue;
127 if (not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
continue;
128 if (cluster->isNeutral()) {
130 Particle particle(cluster);
131 TLorentzVector p_lab = particle.get4Vector();
132 if (p_lab != p_lab)
continue;
133 if (p_lab.Rho() < 0.05)
continue;
134 TLorentzVector p_cms = T.rotateLabToCms() * p_lab;
135 if (p_cms != p_cms)
continue;
136 if (p_cms.Rho() > P_MAX)
continue;
137 p3_cms_roe.push_back(p_cms.Vect());
141 const auto& roeKLMClusters = roe->getKLMClusters();
142 for (
auto& cluster : roeKLMClusters) {
143 if (cluster ==
nullptr)
continue;
144 if (!(cluster -> getAssociatedTrackFlag()) && !(cluster -> getAssociatedEclClusterFlag())) {
146 Particle particle(cluster);
147 TLorentzVector p_lab = particle.get4Vector();
148 if (p_lab != p_lab)
continue;
149 if (p_lab.Rho() < 0.05)
continue;
150 TLorentzVector p_cms = T.rotateLabToCms() * p_lab;
151 if (p_cms != p_cms)
continue;
152 if (p_cms.Rho() > P_MAX)
continue;
153 p3_cms_roe.push_back(p_cms.Vect());
157 thrustO = Thrust::calculateThrust(p3_cms_roe);
158 const TVector3 pAxis = PCmsLabTransform::labToCms(part->get4Vector()).Vect();
159 if (pAxis == pAxis) result = fabs(cos(pAxis.Angle(thrustO)));
165 double lambdaFlavor(
const Particle* particle)
167 if (particle->getPDGCode() == 3122)
return 1.0;
168 else if (particle->getPDGCode() == -3122)
return -1.0;
172 double isLambda(
const Particle* particle)
174 const MCParticle* mcparticle = particle->getRelatedTo<MCParticle>();
177 if (mcparticle !=
nullptr) {
178 if (mcparticle->getPDG() == 3122)
return 1.0;
179 else if (mcparticle->getPDG() == -3122)
return 1.0;
184 double lambdaZError(
const Particle* particle)
188 TMatrixFSym ErrorPositionMatrix = particle->getVertexErrorMatrix();
189 double zError = ErrorPositionMatrix[2][2];
193 double momentumOfSecondDaughter(
const Particle* part)
195 if (part->getDaughter(1) ==
nullptr)
return 0.0;
197 return part->getDaughter(1)->getP();
201 double momentumOfSecondDaughterCMS(
const Particle* part)
203 if (part->getDaughter(1) ==
nullptr)
return 0.0;
206 TLorentzVector vec = T.rotateLabToCms() * part->getDaughter(1)->get4Vector();
211 double chargeTimesKaonLiklihood(
const Particle*)
213 double maximumKaonid = 0;
214 double maximum_charge = 0;
215 StoreObjPtr<ParticleList> KaonList(
"K+:inRoe");
216 if (KaonList.isValid()) {
217 for (
unsigned int i = 0; i < KaonList->getListSize(); ++i) {
218 Particle* p = KaonList->getParticle(i);
219 double Kid = p->getRelatedTo<PIDLikelihood>()->getProbability(Const::kaon, Const::pion);
220 if (Kid > maximumKaonid) {
222 maximum_charge = p->getCharge();
226 return maximumKaonid * maximum_charge;
229 double transverseMomentumOfChargeTracksInRoe(
const Particle* part)
231 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
236 for (
const auto& track : roe->getTracks()) {
237 if (part->getTrack() == track)
continue;
238 if (track ==
nullptr)
continue;
239 const PIDLikelihood* iPidLikelihood = track->getRelated<PIDLikelihood>();
240 const Const::ChargedStable charged = iPidLikelihood ? iPidLikelihood->getMostLikely() : Const::pion;
244 if (track->getTrackFitResultWithClosestMass(charged) ==
nullptr)
continue;
245 double pt = track->getTrackFitResultWithClosestMass(charged)->getTransverseMomentum();
246 if (pt == pt) sum += sqrt(pt * pt);
253 double NumberOfKShortsInRoe(
const Particle* particle)
256 StoreObjPtr<ParticleList> KShortList(
"K_S0:inRoe");
257 if (KShortList.isValid()) {
258 for (
unsigned int i = 0; i < KShortList->getListSize(); i++) {
259 if (particle->overlapsWith(KShortList->getParticle(i))) {
continue;}
262 }
else B2FATAL(
"NumberOfKShortsInRoe cannot be calculated because the required particleList K_S0:inRoe could not be found or is not valid");
268 double isInElectronOrMuonCat(
const Particle* particle)
271 StoreObjPtr<ParticleList> MuonList(
"mu+:inRoe");
272 StoreObjPtr<ParticleList> ElectronList(
"e+:inRoe");
274 const Track* trackTargetMuon =
nullptr;
275 const Track* trackTargetElectron =
nullptr;
277 if (MuonList.isValid()) {
278 double maximumProbMuon = 0;
279 for (
unsigned int i = 0; i < MuonList->getListSize(); ++i) {
280 Particle* pMuon = MuonList->getParticle(i);
281 double probMuon = pMuon->getExtraInfo(
"isRightTrack(Muon)");
282 if (probMuon > maximumProbMuon) {
283 maximumProbMuon = probMuon;
284 trackTargetMuon = pMuon -> getTrack();
288 if (ElectronList.isValid()) {
289 double maximumProbElectron = 0;
290 for (
unsigned int i = 0; i < ElectronList->getListSize(); ++i) {
291 Particle* pElectron = ElectronList->getParticle(i);
292 double probElectron = pElectron->getExtraInfo(
"isRightTrack(Electron)");
293 if (probElectron > maximumProbElectron) {
294 maximumProbElectron = probElectron;
295 trackTargetElectron = pElectron -> getTrack();
299 if (particle->getTrack() == trackTargetMuon || particle->getTrack() == trackTargetElectron) {
306 double isMajorityInRestOfEventFromB0(
const Particle*)
309 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
311 for (
auto& track : roe->getTracks()) {
312 const MCParticle* mcParticle = track->getRelated<MCParticle>();
313 while (mcParticle !=
nullptr) {
314 if (mcParticle->getPDG() == 511) {
318 if (mcParticle->getPDG() == -511) {
322 mcParticle = mcParticle->getMother();
329 double isMajorityInRestOfEventFromB0bar(
const Particle*)
332 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
334 for (
auto& track : roe->getTracks()) {
335 const MCParticle* mcParticle = track->getRelated<MCParticle>();
336 while (mcParticle !=
nullptr) {
337 if (mcParticle->getPDG() == 511) {
340 if (mcParticle->getPDG() == -511) {
343 mcParticle = mcParticle->getMother();
350 double hasRestOfEventTracks(
const Particle* part)
352 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
353 float ObjectsInROE = 0;
354 if (roe !=
nullptr) {
355 if (roe-> getNTracks() != 0) {
363 if (ObjectsInROE > 0) {
368 double isRelatedRestOfEventB0Flavor(
const Particle* particle)
370 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
372 float BtagFlavor = 0;
375 if (roe !=
nullptr) {
376 const MCParticle* BcpMC = particle->getRelatedTo<MCParticle>();
378 if (Variable::isSignal(particle) > 0 && BcpMC !=
nullptr) {
379 const MCParticle* Y4S = BcpMC->getMother();
380 if (Y4S !=
nullptr) {
381 for (
auto& iTrack : roe->getTracks()) {
382 const MCParticle* mcParticle = iTrack->
getRelated<MCParticle>();
383 while (mcParticle !=
nullptr) {
384 if (mcParticle->getMother() == Y4S) {
385 if (mcParticle == BcpMC) {
386 if (mcParticle -> getPDG() > 0) BcpFlavor = 2;
388 }
else if (BtagFlavor == 0) {
389 if (TMath::Abs(mcParticle -> getPDG()) == 511 || TMath::Abs(mcParticle -> getPDG()) == 521) {
390 if (mcParticle -> getPDG() > 0) BtagFlavor = 1;
391 else BtagFlavor = -1;
392 }
else BtagFlavor = 5;
396 mcParticle = mcParticle->getMother();
398 if (BcpFlavor != 0 || BtagFlavor == 5)
break;
403 return (BcpFlavor != 0) ? BcpFlavor : BtagFlavor;
406 double isRestOfEventB0Flavor(
const Particle*)
408 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
411 const Particle* Bcp = roe->getRelated<Particle>();
412 return Variable::isRelatedRestOfEventB0Flavor(Bcp);
417 double ancestorHasWhichFlavor(
const Particle* particle)
419 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
421 float outputB0tagQ = 0;
423 const MCParticle* BcpMC = roe->
getRelated<Particle>()->getRelatedTo<MCParticle>();
424 const MCParticle* Y4S = BcpMC->getMother();
425 const MCParticle* mcParticle = particle->getRelatedTo<MCParticle>();
426 while (mcParticle !=
nullptr) {
427 if (mcParticle->getMother() == Y4S) {
428 if (mcParticle != BcpMC && TMath::Abs(mcParticle -> getPDG()) == 511) {
429 if (mcParticle -> getPDG() == 511) outputB0tagQ = 1;
430 else outputB0tagQ = -1;
431 }
else if (mcParticle == BcpMC) {
432 if (mcParticle -> getPDG() == 511) outputB0tagQ = 2;
433 else outputB0tagQ = -2;
434 }
else outputB0tagQ = 5;
437 mcParticle = mcParticle->getMother();
444 double B0mcErrors(
const Particle* particle)
446 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
448 int MCMatchingError = -1;
450 const Particle* Bcp = roe->getRelated<Particle>();
451 const MCParticle* BcpMC = roe->
getRelated<Particle>()->getRelatedTo<MCParticle>();
453 MCMatchingError = MCMatching::getMCErrors(Bcp, BcpMC);
455 return MCMatchingError;
458 double isRelatedRestOfEventMajorityB0Flavor(
const Particle* part)
460 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
462 float outputStandard = 0.0;
465 if (roe !=
nullptr) {
466 if (roe-> getNTracks() != 0) {
467 for (
auto& track : roe->getTracks()) {
468 const MCParticle* mcParticle = track->getRelated<MCParticle>();
469 while (mcParticle !=
nullptr) {
470 if (mcParticle->getPDG() == 511) {
474 if (mcParticle->getPDG() == -511) {
478 mcParticle = mcParticle->getMother();
481 }
else if (roe-> getNECLClusters() != 0) {
482 for (
auto& cluster : roe-> getECLClusters()) {
483 if (not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
continue;
484 const MCParticle* mcParticle = cluster->getRelated<MCParticle>();
485 while (mcParticle !=
nullptr) {
486 if (mcParticle->getPDG() == 511) {
490 if (mcParticle->getPDG() == -511) {
494 mcParticle = mcParticle->getMother();
497 }
else if (roe-> getNKLMClusters() != 0) {
498 for (
auto& klmcluster : roe-> getKLMClusters()) {
499 const MCParticle* mcParticle = klmcluster->
getRelated<MCParticle>();
500 while (mcParticle !=
nullptr) {
501 if (mcParticle->getPDG() == 511) {
505 if (mcParticle->getPDG() == -511) {
509 mcParticle = mcParticle->getMother();
517 }
else if (q_MC < 0) {
519 }
else outputStandard = -2;
521 return outputStandard;
524 double isRestOfEventMajorityB0Flavor(
const Particle*)
526 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
529 const Particle* Bcp = roe->getRelated<Particle>();
530 return Variable::isRelatedRestOfEventMajorityB0Flavor(Bcp);
534 double mcFlavorOfOtherB(
const Particle* particle)
537 if (std::abs(particle->getPDGCode()) != 511 && std::abs(particle->getPDGCode()) != 521) {
538 B2ERROR(
"MCFlavorOfOtherB: this variable works only for B mesons.\n"
539 "The given particle with PDG code " << particle->getPDGCode() <<
540 " is not a B-meson candidate (PDG code 511 or 521). ");
541 return std::numeric_limits<double>::quiet_NaN();
544 const MCParticle* mcParticle = particle->getRelatedTo<MCParticle>();
546 if (mcParticle ==
nullptr)
return std::numeric_limits<double>::quiet_NaN();
548 const MCParticle* mcMother = mcParticle->getMother();
550 if (mcMother ==
nullptr)
return std::numeric_limits<double>::quiet_NaN();
552 if (Variable::isSignal(particle) < 1.0)
return 0;
554 for (
auto& upsilon4SDaughter : mcMother -> getDaughters()) {
555 if (upsilon4SDaughter != mcParticle) {
556 if (upsilon4SDaughter -> getPDG() > 0)
return 1.0;
568 Manager::FunctionPtr CheckingVariables(
const std::vector<std::string>& arguments)
570 if (arguments.size() == 2) {
571 auto ListName = arguments[0];
572 auto requestedVariable = arguments[1];
573 auto func = [requestedVariable, ListName](
const Particle*) ->
double {
574 if (requestedVariable ==
"getListSize")
576 StoreObjPtr<ParticleList> ListOfParticles(ListName);
577 if (ListOfParticles.isValid())
return ListOfParticles->getListSize();
580 B2FATAL(
"Wrong requested Variable. Available is getListSize for particle lists");
585 B2FATAL(
"Wrong number of arguments (2 required) for meta function CheckingVariables");
589 Manager::FunctionPtr IsDaughterOf(
const std::vector<std::string>& arguments)
591 auto motherlist = arguments[0];
592 auto func = [motherlist](
const Particle * particle) ->
double {
594 StoreObjPtr<ParticleList> Y(motherlist);
595 std::vector<Particle*> daughters;
598 B2ERROR(
"Particle List with name " << motherlist <<
"isn't valid!");
600 for (
unsigned int i = 0; i < Y->getListSize(); ++i)
602 const auto& oParticle = Y->getParticle(i);
603 result = (double)particle->overlapsWith(oParticle);
615 Manager::FunctionPtr BtagToWBosonVariables(
const std::vector<std::string>& arguments)
617 if (arguments.size() == 1) {
618 auto requestedVariable = arguments[0];
619 auto func = [requestedVariable](
const Particle * particle) ->
double {
622 TLorentzVector momXChargedTracks;
623 TLorentzVector momXChargedClusters;
624 TLorentzVector momXNeutralClusters;
625 TLorentzVector momTarget = T.rotateLabToCms() * particle -> get4Vector();
629 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
632 const auto& tracks = roe->getTracks();
633 for (
auto& track : tracks) {
634 const PIDLikelihood* iPidLikelihood = track->getRelated<PIDLikelihood>();
635 const Const::ChargedStable charged = iPidLikelihood ? iPidLikelihood->getMostLikely() : Const::pion;
636 const TrackFitResult* iTrack = track->getTrackFitResultWithClosestMass(charged);
637 if (iTrack ==
nullptr)
continue;
638 if (track != particle->getTrack()) {
639 TLorentzVector iTrackMom = iTrack->get4Momentum();
640 if (iTrackMom == iTrackMom) momXChargedTracks += iTrackMom;
644 momXNeutralClusters = roe->get4VectorNeutralECLClusters();
646 const auto& klm = roe->getKLMClusters();
647 for (
auto& x : klm) {
648 if (x ==
nullptr)
continue;
649 TLorentzVector iMomKLMCluster = x -> getMomentum();
650 if (iMomKLMCluster == iMomKLMCluster) {
651 if (!(x -> getAssociatedTrackFlag()) && !(x -> getAssociatedEclClusterFlag())) {
652 momXNeutralClusters += iMomKLMCluster;
658 TLorentzVector momX = T.rotateLabToCms() * (momXChargedTracks +
659 momXNeutralClusters);
660 TLorentzVector momMiss = -(momX + momTarget);
662 if (requestedVariable ==
"recoilMass") output = momX.M();
663 else if (requestedVariable ==
"recoilMassSqrd") output = momX.M2();
664 else if (requestedVariable ==
"pMissCMS") output = momMiss.Vect().Mag();
665 else if (requestedVariable ==
"cosThetaMissCMS") output = TMath::Cos(momTarget.Angle(momMiss.Vect()));
666 else if (requestedVariable ==
"EW90") {
668 TLorentzVector momW = momTarget + momMiss;
671 const auto& ecl = roe->getECLClusters();
672 for (
auto& x : ecl) {
673 if (x ==
nullptr)
continue;
674 float iEnergy = x -> getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
675 if (x->isNeutral() && iEnergy == iEnergy) {
676 if ((T.rotateLabToCms() * C.Get4MomentumFromCluster(x,
677 ECLCluster::EHypothesisBit::c_nPhotons)).Vect().Dot(momW.Vect()) > 0) E_W_90 += iEnergy;
680 for (
auto& track : tracks) {
681 if (track != particle->getTrack()) {
682 for (
const ECLCluster& chargedCluster : track->getRelationsWith<ECLCluster>()) {
684 if (!chargedCluster.hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
686 float iEnergy = chargedCluster.getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
687 if (iEnergy == iEnergy) {
688 if ((T.rotateLabToCms() * C.Get4MomentumFromCluster(&chargedCluster,
689 ECLCluster::EHypothesisBit::c_nPhotons)).Vect().Dot(momW.Vect()) > 0) E_W_90 += iEnergy;
701 B2FATAL(
"Wrong variable " << requestedVariable <<
702 " requested. The possibilities are recoilMass, recoilMassSqrd, pMissCMS, cosThetaMissCMS or EW90");
709 B2FATAL(
"Wrong number of arguments (1 required) for meta function BtagToWBosonVariables");
713 Manager::FunctionPtr KaonPionVariables(
const std::vector<std::string>& arguments)
715 if (arguments.size() == 1) {
716 auto requestedVariable = arguments[0];
717 auto func = [requestedVariable](
const Particle * particle) ->
double {
719 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
722 TLorentzVector momTargetKaon = T.rotateLabToCms() * particle -> get4Vector();
723 TLorentzVector momTargetSlowPion;
725 float chargeTargetKaon = particle -> getCharge();
729 if ((requestedVariable ==
"HaveOpositeCharges") || (requestedVariable ==
"cosKaonPion"))
731 float chargeTargetSlowPion = 0;
732 if (SlowPionList.isValid()) {
733 double maximumProbSlowPion = 0;
734 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
735 Particle* pSlowPion = SlowPionList->getParticle(i);
736 if (pSlowPion !=
nullptr) {
737 if (pSlowPion -> hasExtraInfo(
"isRightCategory(SlowPion)")) {
738 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
739 if (probSlowPion > maximumProbSlowPion) {
740 maximumProbSlowPion = probSlowPion;
741 chargeTargetSlowPion = pSlowPion -> getCharge();
742 momTargetSlowPion = T.rotateLabToCms() * pSlowPion -> get4Vector();
748 if (requestedVariable ==
"HaveOpositeCharges") {
749 if (chargeTargetKaon * chargeTargetSlowPion == -1) output = 1;
751 if (requestedVariable ==
"cosKaonPion") {
752 if (momTargetKaon == momTargetKaon
753 && momTargetSlowPion == momTargetSlowPion) output = TMath::Cos(momTargetKaon.Angle(momTargetSlowPion.Vect()));
757 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are cosKaonPion or HaveOpositeCharges");
763 B2FATAL(
"Wrong number of arguments (1 required) for meta function KaonPionVariables");
767 Manager::FunctionPtr FSCVariables(
const std::vector<std::string>& arguments)
769 if (arguments.size() == 1) {
770 auto requestedVariable = arguments[0];
771 auto func = [requestedVariable](
const Particle * particle) ->
double {
772 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
774 TLorentzVector momSlowPion = T.rotateLabToCms() * particle -> get4Vector();
775 TLorentzVector momFastParticle;
779 if ((requestedVariable ==
"pFastCMS") || (requestedVariable ==
"cosSlowFast") || (requestedVariable ==
"cosTPTOFast") || (requestedVariable ==
"SlowFastHaveOpositeCharges"))
781 if (FastParticleList.isValid()) {
782 double maximumProbFastest = 0;
783 Particle* TargetFastParticle =
nullptr;
784 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i) {
785 Particle* particlei = FastParticleList->getParticle(i);
786 if (particlei !=
nullptr) {
787 TLorentzVector momParticlei = T.rotateLabToCms() * particlei -> get4Vector();
788 if (momParticlei == momParticlei) {
789 double probFastest = momParticlei.P();
790 if (probFastest > maximumProbFastest) {
791 maximumProbFastest = probFastest;
792 TargetFastParticle = particlei;
793 momFastParticle = momParticlei;
798 if (TargetFastParticle !=
nullptr) {
799 if (requestedVariable ==
"cosTPTOFast") output = Variable::Manager::Instance().getVariable(
"cosTPTO")->function(
801 if (momSlowPion == momSlowPion) {
802 if (requestedVariable ==
"cosSlowFast") output = TMath::Cos(momSlowPion.Angle(momFastParticle.Vect()));
803 else if (requestedVariable ==
"SlowFastHaveOpositeCharges") {
804 if (particle->getCharge()*TargetFastParticle->getCharge() == -1) {
807 }
else output = momFastParticle.P();
812 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are pFastCMS, cosSlowFast or cosTPTOFast");
818 B2FATAL(
"Wrong number of arguments (1 required) for meta function FSCVariables");
822 Manager::FunctionPtr hasHighestProbInCat(
const std::vector<std::string>& arguments)
824 if (arguments.size() == 2) {
826 auto extraInfoName = arguments[1];
827 auto func = [
particleListName, extraInfoName](
const Particle * particle) ->
double {
828 if (!(extraInfoName ==
"isRightTrack(Electron)" || extraInfoName ==
"isRightTrack(IntermediateElectron)" || extraInfoName ==
"isRightTrack(Muon)" || extraInfoName ==
"isRightTrack(IntermediateMuon)"
829 || extraInfoName ==
"isRightTrack(KinLepton)" || extraInfoName ==
"isRightTrack(IntermediateKinLepton)" || extraInfoName ==
"isRightTrack(Kaon)"
830 || extraInfoName ==
"isRightTrack(SlowPion)" || extraInfoName ==
"isRightTrack(FastHadron)" || extraInfoName ==
"isRightTrack(MaximumPstar)" || extraInfoName ==
"isRightTrack(Lambda)"
831 || extraInfoName ==
"isRightCategory(Electron)" || extraInfoName ==
"isRightCategory(IntermediateElectron)" || extraInfoName ==
"isRightCategory(Muon)" || extraInfoName ==
"isRightCategory(IntermediateMuon)"
832 || extraInfoName ==
"isRightCategory(KinLepton)" || extraInfoName ==
"isRightCategory(IntermediateKinLepton)" || extraInfoName ==
"isRightCategory(Kaon)"
833 || extraInfoName ==
"isRightCategory(SlowPion)" || extraInfoName ==
"isRightCategory(FastHadron)" || extraInfoName ==
"isRightCategory(KaonPion)" || extraInfoName ==
"isRightCategory(Lambda)"
834 || extraInfoName ==
"isRightCategory(MaximumPstar)" || extraInfoName ==
"isRightCategory(FSC)"))
836 B2FATAL(
"hasHighestProbInCat: Not available category" << extraInfoName <<
837 ". The possibilities for isRightTrack() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda."
839 "The possibilities for isRightCategory() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
843 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
848 if (ListOfParticles.isValid())
850 double maximumProb = 0;
851 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i) {
852 Particle* particlei = ListOfParticles->getParticle(i);
853 if (particlei !=
nullptr) {
855 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
856 TLorentzVector momParticlei = T.rotateLabToCms() * particlei -> get4Vector();
857 if (momParticlei == momParticlei) {
858 prob = momParticlei.P();
861 if (particlei->hasExtraInfo(extraInfoName)) {
862 prob = particlei->getExtraInfo(extraInfoName);
865 if (prob > maximumProb) {
870 if ((extraInfoName ==
"isRightTrack(MaximumPstar)" && (T.rotateLabToCms() * particle -> get4Vector()).P() == maximumProb)) {
872 }
else if (extraInfoName !=
"isRightTrack(MaximumPstar)" && particle -> hasExtraInfo(extraInfoName)) {
873 if (particle -> getExtraInfo(extraInfoName) == maximumProb) output = 1.0;
880 B2FATAL(
"Wrong number of arguments (2 required) for meta function hasHighestProbInCat");
884 Manager::FunctionPtr HighestProbInCat(
const std::vector<std::string>& arguments)
886 if (arguments.size() == 2) {
888 auto extraInfoName = arguments[1];
890 if (!(extraInfoName ==
"isRightTrack(Electron)" || extraInfoName ==
"isRightTrack(IntermediateElectron)" || extraInfoName ==
"isRightTrack(Muon)" || extraInfoName ==
"isRightTrack(IntermediateMuon)"
891 || extraInfoName ==
"isRightTrack(KinLepton)" || extraInfoName ==
"isRightTrack(IntermediateKinLepton)" || extraInfoName ==
"isRightTrack(Kaon)"
892 || extraInfoName ==
"isRightTrack(SlowPion)" || extraInfoName ==
"isRightTrack(FastHadron)" || extraInfoName ==
"isRightTrack(MaximumPstar)" || extraInfoName ==
"isRightTrack(Lambda)"
893 || extraInfoName ==
"isRightCategory(Electron)" || extraInfoName ==
"isRightCategory(IntermediateElectron" || extraInfoName ==
"isRightCategory(Muon)" || extraInfoName ==
"isRightCategory(IntermediateMuon)"
894 || extraInfoName ==
"isRightCategory(KinLepton)" || extraInfoName ==
"isRightCategory(IntermediateKinLepton)" || extraInfoName ==
"isRightCategory(Kaon)"
895 || extraInfoName ==
"isRightCategory(SlowPion)" || extraInfoName ==
"isRightCategory(FastHadron)" || extraInfoName ==
"isRightCategory(KaonPion)" || extraInfoName ==
"isRightCategory(Lambda)"
896 || extraInfoName ==
"isRightCategory(MaximumPstar)" || extraInfoName ==
"isRightCategory(FSC)"))
898 B2FATAL(
"HighestProbInCat: Not available category" << extraInfoName <<
899 ". The possibilities for isRightTrack() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda."
901 "The possibilities for isRightCategory() are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
905 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
907 double maximumProb = 0;
908 if (ListOfParticles.isValid())
910 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i) {
911 Particle* particlei = ListOfParticles->getParticle(i);
912 if (particlei !=
nullptr) {
914 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
915 TLorentzVector momParticlei = T.rotateLabToCms() * particlei -> get4Vector();
916 if (momParticlei == momParticlei) {
917 prob = momParticlei.P();
920 if (particlei->hasExtraInfo(extraInfoName)) {
921 prob = particlei->getExtraInfo(extraInfoName);
924 if (prob > maximumProb) {
934 B2FATAL(
"Wrong number of arguments (2 required) for meta function HighestProbInCat");
941 std::vector<int> charmMesons = { 411, 421, 10411, 10421, 413, 423, 10413, 10423, 20413, 20423, 415, 425, 431, 10431, 433, 10433, 20433, 435};
943 std::vector<int> charmBaryons = { 4122, 4222, 4212, 4112, 4224, 4214, 4114, 4232, 4132, 4322, 4312, 4324, 4314, 4332, 4334, 4412, 4422,
944 4414, 4424, 4432, 4434, 4444
947 std::vector<int> qqbarMesons = {
948 111, 9000111, 100111, 10111, 200111, 113, 10113, 20113, 9000113, 100113, 9010113, 9020113, 30113, 9030113, 9040113,
949 115, 10115, 100115, 9000115, 117, 9000117, 9010117, 119,
951 221, 331, 9000221, 9010221, 100221, 10221, 100331, 9020221, 10331, 200221, 9030221, 9040221, 9050221, 9060221, 9070221, 223, 333, 10223, 20223,
952 10333, 20333, 100223, 9000223, 9010223, 30223, 100333, 225, 9000225, 335, 9010225, 9020225, 10225, 9030225, 10335, 9040225, 100225, 100335,
953 9050225, 9060225, 9070225, 227, 337, 229, 9000339, 9000229,
955 441, 10441, 100441, 443, 10443, 20443, 100443, 30443, 9000443, 9010443, 9020443, 445, 9000445
958 std::vector<int> flavorConservingMesons = {
959 9000211, 100211, 10211, 200211, 213, 10213, 20213, 9000213, 100213, 9010213, 9020213, 30213, 9030213, 9040213,
960 215, 10215, 100215, 9000215, 217, 9000217, 9010217, 219,
962 30343, 10311, 10321, 100311, 100321, 200311, 200321, 9000311, 9000321, 313, 323, 10313, 10323, 20313, 20323, 100313, 100323,
963 9000313, 9000323, 30313, 30323, 315, 325, 9000315, 9000325, 10315, 10325, 20315, 20325, 100315, 100325, 9010315,
964 9010325, 317, 327, 9010317, 9010327, 319, 329, 9000319, 9000329
967 Manager::FunctionPtr isRightTrack(
const std::vector<std::string>& arguments)
969 if (arguments.size() == 1) {
973 std::vector<std::string> names = {
"Electron",
974 "IntermediateElectron",
978 "IntermediateKinLepton",
986 for (
unsigned i = 0; i < names.size(); ++i) {
987 if (particleName == names[i]) index = i;
991 B2FATAL(
"isRightTrack: Not available category " << particleName <<
992 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron and Lambda");
995 auto func = [index](
const Particle * particle) ->
double {
997 const MCParticle* mcParticle = particle->getRelated<MCParticle>();
998 if (mcParticle ==
nullptr)
return -2.0;
1000 int mcPDG = TMath::Abs(mcParticle->getPDG());
1003 std::vector<int> mothersPDG;
1004 std::vector<const MCParticle*> mothersPointers;
1006 const MCParticle* mcMother = mcParticle->getMother();
1007 while (mcMother !=
nullptr)
1009 mothersPDG.push_back(TMath::Abs(mcMother->getPDG()));
1010 if (index == 8) mothersPointers.push_back(mcMother);
1011 if (TMath::Abs(mcMother->getPDG()) == 511)
break;
1012 mcMother = mcMother -> getMother();
1015 if (mothersPDG.size() == 0)
return -2.0;
1018 if (index == 10)
return 1.0;
1022 bool isCharmedMesonInChain =
false;
1024 if ((index == 6) && mothersPDG.size() > 1)
1027 for (
auto& iMCMotherPDG : mothersPDG) {
1028 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1029 isCharmedMesonInChain =
true;
1038 bool isCharmedBaryonInChain =
false;
1040 if ((index == 6 || index == 9) && mothersPDG.size() > 1)
1043 for (
auto& iMCMotherPDG : mothersPDG) {
1044 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1045 isCharmedBaryonInChain =
true;
1053 bool isQQbarMesonInChain =
false;
1055 if ((index == 1 || index == 3 || index == 5 || index == 6 || index == 8) && mothersPDG.size() > 1)
1058 for (
auto& iMCMotherPDG : mothersPDG) {
1059 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1060 isQQbarMesonInChain =
true;
1069 bool isB0DaughterConservingFlavor =
false;
1071 if ((index == 8) && mothersPDG.size() > 1)
1074 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1075 mothersPDG.rbegin()[1]) != flavorConservingMesons.end()) {
1076 isB0DaughterConservingFlavor =
true;
1083 bool isHadronSingleTauDaughter =
false;
1085 if (index == 8 && mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1087 int numberOfChargedDaughters = 0;
1088 for (
auto& tauDaughter : mothersPointers.rbegin()[1] -> getDaughters()) {
1089 if (tauDaughter -> getCharge() != 0) numberOfChargedDaughters += 1;
1091 if (numberOfChargedDaughters == 1) isHadronSingleTauDaughter =
true;
1097 && mothersPDG[0] == 511)
1101 }
else if (index == 1
1102 && mcPDG == 11 && mothersPDG.size() > 1
1103 && isQQbarMesonInChain ==
false)
1107 }
else if (index == 2
1108 && mcPDG == 13 && mothersPDG[0] == 511)
1112 }
else if (index == 3
1113 && mcPDG == 13 && mothersPDG.size() > 1
1114 && isQQbarMesonInChain ==
false)
1118 }
else if (index == 4
1119 && (mcPDG == 13 || mcPDG == 11) && mothersPDG[0] == 511)
1123 }
else if (index == 5
1124 && (mcPDG == 13 || mcPDG == 11) && mothersPDG.size() > 1
1125 && isQQbarMesonInChain ==
false)
1129 }
else if (index == 6
1130 && mcPDG == 321 && isQQbarMesonInChain ==
false && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1134 }
else if (index == 7
1135 && mcPDG == 211 && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1139 }
else if (index == 8
1140 && (mcPDG == 211 || mcPDG == 321) && isQQbarMesonInChain ==
false && (mothersPDG[0] == 511 || (mothersPDG.rbegin()[0] == 511
1141 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1145 }
else if (index == 9 && mcPDG == 3122 && isCharmedBaryonInChain ==
true)
1152 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightTrack");
1156 Manager::FunctionPtr isRightCategory(
const std::vector<std::string>& arguments)
1158 if (arguments.size() == 1) {
1161 std::vector<std::string> names = {
"Electron",
1162 "IntermediateElectron",
1166 "IntermediateKinLepton",
1177 for (
unsigned i = 0; i < names.size(); ++i) {
1178 if (particleName == names[i]) index = i;
1182 B2FATAL(
"isRightCategory: Not available category " << particleName <<
1183 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1186 auto func = [index](
const Particle * particle) ->
double {
1188 Particle* nullParticle =
nullptr;
1189 float qTarget = particle -> getCharge();
1190 float qMC = Variable::isRestOfEventB0Flavor(nullParticle);
1192 const MCParticle* mcParticle = particle->getRelated<MCParticle>();
1193 if (mcParticle ==
nullptr)
return -2.0;
1195 int mcPDG = TMath::Abs(mcParticle->getPDG());
1198 std::vector<int> mothersPDG;
1199 std::vector<const MCParticle*> mothersPointers;
1201 const MCParticle* mcMother = mcParticle->getMother();
1202 while (mcMother !=
nullptr)
1204 mothersPDG.push_back(TMath::Abs(mcMother->getPDG()));
1205 if (index == 8 || index == 9) mothersPointers.push_back(mcMother);
1206 if (TMath::Abs(mcMother->getPDG()) == 511)
break;
1207 mcMother = mcMother -> getMother();
1210 if (mothersPDG.size() == 0)
return -2.0;
1212 if (index == 13)
return 1.0;
1216 bool isCharmedMesonInChain =
false;
1218 if ((index == 6) && mothersPDG.size() > 1)
1221 for (
auto& iMCMotherPDG : mothersPDG) {
1222 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1223 isCharmedMesonInChain =
true;
1232 bool isCharmedBaryonInChain =
false;
1234 if ((index == 6 || index == 12) && mothersPDG.size() > 1)
1237 for (
auto& iMCMotherPDG : mothersPDG) {
1238 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1239 isCharmedBaryonInChain =
true;
1247 bool isQQbarMesonInChain =
false;
1249 if ((index == 1 || index == 3 || index == 5 || index == 6 || index == 8 || index == 11) && mothersPDG.size() > 1)
1252 for (
auto& iMCMotherPDG : mothersPDG) {
1253 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1254 isQQbarMesonInChain =
true;
1263 bool isB0DaughterConservingFlavor =
false;
1265 if ((index == 8) && mothersPDG.size() > 1)
1268 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1269 mothersPDG.rbegin()[1]) != flavorConservingMesons.end()) {
1270 isB0DaughterConservingFlavor =
true;
1277 bool isHadronSingleTauDaughter =
false;
1279 if (index == 8 && mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1281 int numberOfChargedDaughters = 0;
1282 for (
auto& tauDaughter : mothersPointers.rbegin()[1] -> getDaughters()) {
1283 if (tauDaughter -> getCharge() != 0) numberOfChargedDaughters += 1;
1285 if (numberOfChargedDaughters == 1) isHadronSingleTauDaughter =
true;
1289 bool haveKaonPionSameMother =
false;
1293 const MCParticle* mcSlowPionMother =
nullptr;
1294 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
1295 Particle* targetSlowPion =
nullptr;
1296 if (SlowPionList.isValid()) {
1297 double mcProbSlowPion = 0;
1298 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
1299 Particle* pSlowPion = SlowPionList->getParticle(i);
1300 if (pSlowPion !=
nullptr) {
1301 if (pSlowPion -> hasExtraInfo(
"isRightCategory(SlowPion)")) {
1302 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
1303 if (probSlowPion > mcProbSlowPion) {
1304 mcProbSlowPion = probSlowPion;
1305 targetSlowPion = pSlowPion;
1310 if (targetSlowPion !=
nullptr) {
1311 const MCParticle* mcSlowPion = targetSlowPion ->
getRelated<MCParticle>();
1313 if (mcSlowPion !=
nullptr && mcSlowPion->getMother() !=
nullptr
1314 && TMath::Abs(mcSlowPion->getPDG()) == 211 && TMath::Abs(mcSlowPion->getMother()->getPDG()) == 413) {
1315 mcSlowPionMother = mcSlowPion->getMother();
1320 if (std::find(mothersPointers.begin(), mothersPointers.end(), mcSlowPionMother) != mothersPointers.end())
1321 haveKaonPionSameMother =
true;
1326 int FastParticlePDGMother = 0;
1331 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
1333 Particle* targetFastParticle =
nullptr;
1334 if (FastParticleList.isValid()) {
1335 double mcProbFastest = 0;
1336 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i) {
1337 Particle* particlei = FastParticleList->getParticle(i);
1338 if (particlei !=
nullptr) {
1339 TLorentzVector momParticlei = T.rotateLabToCms() * particlei -> get4Vector();
1340 if (momParticlei == momParticlei) {
1341 double probFastest = momParticlei.P();
1342 if (probFastest > mcProbFastest) {
1343 mcProbFastest = probFastest;
1344 targetFastParticle = particlei;
1349 if (targetFastParticle !=
nullptr) {
1350 const MCParticle* mcFastParticle = targetFastParticle ->
getRelated<MCParticle>();
1352 if (mcFastParticle !=
nullptr && mcFastParticle->getMother() !=
nullptr) {
1353 FastParticlePDGMother = TMath::Abs(mcFastParticle->getMother()->getPDG());
1354 qFSC = mcFastParticle->getCharge();
1362 && qTarget == qMC && mcPDG == 11 && mothersPDG[0] == 511)
1365 }
else if (index == 1
1366 && qTarget != qMC && mcPDG == 11 && mothersPDG.size() > 1
1367 && isQQbarMesonInChain ==
false)
1370 }
else if (index == 2
1371 && qTarget == qMC && mcPDG == 13 && mothersPDG[0] == 511)
1374 }
else if (index == 3
1375 && qTarget != qMC && mcPDG == 13 && mothersPDG.size() > 1
1376 && isQQbarMesonInChain ==
false)
1379 }
else if (index == 4
1380 && qTarget == qMC && (mcPDG == 11 || mcPDG == 13) && mothersPDG[0] == 511)
1383 }
else if (index == 5
1384 && qTarget != qMC && (mcPDG == 11 || mcPDG == 13) && mothersPDG.size() > 1
1385 && isQQbarMesonInChain ==
false)
1388 }
else if (index == 6 && qTarget == qMC
1389 && mcPDG == 321 && isQQbarMesonInChain ==
false && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1392 }
else if (index == 7 && qTarget != qMC
1393 && mcPDG == 211 && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1396 }
else if (index == 8 && qTarget == qMC
1397 && (mcPDG == 211 || mcPDG == 321) && isQQbarMesonInChain ==
false && (mothersPDG[0] == 511 || (mothersPDG.rbegin()[0] == 511
1398 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1401 }
else if (index == 9 && qTarget == qMC
1402 && mcPDG == 321 && haveKaonPionSameMother ==
true)
1405 }
else if (index == 10 && qTarget == qMC)
1408 }
else if (index == 11 && qTarget != qMC && mothersPDG.size() > 1 && qFSC == qMC
1409 && mcPDG == 211 && FastParticlePDGMother == 511 && isQQbarMesonInChain ==
false)
1412 }
else if (index == 12 && (particle->getPDGCode() / TMath::Abs(particle->getPDGCode())) != qMC
1413 && mcPDG == 3122 && isCharmedBaryonInChain ==
true)
1423 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightCategory");
1429 std::vector<std::string> availableExtraInfos = {
"isRightTrack(Electron)",
1430 "isRightTrack(IntermediateElectron)",
1431 "isRightTrack(Muon)",
1432 "isRightTrack(IntermediateMuon)",
1433 "isRightTrack(KinLepton)",
1434 "isRightTrack(IntermediateKinLepton)",
1435 "isRightTrack(Kaon)",
1436 "isRightTrack(SlowPion)",
1437 "isRightTrack(FastHadron)",
1438 "isRightTrack(MaximumPstar)",
1439 "isRightTrack(Lambda)",
1440 "isRightCategory(Electron)",
1441 "isRightCategory(IntermediateElectron)",
1442 "isRightCategory(Muon)",
1443 "isRightCategory(IntermediateMuon)",
1444 "isRightCategory(KinLepton)",
1445 "isRightCategory(IntermediateKinLepton)",
1446 "isRightCategory(Kaon)",
1447 "isRightCategory(SlowPion)",
1448 "isRightCategory(FastHadron)",
1449 "isRightCategory(MaximumPstar)",
1450 "isRightCategory(Lambda)",
1451 "isRightCategory(KaonPion)",
1452 "isRightCategory(FSC)",
1455 Manager::FunctionPtr QpOf(
const std::vector<std::string>& arguments)
1457 if (arguments.size() == 3) {
1459 auto outputExtraInfo = arguments[1];
1460 auto rankingExtraInfo = arguments[2];
1462 int indexOutput = -1;
1463 int indexRanking = -1;
1465 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1466 if (rankingExtraInfo == availableExtraInfos[i]) {indexRanking = i;
break;}
1470 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1471 if (outputExtraInfo == availableExtraInfos[i]) {indexOutput = i;
break;}
1474 if (indexRanking == -1) {
1475 B2FATAL(
"QpOf: Not available category " << rankingExtraInfo <<
1476 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1478 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1481 if (indexOutput == -1) {
1482 B2FATAL(
"QpOf: Not available category " << outputExtraInfo <<
1483 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1485 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1489 auto func = [
particleListName, indexOutput, indexRanking](
const Particle*) ->
double {
1490 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1492 Particle* target =
nullptr;
1496 if (ListOfParticles.isValid())
1498 float maximumTargetProb = 0;
1499 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i) {
1500 Particle* particlei = ListOfParticles->getParticle(i);
1501 if (particlei !=
nullptr) {
1502 double target_prob = 0;
1503 if (indexRanking == 9 || indexRanking == 20) {
1504 TLorentzVector momParticlei = T.rotateLabToCms() * particlei -> get4Vector();
1505 if (momParticlei == momParticlei) {
1506 target_prob = momParticlei.P();
1509 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
1510 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
1513 if (target_prob > maximumTargetProb) {
1514 maximumTargetProb = target_prob;
1519 if (target !=
nullptr) {
1520 prob = target -> getExtraInfo(
1521 availableExtraInfos[indexOutput]);
1523 if (indexRanking == 10 || indexRanking == 21) {
1524 qTarget = (-1) * target->getPDGCode() / TMath::Abs(target->getPDGCode());
1526 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1527 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18
1529 qTarget = (-1) * target -> getCharge();
1530 }
else qTarget = target -> getCharge();
1535 return qTarget * prob;
1539 B2FATAL(
"Wrong number of arguments (3 required) for meta function QpOf");
1543 Manager::FunctionPtr weightedQpOf(
const std::vector<std::string>& arguments)
1546 if (arguments.size() == 3) {
1549 auto outputExtraInfo = arguments[1];
1550 auto rankingExtraInfo = arguments[2];
1552 int indexOutput = -1;
1553 int indexRanking = -1;
1556 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1557 if (rankingExtraInfo == availableExtraInfos[i]) {indexRanking = i;
break;}
1561 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1562 if (outputExtraInfo == availableExtraInfos[i]) {indexOutput = i;
break;}
1565 if (indexRanking == -1) {
1566 B2FATAL(
"weightedQpOf: Not available category " << rankingExtraInfo <<
1567 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1569 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1572 if (indexOutput == -1) {
1573 B2FATAL(
"weightedQpOf: Not available category " << outputExtraInfo <<
1574 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1576 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1579 auto func = [
particleListName, indexOutput, indexRanking, rankingExtraInfo](
const Particle*) ->
double {
1581 double final_value = 0.0;
1583 auto compare = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1586 if (part1->hasExtraInfo(rankingExtraInfo)) info1 = part1->getExtraInfo(rankingExtraInfo);
1587 if (part2->hasExtraInfo(rankingExtraInfo)) info2 = part2->getExtraInfo(rankingExtraInfo);
1588 return (info1 > info2);
1591 auto compareMomentum = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1595 info1 = (T.rotateLabToCms() * part1 -> get4Vector()).P();
1596 info2 = (T.rotateLabToCms() * part2 -> get4Vector()).P();
1597 return (info1 > info2);
1600 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1601 if (ListOfParticles)
1603 if (ListOfParticles->getListSize() > 0) {
1606 std::vector<const Particle*> ParticleVector;
1607 ParticleVector.reserve(ListOfParticles->getListSize());
1609 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); i++) {
1610 ParticleVector.push_back(ListOfParticles->getParticle(i));
1613 if (indexRanking == 9 ||
1614 indexRanking == 20) std::sort(ParticleVector.begin(), ParticleVector.end(), compareMomentum);
1615 else std::sort(ParticleVector.begin(), ParticleVector.end(), compare);
1617 if (ParticleVector.size() != 0) final_value = 1.0;
1619 unsigned int Limit = ParticleVector.size() > 3 ? 3 : ParticleVector.size();
1620 for (
unsigned int i = 0; i < Limit; i++) {
1621 if (ParticleVector[i]->hasExtraInfo(availableExtraInfos[indexOutput])) {
1622 double flavor = 0.0;
1623 if (indexRanking == 10 || indexRanking == 21) {
1624 flavor = (-1) * ParticleVector[i]->getPDGCode() / TMath::Abs(ParticleVector[i]->getPDGCode());
1626 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1627 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18
1629 flavor = (-1) * ParticleVector[i] -> getCharge();
1630 }
else flavor = ParticleVector[i]->getCharge();
1632 double p = ParticleVector[i]->getExtraInfo(availableExtraInfos[indexOutput]);
1635 double qp = (flavor * p);
1636 val1 = val1 * (1 + qp);
1637 val2 = val2 * (1 - qp);
1640 final_value = (val1 - val2) / (val1 + val2);
1647 B2FATAL(
"Wrong number of arguments (3 required) for meta function weightedQpOf");
1651 Manager::FunctionPtr variableOfTarget(
const std::vector<std::string>& arguments)
1654 if (arguments.size() != 3)
1655 B2FATAL(
"Wrong number of arguments (3 required) for meta function variableOfTarget");
1658 auto inputVariable = arguments[1];
1659 auto rankingExtraInfo = arguments[2];
1661 int indexRanking = -1;
1663 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1664 if (rankingExtraInfo == availableExtraInfos[i]) {indexRanking = i;
break;}
1667 if (indexRanking == -1) {
1668 B2FATAL(
"variableOfTarget: category " << rankingExtraInfo <<
"not available" <<
1669 ". The possibilities for isRightTrack() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, MaximumPstar, and Lambda"
1671 ". The possibilities for isRightCategory() are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1675 auto func = [
particleListName, inputVariable, indexRanking](
const Particle*) ->
double {
1676 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1678 Particle* target =
nullptr;
1679 double output = std::numeric_limits<float>::quiet_NaN();
1681 if (ListOfParticles.isValid())
1683 float maximumTargetProb = 0;
1684 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i) {
1685 Particle* particlei = ListOfParticles->getParticle(i);
1686 if (particlei !=
nullptr) {
1687 double target_prob = 0;
1688 if (indexRanking == 9 || indexRanking == 20) {
1689 TLorentzVector momParticlei = T.rotateLabToCms() * particlei -> get4Vector();
1690 if (momParticlei == momParticlei) {
1691 target_prob = momParticlei.P();
1694 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
1695 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
1698 if (target_prob > maximumTargetProb) {
1699 maximumTargetProb = target_prob;
1704 if (target !=
nullptr) {
1705 Variable::Manager& manager = Variable::Manager::Instance();
1706 output = manager.getVariable(inputVariable)->
function(target);
1714 Manager::FunctionPtr hasTrueTarget(
const std::vector<std::string>& arguments)
1716 if (arguments.size() == 1) {
1717 auto categoryName = arguments[0];
1718 auto func = [categoryName](
const Particle*) ->
double {
1719 if (!(categoryName ==
"Electron" || categoryName ==
"IntermediateElectron" || categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton" || categoryName ==
"Kaon"
1720 || categoryName ==
"SlowPion" || categoryName ==
"FastHadron" || categoryName ==
"KaonPion" || categoryName ==
"Lambda" || categoryName ==
"MaximumPstar" || categoryName ==
"FSC"))
1722 B2FATAL(
"hasTrueTarget: Not available category" << categoryName <<
1723 ". The possibilities for the category name are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1728 std::string trackTargetName = categoryName;
1730 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron")
particleListName =
"e+:inRoe";
1731 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton")
particleListName =
"mu+:inRoe";
1732 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {
particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
1736 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
1738 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1740 double output = std::numeric_limits<double>::quiet_NaN();
1742 Variable::Manager& manager = Variable::Manager::Instance();
1745 if (ListOfParticles.isValid())
1748 bool particlesHaveMCAssociated =
false;
1750 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i) {
1751 Particle* iParticle = ListOfParticles->getParticle(i);
1752 if (iParticle !=
nullptr) {
1753 double targetFlag = 0;
1754 if (categoryName ==
"MaximumPstar") {
1755 targetFlag = manager.getVariable(
"hasHighestProbInCat(pi+:inRoe, isRightTrack(MaximumPstar))")->
function(iParticle);
1757 targetFlag = manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->
function(iParticle);
1759 if (targetFlag != -2) particlesHaveMCAssociated =
true;
1760 if (targetFlag == 1) {
1766 if (!particlesHaveMCAssociated) output = std::numeric_limits<double>::quiet_NaN();
1767 if (nTargets > 0) output = 1;
1775 B2FATAL(
"Wrong number of arguments (1 required) for meta function hasTrueTarget");
1779 Manager::FunctionPtr isTrueCategory(
const std::vector<std::string>& arguments)
1781 if (arguments.size() == 1) {
1782 auto categoryName = arguments[0];
1783 auto func = [categoryName](
const Particle*) ->
double {
1784 if (!(categoryName ==
"Electron" || categoryName ==
"IntermediateElectron" || categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton" || categoryName ==
"Kaon"
1785 || categoryName ==
"SlowPion" || categoryName ==
"FastHadron" || categoryName ==
"KaonPion" || categoryName ==
"Lambda" || categoryName ==
"MaximumPstar" || categoryName ==
"FSC"))
1787 B2FATAL(
"isTrueCategory: Not available category" << categoryName <<
1788 ". The possibilities for the category name are \nElectron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1793 std::string trackTargetName = categoryName;
1795 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron")
particleListName =
"e+:inRoe";
1796 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton")
particleListName =
"mu+:inRoe";
1797 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {
particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
1801 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
1803 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1805 double output = std::numeric_limits<double>::quiet_NaN();
1807 std::vector<Particle*> targetParticles;
1808 std::vector<Particle*> targetParticlesCategory;
1809 Variable::Manager& manager = Variable::Manager::Instance();
1811 if (ListOfParticles.isValid())
1815 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i) {
1816 Particle* iParticle = ListOfParticles->getParticle(i);
1817 if (iParticle !=
nullptr) {
1818 double targetFlag = 0;
1819 if (categoryName ==
"MaximumPstar") {
1820 targetFlag = manager.getVariable(
"hasHighestProbInCat(pi+:inRoe, isRightTrack(MaximumPstar))")->
function(iParticle);
1822 targetFlag = manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->
function(iParticle);
1824 if (targetFlag == 1) {
1825 targetParticles.push_back(iParticle);
1830 for (
auto& targetParticle : targetParticles) {
1831 double isTargetOfRightCategory = manager.getVariable(
"isRightCategory(" + categoryName +
")")->
function(targetParticle);
1832 if (isTargetOfRightCategory == 1) {
1834 nTargets += 1; targetParticlesCategory.push_back(targetParticle);
1835 }
else if (isTargetOfRightCategory == -2 && output != 1) output = std::numeric_limits<double>::quiet_NaN();
1857 B2FATAL(
"Wrong number of arguments (1 required) for meta function isTrueCategory");
1861 Manager::FunctionPtr qrOutput(
const std::vector<std::string>& arguments)
1863 if (arguments.size() == 1) {
1864 std::string combinerMethod = arguments[0];
1865 auto func = [combinerMethod](
const Particle * particle) ->
double {
1867 double output = std::numeric_limits<double>::quiet_NaN();
1868 auto* flavorTaggerInfo = particle -> getRelatedTo<FlavorTaggerInfo>();
1870 if (flavorTaggerInfo !=
nullptr)
1872 if (flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1873 output = flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined();
1879 B2FATAL(
"Wrong number of arguments for meta function qrOutput");
1883 Manager::FunctionPtr qOutput(
const std::vector<std::string>& arguments)
1885 if (arguments.size() == 1) {
1886 std::string combinerMethod = arguments[0];
1887 auto func = [combinerMethod](
const Particle * particle) ->
double {
1889 double output = std::numeric_limits<double>::quiet_NaN();
1890 auto* flavorTaggerInfo = particle -> getRelatedTo<FlavorTaggerInfo>();
1892 if (flavorTaggerInfo !=
nullptr)
1894 if (flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
1895 output = TMath::Sign(1, flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
1901 B2FATAL(
"Wrong number of arguments for meta function qOutput");
1905 Manager::FunctionPtr rBinBelle(
const std::vector<std::string>& arguments)
1907 if (arguments.size() == 1) {
1908 std::string combinerMethod = arguments[0];
1909 auto func = [combinerMethod](
const Particle * particle) ->
double {
1911 int output = std::numeric_limits<int>::quiet_NaN();
1912 auto* flavorTaggerInfo = particle -> getRelatedTo<FlavorTaggerInfo>();
1914 if (flavorTaggerInfo !=
nullptr)
1916 if (flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert") {
1917 double r = std::abs(flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
1918 if (r < 0.1) output = 0;
1919 if (r > 0.1 && r < 0.25) output = 1;
1920 if (r > 0.25 && r < 0.5) output = 2;
1921 if (r > 0.5 && r < 0.625) output = 3;
1922 if (r > 0.625 && r < 0.75) output = 4;
1923 if (r > 0.75 && r < 0.875) output = 5;
1924 if (r > 0.875 && r < 1.10) output = 6;
1931 B2FATAL(
"Wrong number of arguments for meta function rBinBelle");
1935 Manager::FunctionPtr qpCategory(
const std::vector<std::string>& arguments)
1937 if (arguments.size() == 1) {
1938 std::string categoryName = arguments[0];
1939 auto func = [categoryName](
const Particle * particle) ->
double {
1941 double output = std::numeric_limits<double>::quiet_NaN();
1942 auto* flavorTaggerInfo = particle -> getRelatedTo<FlavorTaggerInfo>();
1944 if (flavorTaggerInfo !=
nullptr)
1946 if (flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert") {
1947 std::map<std::string, float> iQpCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getQpCategory();
1948 if (iQpCategories.find(categoryName) != iQpCategories.end()) output = iQpCategories.at(categoryName);
1949 else if (iQpCategories.size() != 0) B2FATAL(
"qpCategory: Category with name " << categoryName
1950 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
1957 B2FATAL(
"Wrong number of arguments for meta function qpCategory");
1961 Manager::FunctionPtr isTrueFTCategory(
const std::vector<std::string>& arguments)
1963 if (arguments.size() == 1) {
1964 std::string categoryName = arguments[0];
1965 auto func = [categoryName](
const Particle * particle) ->
double {
1967 double output = std::numeric_limits<double>::quiet_NaN();
1968 auto* flavorTaggerInfo = particle -> getRelatedTo<FlavorTaggerInfo>();
1970 if (flavorTaggerInfo !=
nullptr)
1972 if (flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert") {
1973 std::map<std::string, float> iIsTrueCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getIsTrueCategory();
1974 if (iIsTrueCategories.find(categoryName) != iIsTrueCategories.end()) output = iIsTrueCategories.at(categoryName);
1975 else if (iIsTrueCategories.size() != 0) B2FATAL(
"isTrueFTCategory: Category with name " << categoryName
1976 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
1983 B2FATAL(
"Wrong number of arguments for meta function isTrueFTCategory");
1987 Manager::FunctionPtr hasTrueTargets(
const std::vector<std::string>& arguments)
1989 if (arguments.size() == 1) {
1990 std::string categoryName = arguments[0];
1991 auto func = [categoryName](
const Particle * particle) ->
double {
1993 double output = std::numeric_limits<double>::quiet_NaN();
1994 auto* flavorTaggerInfo = particle -> getRelatedTo<FlavorTaggerInfo>();
1996 if (flavorTaggerInfo !=
nullptr)
1998 if (flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert") {
1999 std::map<std::string, float> iHasTrueTargets = flavorTaggerInfo->getMethodMap(
"FBDT")->getHasTrueTarget();
2000 if (iHasTrueTargets.find(categoryName) != iHasTrueTargets.end()) output = iHasTrueTargets.at(categoryName);
2001 else if (iHasTrueTargets.size() != 0) B2FATAL(
"hasTrueTargets: Category with name " << categoryName
2002 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2009 B2FATAL(
"Wrong number of arguments for meta function hasTrueTargets");
2013 VARIABLE_GROUP(
"Flavor Tagger Variables");
2015 REGISTER_VARIABLE(
"pMissTag", momentumMissingTagSide,
"Calculates the missing Momentum for a given particle on the tag side.");
2016 REGISTER_VARIABLE(
"cosTPTO" , cosTPTO ,
"cosine of angle between thrust axis of given particle and thrust axis of ROE");
2017 REGISTER_VARIABLE(
"lambdaFlavor", lambdaFlavor,
"1.0 if Lambda0, -1.0 if Anti-Lambda0, 0.0 else.");
2018 REGISTER_VARIABLE(
"isLambda", isLambda,
"1.0 if MCLambda0, 0.0 else.");
2019 REGISTER_VARIABLE(
"lambdaZError", lambdaZError,
"Returns the Matrixelement[2][2] of the PositionErrorMatrix of the Vertex fit.");
2020 REGISTER_VARIABLE(
"momentumOfSecondDaughter", momentumOfSecondDaughter,
2021 "Returns the Momentum of second daughter if existing, else 0.");
2022 REGISTER_VARIABLE(
"momentumOfSecondDaughterCMS", momentumOfSecondDaughterCMS,
2023 "Returns the Momentum of second daughter if existing in CMS, else 0.");
2024 REGISTER_VARIABLE(
"chargeTimesKaonLiklihood", chargeTimesKaonLiklihood,
2025 "Returns the q*(highest PID_Likelihood for Kaons), else 0.");
2026 REGISTER_VARIABLE(
"ptTracksRoe", transverseMomentumOfChargeTracksInRoe,
2027 "Returns the transverse momentum of all charged tracks if there exists a ROE for the given particle, else 0.");
2028 REGISTER_VARIABLE(
"NumberOfKShortsInRoe", NumberOfKShortsInRoe,
2029 "Returns the number of K_S0 in the rest of event. The particleList K_S0:inRoe is required");
2031 REGISTER_VARIABLE(
"isInElectronOrMuonCat", isInElectronOrMuonCat,
2032 "Returns 1.0 if the particle has been selected as target in the Muon or Electron Category, 0.0 else.");
2034 REGISTER_VARIABLE(
"isMajorityInRestOfEventFromB0", isMajorityInRestOfEventFromB0,
2035 "[Eventbased] Check if the majority of the tracks in the current RestOfEvent are from a B0.");
2036 REGISTER_VARIABLE(
"isMajorityInRestOfEventFromB0bar", isMajorityInRestOfEventFromB0bar,
2037 "[Eventbased] Check if the majority of the tracks in the current RestOfEvent are from a B0bar.");
2038 REGISTER_VARIABLE(
"hasRestOfEventTracks", hasRestOfEventTracks,
2039 "Returns the amount of tracks in the RestOfEvent related to the given Particle. -2 If ROE is empty.");
2040 REGISTER_VARIABLE(
"isRelatedRestOfEventB0Flavor", isRelatedRestOfEventB0Flavor,
2041 "-1 (1) if the RestOfEvent related to the given Particle is related to a B0bar (B0). The MCError bit of Breco has to be 0, 1, 2, 16 or 1024. The output of the variable is 0 otherwise. If one Particle in the Rest of Event is found to belong the reconstructed B0, the output is -2(2) for a B0bar (B0) on the reco side.");
2042 REGISTER_VARIABLE(
"qrCombined", isRestOfEventB0Flavor,
2043 "[Eventbased] -1 (1) if current RestOfEvent is related to a B0bar (B0). The MCError bit of Breco has to be 0, 1, 2, 16 or 1024. The output of the variable is 0 otherwise. If one Particle in the Rest of Event is found to belong the reconstructed B0, the output is -2(2) for a B0bar (B0) on the reco side.");
2044 REGISTER_VARIABLE(
"ancestorHasWhichFlavor", ancestorHasWhichFlavor,
2045 "checks the decay chain of the given particle upwards up to the Y(4S) resonance.Output is 0 (1) if an ancestor is found to be a B0bar (B0), if not -2.");
2046 REGISTER_VARIABLE(
"B0mcErrors", B0mcErrors,
"mcErrors MCMatching Flag on the reconstructed B0_cp.");
2047 REGISTER_VARIABLE(
"isRelatedRestOfEventMajorityB0Flavor", isRelatedRestOfEventMajorityB0Flavor,
2048 " 0 (1) if the majority of tracks and clusters of the RestOfEvent related to the given Particle are related to a B0bar (B0).");
2049 REGISTER_VARIABLE(
"isRestOfEventMajorityB0Flavor", isRestOfEventMajorityB0Flavor,
2050 "0 (1) if the majority of tracks and clusters of the current RestOfEvent are related to a B0bar (B0).");
2051 REGISTER_VARIABLE(
"mcFlavorOfOtherB", mcFlavorOfOtherB,
2052 "Returns the MC flavor (+-1) of the accompaning tag-side B meson if the given particle is a correctly MC-matched B candidate. It returns 0 else. \n"
2053 "In other words, this variable checks the generated flavor of the other MC Upsilon(4S) daughter.");
2055 VARIABLE_GROUP(
"Flavor Tagger MetaFunctions")
2057 REGISTER_VARIABLE("CheckingVariables(ListName, requestedVariable)", CheckingVariables,
2058 "FlavorTagging:[Eventbased] Available checking variables are getListSize for particle lists.");
2059 REGISTER_VARIABLE("IsDaughterOf(variable)", IsDaughterOf, "Check if the particle is a daughter of the given list.");
2061 REGISTER_VARIABLE("BtagToWBosonVariables(requestedVariable)", BtagToWBosonVariables,
2062 "FlavorTagging:[Eventbased] Kinematical variables (recoilMass, pMissCMS, cosThetaMissCMS or EW90) assuming a semileptonic decay with the given particle as target.");
2063 REGISTER_VARIABLE("KaonPionVariables(requestedVariable)" , KaonPionVariables ,
2064 " Kinematical variables for KaonPion category (cosKaonPion or HaveOpositeCharges)");
2065 REGISTER_VARIABLE("FSCVariables(requestedVariable)", FSCVariables,
2066 "FlavorTagging:[Eventbased] Kinematical variables for FastSlowCorrelated category (pFastCMS, cosSlowFast, SlowFastHaveOpositeCharges, or cosTPTOFast).");
2067 REGISTER_VARIABLE("hasHighestProbInCat(particleListName, extraInfoName)", hasHighestProbInCat,
2068 "Returns 1.0 if the given Particle is classified as target track, i.e. if it has the highest target track probability in particlelistName. The probability is accessed via extraInfoName.");
2069 REGISTER_VARIABLE("HighestProbInCat(particleListName, extraInfoName)", HighestProbInCat,
2070 "Returns the highest target track probability value for the given category")
2072 REGISTER_VARIABLE("isRightTrack(particleName)", isRightTrack,
2073 "Checks if the given Particle was really from a B. 1.0 if true otherwise 0.0");
2074 REGISTER_VARIABLE("isRightCategory(particleName)", isRightCategory,
2075 "FlavorTagging: returns 1 if the class track by particleName category has the same flavor as the MC target track 0 else also if there is no target track");
2076 REGISTER_VARIABLE("QpOf(particleListName, outputExtraInfo, rankingExtraInfo)", QpOf,
2077 "FlavorTagging: [Eventbased] Returns the q*p value for a given list (argument[0]), where p is the probability of a category stored as extraInfo (argument[1]).\n"
2078 "The particle is selected after ranking according to a flavor tagging extraInfo (argument[2]).");
2079 REGISTER_VARIABLE("weightedQpOf(particleListName, outputExtraInfo, rankingExtraInfo)", weightedQpOf,
2080 "FlavorTagging: [Eventbased] Returns the weighted q*p value for a given list (argument[0]), where p is the probability of a category stored as extraInfo (argument[1]).\n"
2081 "The particles in the list are ranked according to a flavor tagging extraInfo (argument[2]). \n"
2082 "The values for the three top particles is combined into an effective (weighted) output.");
2083 REGISTER_VARIABLE("variableOfTarget(particleListName, inputVariable, rankingExtraInfo)", variableOfTarget,
2084 "FlavorTagging: [Eventbased] Returns the value of an input variable (argument[1]) for a particle selected from the given list (argument[0]).\n"
2085 "The particles are ranked according to a flavor tagging extraInfo (argument[2]).");
2087 REGISTER_VARIABLE("hasTrueTarget(categoryName)", hasTrueTarget,
2088 "Returns 1 if the given category has a target. 0 Else.")
2089 REGISTER_VARIABLE("isTrueCategory(categoryName)", isTrueCategory,
2090 "Returns 1 if the given category tags the B0 MC flavor correctly. 0 Else.")
2091 REGISTER_VARIABLE("qrOutput(combinerMethod)", qrOutput,
2092 "Returns the output of the flavorTagger for the given combinerMethod. The default methods are 'FBDT' or 'FANN'.")
2093 REGISTER_VARIABLE("qOutput(combinerMethod)", qOutput,
2094 "Returns the flavor tag q output of the flavorTagger for the given combinerMethod. The default methods are 'FBDT' or 'FANN'.")
2095 REGISTER_VARIABLE("rBinBelle(combinerMethod)", rBinBelle,
2096 "Returns the corresponding r (dilution) bin according to the Belle binning for the given combinerMethod. The default methods are 'FBDT' or 'FANN'.")
2097 REGISTER_VARIABLE("qpCategory(categoryName)", qpCategory,
2098 "Returns the output q (charge of target track) times p (probability that this is the right category) of the category with the given name. The allowed categories are the official Flavor Tagger Category Names.");
2099 REGISTER_VARIABLE("isTrueFTCategory(categoryName)", isTrueFTCategory,
2100 "Returns 1 if the target particle (checking the decay chain) of the category with the given name is found in the mc Particles, and if it provides the right Flavor. The allowed categories are the official Flavor Tagger Category Names.");
2101 REGISTER_VARIABLE("hasTrueTargets(categoryName)", hasTrueTargets,
2102 "Returns 1 if target particles (checking only the decay chain) of the category with the given name is found in the mc Particles. The allowed categories are the official Flavor Tagger Category Names.");