10#include <analysis/variables/FlavorTaggingVariables.h>
11#include <analysis/variables/ROEVariables.h>
13#include <analysis/variables/MCTruthVariables.h>
14#include <analysis/variables/KLMClusterVariables.h>
16#include <analysis/ClusterUtility/ClusterUtils.h>
18#include <analysis/utility/MCMatching.h>
19#include <analysis/utility/PCmsLabTransform.h>
22#include <framework/datastore/StoreObjPtr.h>
25#include <analysis/dataobjects/Particle.h>
26#include <analysis/dataobjects/RestOfEvent.h>
27#include <analysis/dataobjects/ParticleList.h>
28#include <analysis/dataobjects/FlavorTaggerInfo.h>
29#include <analysis/ContinuumSuppression/Thrust.h>
31#include <mdst/dataobjects/MCParticle.h>
32#include <mdst/dataobjects/Track.h>
33#include <mdst/dataobjects/ECLCluster.h>
34#include <mdst/dataobjects/KLMCluster.h>
35#include <mdst/dataobjects/PIDLikelihood.h>
38#include <framework/gearbox/Const.h>
39#include <framework/logging/Logger.h>
41#include <Math/Vector3D.h>
42#include <Math/Vector4D.h>
43#include <framework/geometry/B2Vector3.h>
61 double momentumMissingTagSide(
const Particle*)
63 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
64 if (!roe.isValid())
return 0;
66 ROOT::Math::PxPyPzEVector roeCMSVec;
68 const auto& roeChargedParticles = roe->getChargedParticles();
69 for (
auto roeChargedParticle : roeChargedParticles) {
73 double missMom = -roeCMSVec.P();
80 if (arguments.size() == 0)
82 else if (arguments.size() == 1)
83 maskName = arguments[0];
85 B2FATAL(
"At most 1 argument (name of mask) accepted.");
87 auto func = [maskName](
const Particle*) ->
double {
88 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
89 if (!roe.isValid())
return 0;
91 ROOT::Math::PxPyPzEVector roeCMSVec;
93 const auto& roeChargedParticles = roe->getChargedParticles(maskName);
94 for (
auto roeChargedParticle : roeChargedParticles)
98 double missMom = -roeCMSVec.P();
104 double cosTPTO(
const Particle* part)
106 StoreObjPtr<RestOfEvent> roeobject(
"RestOfEvent");
107 const RestOfEvent* roe;
108 if (roeobject.isValid()) {
111 roe = getRelatedROEObject(part);
116 std::vector<ROOT::Math::XYZVector> p3_cms_roe;
117 static const double P_MAX(3.2);
120 const auto& roeTracks = roe->getChargedParticles();
121 for (
auto& roeChargedParticle : roeTracks) {
125 if (p_cms != p_cms)
continue;
126 if (p_cms.P() > P_MAX)
continue;
127 p3_cms_roe.push_back(p_cms.Vect());
131 const auto& roePhotons = roe->getPhotons();
132 for (
auto& roePhoton : roePhotons) {
134 ROOT::Math::PxPyPzEVector p_lab = roePhoton->get4Vector();
135 if (p_lab != p_lab)
continue;
136 if (p_lab.P() < 0.05)
continue;
138 if (p_cms != p_cms)
continue;
139 if (p_cms.P() > P_MAX)
continue;
140 p3_cms_roe.push_back(p_cms.Vect());
144 const auto& roeKlongs = roe->getHadrons();
145 for (
auto& roeKlong : roeKlongs) {
146 if (nKLMClusterTrackMatches(roeKlong) == 0 && !(roeKlong->getKLMCluster()->getAssociatedEclClusterFlag())) {
147 ROOT::Math::PxPyPzEVector p_lab = roeKlong->get4Vector();
148 if (p_lab != p_lab)
continue;
149 if (p_lab.P() < 0.05)
continue;
151 if (p_cms != p_cms)
continue;
152 if (p_cms.P() > P_MAX)
continue;
153 p3_cms_roe.push_back(p_cms.Vect());
161 if (pAxis == pAxis) result = abs(cos(pAxis.Angle(thrustO)));
168 std::string maskName;
169 if (arguments.size() == 0)
171 else if (arguments.size() == 1)
172 maskName = arguments[0];
174 B2FATAL(
"At most 1 argument (name of mask) accepted.");
176 auto func = [maskName](
const Particle * particle) ->
double {
177 StoreObjPtr<RestOfEvent> roeobject(
"RestOfEvent");
178 const RestOfEvent* roe;
179 if (roeobject.isValid())
184 roe = getRelatedROEObject(particle);
189 std::vector<ROOT::Math::XYZVector> p3_cms_roe;
193 const auto& roeTracks = roe->getChargedParticles(maskName);
194 for (
auto& roeChargedParticle : roeTracks)
199 if (p_cms != p_cms)
continue;
201 p3_cms_roe.push_back(p_cms.Vect());
205 const auto& roePhotons = roe->getPhotons(maskName);
206 for (
auto& roePhoton : roePhotons)
209 ROOT::Math::PxPyPzEVector p_lab = roePhoton->get4Vector();
210 if (p_lab != p_lab)
continue;
213 if (p_cms != p_cms)
continue;
215 p3_cms_roe.push_back(p_cms.Vect());
220 const auto& roeKlongs = roe->getHadrons(maskName);
221 for (
auto& roeKlong : roeKlongs)
223 if (nKLMClusterTrackMatches(roeKlong) == 0 && !(roeKlong->getKLMCluster()->getAssociatedEclClusterFlag())) {
224 ROOT::Math::PxPyPzEVector p_lab = roeKlong->get4Vector();
225 if (p_lab != p_lab)
continue;
228 if (p_cms != p_cms)
continue;
230 p3_cms_roe.push_back(p_cms.Vect());
239 result = abs(cos(pAxis.Angle(thrustO)));
247 int lambdaFlavor(
const Particle* particle)
254 bool isLambda(
const Particle* particle)
257 if (!mcparticle)
return false;
261 double lambdaZError(
const Particle* particle)
265 TMatrixFSym ErrorPositionMatrix = particle->getVertexErrorMatrix();
266 return ErrorPositionMatrix[2][2];
269 double momentumOfSecondDaughter(
const Particle* part)
271 if (!part->getDaughter(1))
return 0.0;
272 return part->getDaughter(1)->getP();
275 double momentumOfSecondDaughterCMS(
const Particle* part)
277 if (!part->getDaughter(1))
return 0.0;
282 double chargeTimesKaonLiklihood(
const Particle*)
284 StoreObjPtr<ParticleList> KaonList(
"K+:inRoe");
285 if (!KaonList.isValid())
return 0;
287 double maximumKaonid = 0;
288 double maximum_charge = 0;
289 for (
unsigned int i = 0; i < KaonList->getListSize(); ++i) {
290 const Particle* p = KaonList->getParticle(i);
292 if (Kid > maximumKaonid) {
294 maximum_charge = p->getCharge();
297 return maximumKaonid * maximum_charge;
300 double transverseMomentumOfChargeTracksInRoe(
const Particle* part)
302 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
303 if (!roe.isValid())
return 0;
307 for (
const auto& track : roe->getChargedParticles()) {
308 if (part->isCopyOf(track,
true))
continue;
309 sum += track->getMomentum().Perp2();
316 Manager::FunctionPtr transverseMomentumOfChargeTracksInRoeWithMask(
const std::vector<std::string>& arguments)
318 std::string maskName;
319 if (arguments.size() == 0)
321 else if (arguments.size() == 1)
322 maskName = arguments[0];
324 B2FATAL(
"At most 1 argument (name of mask) accepted.");
326 auto func = [maskName](
const Particle * particle) ->
double {
327 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
328 if (!roe.isValid())
return 0;
332 for (
const auto& track : roe->getChargedParticles(maskName))
334 if (particle->isCopyOf(track,
true))
continue;
335 sum += track->getMomentum().Rho();
343 Manager::FunctionPtr transverseMomentumSquaredOfChargeTracksInRoeWithMask(
const std::vector<std::string>& arguments)
345 std::string maskName;
346 if (arguments.size() == 0)
348 else if (arguments.size() == 1)
349 maskName = arguments[0];
351 B2FATAL(
"At most 1 argument (name of mask) accepted.");
353 auto func = [maskName](
const Particle * particle) ->
double {
354 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
355 if (!roe.isValid())
return 0;
359 for (
const auto& track : roe->getChargedParticles(maskName))
361 if (particle->isCopyOf(track,
true))
continue;
362 sum += track->getMomentum().Perp2();
370 int NumberOfKShortsInRoe(
const Particle* particle)
372 StoreObjPtr<ParticleList> KShortList(
"K_S0:inRoe");
373 if (!KShortList.isValid())
374 B2FATAL(
"NumberOfKShortsInRoe cannot be calculated because the required particleList K_S0:inRoe could not be found or is not valid");
377 for (
unsigned int i = 0; i < KShortList->getListSize(); ++i) {
378 if (!particle->overlapsWith(KShortList->getParticle(i)))
386 bool isInElectronOrMuonCat(
const Particle* particle)
389 StoreObjPtr<ParticleList> MuonList(
"mu+:inRoe");
390 const Track* trackTargetMuon =
nullptr;
391 if (MuonList.isValid()) {
392 double maximumProbMuon = 0;
393 for (
unsigned int i = 0; i < MuonList->getListSize(); ++i) {
394 Particle* pMuon = MuonList->getParticle(i);
395 double probMuon = pMuon->getExtraInfo(
"isRightTrack(Muon)");
396 if (probMuon > maximumProbMuon) {
397 maximumProbMuon = probMuon;
398 trackTargetMuon = pMuon->getTrack();
402 if (particle->getTrack() == trackTargetMuon)
407 StoreObjPtr<ParticleList> ElectronList(
"e+:inRoe");
408 const Track* trackTargetElectron =
nullptr;
409 if (ElectronList.isValid()) {
410 double maximumProbElectron = 0;
411 for (
unsigned int i = 0; i < ElectronList->getListSize(); ++i) {
412 Particle* pElectron = ElectronList->getParticle(i);
413 double probElectron = pElectron->getExtraInfo(
"isRightTrack(Electron)");
414 if (probElectron > maximumProbElectron) {
415 maximumProbElectron = probElectron;
416 trackTargetElectron = pElectron->getTrack();
420 if (particle->getTrack() == trackTargetElectron)
427 static int getB0flavourMC(
const MCParticle* mcParticle)
430 if (mcParticle->getPDG() == 511) {
432 }
else if (mcParticle->getPDG() == -511) {
435 mcParticle = mcParticle->getMother();
442 bool isMajorityInRestOfEventFromB0(
const Particle*)
444 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
445 if (!roe.isValid())
return 0;
448 for (
auto& track : roe->getChargedParticles()) {
449 const MCParticle* mcParticle = track->getMCParticle();
450 vote += getB0flavourMC(mcParticle);
456 Manager::FunctionPtr isMajorityInRestOfEventFromB0WithMask(
const std::vector<std::string>& arguments)
458 std::string maskName;
459 if (arguments.size() == 0)
461 else if (arguments.size() == 1)
462 maskName = arguments[0];
464 B2FATAL(
"At most 1 argument (name of mask) accepted.");
466 auto func = [maskName](
const Particle*) ->
bool {
467 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
468 if (!roe.isValid())
return 0;
471 for (
auto& track : roe->getChargedParticles(maskName))
473 const MCParticle* mcParticle = track->getMCParticle();
474 vote += getB0flavourMC(mcParticle);
483 bool isMajorityInRestOfEventFromB0bar(
const Particle*)
485 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
486 if (!roe.isValid())
return 0;
489 for (
auto& track : roe->getChargedParticles()) {
490 const MCParticle* mcParticle = track->getMCParticle();
491 vote += getB0flavourMC(mcParticle);
497 Manager::FunctionPtr isMajorityInRestOfEventFromB0barWithMask(
const std::vector<std::string>& arguments)
499 std::string maskName;
500 if (arguments.size() == 0)
502 else if (arguments.size() == 1)
503 maskName = arguments[0];
505 B2FATAL(
"At most 1 argument (name of mask) accepted.");
507 auto func = [maskName](
const Particle*) ->
bool {
508 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
509 if (!roe.isValid())
return 0;
512 for (
auto& track : roe->getChargedParticles(maskName))
514 const MCParticle* mcParticle = track->getMCParticle();
515 vote += getB0flavourMC(mcParticle);
524 bool hasRestOfEventTracks(
const Particle* part)
526 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
527 return (roe && roe-> getNTracks() > 0);
532 std::string maskName;
533 if (arguments.size() == 0)
535 else if (arguments.size() == 1)
536 maskName = arguments[0];
538 B2FATAL(
"At most 1 argument (name of mask) accepted.");
540 auto func = [maskName](
const Particle*) ->
bool {
541 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
542 if (!roe.isValid())
return 0;
544 return roe->getNTracks(maskName) > 0;
549 int isRelatedRestOfEventB0Flavor(
const Particle* particle)
551 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
555 if (!BcpMC)
return 0;
556 if (Variable::isSignal(particle) <= 0)
return 0;
558 const MCParticle* Y4S = BcpMC->getMother();
564 for (
auto& roeChargedParticle : roe->getChargedParticles()) {
565 const MCParticle* mcParticle = roeChargedParticle->
getMCParticle();
567 if (mcParticle->getMother() == Y4S) {
568 if (mcParticle == BcpMC) {
569 if (mcParticle->getPDG() > 0) BcpFlavor = 2;
571 }
else if (BtagFlavor == 0) {
572 if (abs(mcParticle->getPDG()) == 511 || abs(mcParticle->getPDG()) == 521) {
573 if (mcParticle->getPDG() > 0) BtagFlavor = 1;
574 else BtagFlavor = -1;
575 }
else BtagFlavor = 5;
581 if (BcpFlavor != 0 || BtagFlavor == 5)
break;
585 return (BcpFlavor != 0) ? BcpFlavor : BtagFlavor;
588 Manager::FunctionPtr isRelatedRestOfEventB0FlavorWithMask(
const std::vector<std::string>& arguments)
590 std::string maskName;
591 if (arguments.size() == 0)
593 else if (arguments.size() == 1)
594 maskName = arguments[0];
596 B2FATAL(
"At most 1 argument (name of mask) accepted.");
598 auto func = [maskName](
const Particle * particle) ->
int {
599 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
600 if (!roe.isValid())
return 0;
603 if (!BcpMC)
return 0;
604 if (Variable::isSignal(particle) <= 0)
return 0;
606 const MCParticle* Y4S = BcpMC->getMother();
612 for (
auto& roeChargedParticle : roe->getChargedParticles(maskName))
614 const MCParticle* mcParticle = roeChargedParticle->
getMCParticle();
616 if (mcParticle->getMother() != Y4S) {
621 if (mcParticle == BcpMC) {
622 if (mcParticle->getPDG() > 0)
626 }
else if (BtagFlavor == 0) {
627 if (abs(mcParticle->getPDG()) == 511 || abs(mcParticle->getPDG()) == 521) {
628 if (mcParticle->getPDG() > 0)
638 if (BcpFlavor != 0 || BtagFlavor == 5)
break;
641 return (BcpFlavor != 0) ? BcpFlavor : BtagFlavor;
647 int isRestOfEventB0Flavor(
const Particle*)
649 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
650 if (!roe.isValid())
return 0;
652 const Particle* Bcp = roe->getRelatedFrom<Particle>();
653 return Variable::isRelatedRestOfEventB0Flavor(Bcp);
656 int ancestorHasWhichFlavor(
const Particle* particle)
658 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
659 if (!roe.isValid())
return 0;
661 const MCParticle* BcpMC = roe->
getRelatedFrom<Particle>()->getMCParticle();
662 const MCParticle* Y4S = BcpMC->getMother();
665 int outputB0tagQ = 0;
667 if (mcParticle->getMother() == Y4S) {
668 if (mcParticle != BcpMC && abs(mcParticle->getPDG()) == 511) {
669 if (mcParticle->getPDG() == 511) outputB0tagQ = 1;
670 else outputB0tagQ = -1;
671 }
else if (mcParticle == BcpMC) {
672 if (mcParticle->getPDG() == 511) outputB0tagQ = 2;
673 else outputB0tagQ = -2;
674 }
else outputB0tagQ = 5;
683 int B0mcErrors(
const Particle*)
685 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
686 if (!roe.isValid())
return -1;
688 const Particle* Bcp = roe->getRelatedFrom<Particle>();
689 const MCParticle* BcpMC = roe->
getRelatedFrom<Particle>()->getMCParticle();
693 int isRelatedRestOfEventMajorityB0Flavor(
const Particle* part)
695 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
700 if (roe->getNTracks() > 0) {
701 for (
auto& track : roe->getChargedParticles()) {
702 const MCParticle* mcParticle = track->getMCParticle();
703 q_MC += getB0flavourMC(mcParticle);
705 }
else if (roe->getNECLClusters() > 0) {
706 for (
auto& cluster : roe->getPhotons()) {
708 const MCParticle* mcParticle = cluster->getMCParticle();
709 q_MC += getB0flavourMC(mcParticle);
711 }
else if (roe->getNKLMClusters() > 0) {
712 for (
auto& klmcluster : roe->getHadrons()) {
714 q_MC += getB0flavourMC(mcParticle);
724 Manager::FunctionPtr isRelatedRestOfEventMajorityB0FlavorWithMask(
const std::vector<std::string>& arguments)
726 std::string maskName;
727 if (arguments.size() == 0)
729 else if (arguments.size() == 1)
730 maskName = arguments[0];
732 B2FATAL(
"At most 1 argument (name of mask) accepted.");
734 auto func = [maskName](
const Particle*) ->
int {
735 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
736 if (!roe.isValid())
return -2;
740 if (roe->getNTracks(maskName) > 0)
742 for (
auto& track : roe->getChargedParticles(maskName)) {
743 const MCParticle* mcParticle = track->getMCParticle();
744 q_MC += getB0flavourMC(mcParticle);
746 }
else if (roe->getNECLClusters(maskName) > 0)
748 for (
auto& cluster : roe->getPhotons(maskName)) {
750 const MCParticle* mcParticle = cluster->getMCParticle();
751 q_MC += getB0flavourMC(mcParticle);
753 }
else if (roe->getNKLMClusters(maskName) > 0)
755 for (
auto& klmcluster : roe->getHadrons(maskName)) {
757 q_MC += getB0flavourMC(mcParticle);
764 return int(q_MC > 0);
770 int isRestOfEventMajorityB0Flavor(
const Particle*)
772 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
773 if (!roe.isValid())
return -2;
775 const Particle* Bcp = roe->getRelatedFrom<Particle>();
776 return Variable::isRelatedRestOfEventMajorityB0Flavor(Bcp);
779 double mcFlavorOfOtherB(
const Particle* particle)
782 if (std::abs(particle->getPDGCode()) != 511 && std::abs(particle->getPDGCode()) != 521) {
783 B2ERROR(
"MCFlavorOfOtherB: this variable works only for B mesons.\n"
784 "The given particle with PDG code " << particle->getPDGCode() <<
785 " is not a B-meson candidate (PDG code 511 or 521). ");
792 const MCParticle* mcMother = mcParticle->getMother();
795 if (Variable::isSignal(particle) < 1.0)
return 0;
797 for (
auto& upsilon4SDaughter : mcMother->getDaughters()) {
798 if (upsilon4SDaughter == mcParticle)
continue;
799 return (upsilon4SDaughter->getPDG() > 0) ? 1 : -1;
813 std::string requestedVariable;
814 std::string maskName;
815 if (arguments.size() == 1) {
816 requestedVariable = arguments[0];
818 }
else if (arguments.size() == 2) {
819 requestedVariable = arguments[0];
820 maskName = arguments[1];
822 B2FATAL(
"Number of arguments must be 1 (requestedVariable) or 2 (requestedVariable, maskName).");
825 const std::vector<string> availableVariables = {
"recoilMass",
832 if (std::find(availableVariables.begin(), availableVariables.end(), requestedVariable) == availableVariables.end()) {
833 B2FATAL(
"Wrong variable " << requestedVariable <<
834 " requested. The possibilities are recoilMass, recoilMassSqrd, pMissCMS, cosThetaMissCMS or EW90");
837 auto func = [requestedVariable, maskName](
const Particle * particle) ->
double {
838 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
842 ROOT::Math::PxPyPzEVector momXChargedTracks;
843 const auto& roeChargedParticles = roe->getChargedParticles(maskName);
844 for (
auto& roeChargedParticle : roeChargedParticles)
846 if (roeChargedParticle->isCopyOf(particle,
true))
continue;
847 momXChargedTracks += roeChargedParticle->get4Vector();
850 ROOT::Math::PxPyPzEVector momXNeutralClusters = roe->get4VectorNeutralECLClusters(maskName);
851 const auto& klongs = roe->getHadrons(maskName);
852 for (
auto& klong : klongs)
854 if (nKLMClusterTrackMatches(klong) == 0 && !(klong->getKLMCluster()->getAssociatedEclClusterFlag())) {
855 momXNeutralClusters += klong->get4Vector();
861 ROOT::Math::PxPyPzEVector momMiss = -(momX + momTarget);
864 if (requestedVariable ==
"recoilMass") output = momX.M();
865 if (requestedVariable ==
"recoilMassSqrd") output = momX.M2();
866 if (requestedVariable ==
"pMissCMS") output = momMiss.P();
867 if (requestedVariable ==
"cosThetaMissCMS") output = momTarget.Vect().Unit().Dot(momMiss.Vect().Unit());
868 if (requestedVariable ==
"EW90")
871 ROOT::Math::PxPyPzEVector momW = momTarget + momMiss;
874 const auto& photons = roe->getPhotons(maskName);
875 for (
auto& photon : photons) {
877 E_W_90 += photon->getECLClusterEnergy();
880 for (
auto& roeChargedParticle : roeChargedParticles) {
881 if (roeChargedParticle->isCopyOf(particle,
true))
884 for (
const ECLCluster& chargedCluster : roeChargedParticle->getTrack()->getRelationsWith<ECLCluster>()) {
889 if (iEnergy == iEnergy) {
907 if (arguments.size() != 1)
908 B2FATAL(
"Wrong number of arguments (1 required) for meta function KaonPionVariables");
911 auto requestedVariable = arguments[0];
912 auto func = [requestedVariable](
const Particle * particle) ->
double {
914 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
917 if ((requestedVariable !=
"HaveOpositeCharges") && (requestedVariable !=
"cosKaonPion"))
918 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are cosKaonPion or HaveOpositeCharges");
921 ROOT::Math::PxPyPzEVector momTargetSlowPion;
922 double chargeTargetSlowPion = 0;
923 if (SlowPionList.isValid())
925 double maximumProbSlowPion = 0;
926 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
927 Particle* pSlowPion = SlowPionList->getParticle(i);
928 if (!pSlowPion)
continue;
929 if (!pSlowPion->hasExtraInfo(
"isRightCategory(SlowPion)"))
continue;
931 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
932 if (probSlowPion > maximumProbSlowPion) {
933 maximumProbSlowPion = probSlowPion;
934 chargeTargetSlowPion = pSlowPion->getCharge();
942 double chargeTargetKaon = particle->getCharge();
943 if (requestedVariable ==
"HaveOpositeCharges")
945 if (chargeTargetKaon * chargeTargetSlowPion == -1)
949 else if (requestedVariable ==
"cosKaonPion")
952 if (momTargetKaon == momTargetKaon && momTargetSlowPion == momTargetSlowPion)
953 output = momTargetKaon.Vect().Unit().Dot(momTargetSlowPion.Vect().Unit());
963 if (arguments.size() != 1)
964 B2FATAL(
"Wrong number of arguments (1 required) for meta function FSCVariables");
967 auto requestedVariable = arguments[0];
968 auto func = [requestedVariable](
const Particle * particle) ->
double {
969 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
970 if (!FastParticleList.isValid())
return 0;
973 if ((requestedVariable !=
"pFastCMS") && (requestedVariable !=
"cosSlowFast") && (requestedVariable !=
"cosTPTOFast") && (requestedVariable !=
"SlowFastHaveOpositeCharges"))
974 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are pFastCMS, cosSlowFast, cosTPTOFast or SlowFastHaveOpositeCharges");
977 double maximumProbFastest = 0;
978 ROOT::Math::PxPyPzEVector momFastParticle;
979 Particle* TargetFastParticle =
nullptr;
980 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i)
982 Particle* particlei = FastParticleList->getParticle(i);
983 if (!particlei)
continue;
986 if (momParticlei != momParticlei)
continue;
988 double probFastest = momParticlei.P();
989 if (probFastest > maximumProbFastest) {
990 maximumProbFastest = probFastest;
991 TargetFastParticle = particlei;
992 momFastParticle = momParticlei;
997 if (!TargetFastParticle)
return 0;
1000 double output = 0.0;
1002 if (requestedVariable ==
"cosTPTOFast")
1003 output = cosTPTO(TargetFastParticle);
1006 if (momSlowPion == momSlowPion)
1008 if (requestedVariable ==
"cosSlowFast") {
1009 output = momSlowPion.Vect().Unit().Dot(momFastParticle.Vect().Unit());
1010 }
else if (requestedVariable ==
"SlowFastHaveOpositeCharges") {
1011 if (particle->getCharge()*TargetFastParticle->getCharge() == -1) {
1015 output = momFastParticle.P();
1028 static const std::vector<int> charmMesons = {
1029 411 , 413 , 415, 421 , 423 , 425, 431, 433, 435,
1030 10411 , 10413 , 10421 , 10423 , 10431 , 10433,
1031 20413 , 20423 , 20433,
1034 static const std::vector<int> charmBaryons = {
1035 4112 , 4114 , 4122 , 4132 ,
1036 4212 , 4214 , 4222 , 4224 , 4232 ,
1037 4312 , 4314 , 4322 , 4324 , 4332 , 4334 ,
1038 4412 , 4414 , 4422 , 4424 , 4432 , 4434 ,
1043 static const std::vector<int> qqbarMesons = {
1045 111 , 113 , 115 , 117 , 119 ,
1046 10111 , 10113 , 10115 ,
1049 9000111 , 9000113 , 9010113 , 9040113 ,
1052 200111 , 9020113 , 9030113 , 100115 , 9000115 ,
1056 221 , 223 , 225 , 227 , 229 ,
1057 331 , 333 , 335 , 337 ,
1058 10223 , 10225 , 10331 , 10333 ,
1059 20223 , 20333 , 30223 ,
1061 9000221 , 9010221 , 9020221 , 9030221 ,
1067 9000223 , 9000225 , 9000229 ,
1068 9010223 , 9010225 , 9020225 , 9030225 ,
1069 9040221 , 9040225 , 9050221 ,
1070 9060221 , 9070221 , 9070225 ,
1078 10441 , 10443 , 20443 , 30443 ,
1080 9000443 , 9010443 , 9020443 ,
1084 static const std::vector<int> flavorConservingMesons = {
1086 213 , 215 , 217 , 219 ,
1087 10211 , 10213 , 10215 ,
1090 9000211 , 9000213 , 9010213 ,
1094 9010217 , 9020213 , 9030213 , 9040213 ,
1099 313 , 315 , 317 , 319 ,
1100 323 , 325 , 327 , 329 ,
1101 10311 , 10313 , 10315 ,
1102 10321 , 10323 , 10325 ,
1105 30313 , 30323 , 30343 ,
1110 9000311 , 9000313 , 9000315 ,
1111 9000321 , 9000323 , 9000325 ,
1120 const std::vector<std::string> availableForIsRightTrack = {
"Electron",
1121 "IntermediateElectron",
1125 "IntermediateKinLepton",
1133 const std::vector<std::string> availableForIsRightCategory = {
"Electron",
1134 "IntermediateElectron",
1138 "IntermediateKinLepton",
1153 if (arguments.size() != 1) {
1154 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightTrack");
1159 unsigned index = std::find(availableForIsRightTrack.begin(), availableForIsRightTrack.end(), particleName)
1160 - availableForIsRightTrack.begin();
1161 if (index == availableForIsRightTrack.size()) {
1162 B2FATAL(
"isRightTrack: Not available category " << particleName <<
1163 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron and Lambda");
1166 auto func = [index](
const Particle * particle) ->
int {
1169 if (!mcParticle)
return -2;
1171 int mcPDG = abs(mcParticle->getPDG());
1174 std::vector<int> mothersPDG;
1175 std::vector<const MCParticle*> mothersPointers;
1177 const MCParticle* mcMother = mcParticle->getMother();
1180 mothersPDG.push_back(abs(mcMother->getPDG()));
1181 mothersPointers.push_back(mcMother);
1182 if (abs(mcMother->getPDG()) == 511)
break;
1183 mcMother = mcMother->getMother();
1186 if (mothersPDG.size() == 0)
return -2;
1189 if (index == 10)
return 1;
1193 bool isCharmedMesonInChain =
false;
1194 for (
auto& iMCMotherPDG : mothersPDG)
1196 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1197 isCharmedMesonInChain =
true;
1204 bool isCharmedBaryonInChain =
false;
1205 for (
auto& iMCMotherPDG : mothersPDG)
1207 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1208 isCharmedBaryonInChain =
true;
1215 bool isQQbarMesonInChain =
false;
1216 for (
auto& iMCMotherPDG : mothersPDG)
1218 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1219 isQQbarMesonInChain =
true;
1226 bool isB0DaughterConservingFlavor =
false;
1227 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1228 mothersPDG.rbegin()[1]) != flavorConservingMesons.end())
1230 isB0DaughterConservingFlavor =
true;
1235 bool isHadronSingleTauDaughter =
false;
1236 if (mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1238 int numberOfChargedDaughters = 0;
1239 for (
auto& tauDaughter : mothersPointers.rbegin()[1]->getDaughters()) {
1240 if (tauDaughter->getCharge() != 0)
1241 numberOfChargedDaughters += 1;
1243 if (numberOfChargedDaughters == 1)
1244 isHadronSingleTauDaughter =
true;
1251 }
else if (index == 1
1252 && mcPDG ==
Const::electron.getPDGCode() && mothersPDG.size() > 1 && isQQbarMesonInChain ==
false)
1255 }
else if (index == 2
1256 && mcPDG ==
Const::muon.getPDGCode() && mothersPDG[0] == 511)
1259 }
else if (index == 3
1260 && mcPDG ==
Const::muon.getPDGCode() && mothersPDG.size() > 1 && isQQbarMesonInChain ==
false)
1263 }
else if (index == 4
1267 }
else if (index == 5
1269 && isQQbarMesonInChain ==
false)
1272 }
else if (index == 6
1273 && mcPDG ==
Const::kaon.getPDGCode() && isQQbarMesonInChain ==
false
1274 && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1277 }
else if (index == 7
1278 && mcPDG ==
Const::pion.getPDGCode() && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1281 }
else if (index == 8
1283 && isQQbarMesonInChain ==
false
1284 && (mothersPDG[0] == 511
1285 || (mothersPDG.rbegin()[0] == 511 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1288 }
else if (index == 9
1289 && mcPDG ==
Const::Lambda.getPDGCode() && isCharmedBaryonInChain ==
true)
1302 if (arguments.size() != 1) {
1303 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightCategory");
1308 unsigned index = find(availableForIsRightCategory.begin(), availableForIsRightCategory.end(), particleName)
1309 - availableForIsRightCategory.begin();
1310 if (index == availableForIsRightCategory.size()) {
1311 B2FATAL(
"isRightCategory: Not available category " << particleName <<
1312 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1315 auto func = [index](
const Particle * particle) ->
int {
1317 Particle* nullParticle =
nullptr;
1318 double qTarget = particle->getCharge();
1319 double qMC = Variable::isRestOfEventB0Flavor(nullParticle);
1322 if (!mcParticle)
return -2;
1324 int mcPDG = abs(mcParticle->getPDG());
1327 std::vector<int> mothersPDG;
1328 std::vector<const MCParticle*> mothersPointers;
1330 const MCParticle* mcMother = mcParticle->getMother();
1333 mothersPDG.push_back(abs(mcMother->getPDG()));
1334 mothersPointers.push_back(mcMother);
1335 if (abs(mcMother->getPDG()) == 511)
break;
1336 mcMother = mcMother->getMother();
1339 if (mothersPDG.size() == 0)
return -2;
1341 if (index == 13)
return 1;
1345 bool isCharmedMesonInChain =
false;
1346 for (
auto& iMCMotherPDG : mothersPDG)
1348 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1349 isCharmedMesonInChain =
true;
1356 bool isCharmedBaryonInChain =
false;
1357 for (
auto& iMCMotherPDG : mothersPDG)
1359 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1360 isCharmedBaryonInChain =
true;
1367 bool isQQbarMesonInChain =
false;
1368 for (
auto& iMCMotherPDG : mothersPDG)
1370 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1371 isQQbarMesonInChain =
true;
1378 bool isB0DaughterConservingFlavor =
false;
1379 if (mothersPDG.size() > 1)
1381 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1382 mothersPDG.rbegin()[1]) != flavorConservingMesons.end()) {
1383 isB0DaughterConservingFlavor =
true;
1389 bool isHadronSingleTauDaughter =
false;
1390 if (mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1392 int numberOfChargedDaughters = 0;
1393 for (
auto& tauDaughter : mothersPointers.rbegin()[1]->getDaughters()) {
1394 if (tauDaughter->getCharge() != 0)
1395 numberOfChargedDaughters += 1;
1397 if (numberOfChargedDaughters == 1)
1398 isHadronSingleTauDaughter =
true;
1402 bool haveKaonPionSameMother =
false;
1405 const MCParticle* mcSlowPionMother =
nullptr;
1406 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
1407 Particle* targetSlowPion =
nullptr;
1408 if (SlowPionList.isValid()) {
1409 double mcProbSlowPion = 0;
1410 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
1411 Particle* pSlowPion = SlowPionList->getParticle(i);
1412 if (!pSlowPion)
continue;
1413 if (pSlowPion->hasExtraInfo(
"isRightCategory(SlowPion)")) {
1414 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
1415 if (probSlowPion > mcProbSlowPion) {
1416 mcProbSlowPion = probSlowPion;
1417 targetSlowPion = pSlowPion;
1421 if (targetSlowPion !=
nullptr) {
1422 const MCParticle* mcSlowPion = targetSlowPion ->
getMCParticle();
1424 if (mcSlowPion !=
nullptr && mcSlowPion->getMother() !=
nullptr
1425 && abs(mcSlowPion->getPDG()) ==
Const::pion.
getPDGCode() && abs(mcSlowPion->getMother()->getPDG()) == 413) {
1426 mcSlowPionMother = mcSlowPion->
getMother();
1431 if (std::find(mothersPointers.begin(), mothersPointers.end(), mcSlowPionMother) != mothersPointers.end())
1432 haveKaonPionSameMother =
true;
1437 int FastParticlePDGMother = 0;
1441 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
1442 Particle* targetFastParticle =
nullptr;
1443 if (FastParticleList.isValid()) {
1444 double mcProbFastest = 0;
1445 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i) {
1446 Particle* particlei = FastParticleList->getParticle(i);
1447 if (!particlei)
continue;
1450 if (momParticlei == momParticlei) {
1451 double probFastest = momParticlei.P();
1452 if (probFastest > mcProbFastest) {
1453 mcProbFastest = probFastest;
1454 targetFastParticle = particlei;
1458 if (targetFastParticle !=
nullptr) {
1459 const MCParticle* mcFastParticle = targetFastParticle ->
getMCParticle();
1461 if (mcFastParticle !=
nullptr && mcFastParticle->getMother() !=
nullptr) {
1462 FastParticlePDGMother = abs(mcFastParticle->getMother()->getPDG());
1463 qFSC = mcFastParticle->getCharge();
1471 && qTarget == qMC && mcPDG ==
Const::electron.getPDGCode() && mothersPDG[0] == 511)
1474 }
else if (index == 1
1475 && qTarget != qMC && mcPDG ==
Const::electron.getPDGCode() && mothersPDG.size() > 1
1476 && isQQbarMesonInChain ==
false)
1479 }
else if (index == 2
1480 && qTarget == qMC && mcPDG ==
Const::muon.getPDGCode() && mothersPDG[0] == 511)
1483 }
else if (index == 3
1484 && qTarget != qMC && mcPDG ==
Const::muon.getPDGCode() && mothersPDG.size() > 1
1485 && isQQbarMesonInChain ==
false)
1488 }
else if (index == 4
1493 }
else if (index == 5
1495 && mothersPDG.size() > 1 && isQQbarMesonInChain ==
false)
1498 }
else if (index == 6
1499 && qTarget == qMC && mcPDG ==
Const::kaon.getPDGCode() && isQQbarMesonInChain ==
false
1500 && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1503 }
else if (index == 7
1504 && qTarget != qMC && mcPDG ==
Const::pion.getPDGCode()
1505 && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1508 }
else if (index == 8
1510 && isQQbarMesonInChain ==
false
1511 && (mothersPDG[0] == 511 || (mothersPDG.rbegin()[0] == 511
1512 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1515 }
else if (index == 9
1516 && qTarget == qMC && mcPDG ==
Const::kaon.getPDGCode() && haveKaonPionSameMother ==
true)
1519 }
else if (index == 10 && qTarget == qMC)
1522 }
else if (index == 11
1523 && qTarget != qMC && mothersPDG.size() > 1 && qFSC == qMC
1524 && mcPDG ==
Const::pion.
getPDGCode() && FastParticlePDGMother == 511 && isQQbarMesonInChain ==
false)
1527 }
else if (index == 12
1528 && (particle->getPDGCode() / abs(particle->getPDGCode())) != qMC
1543 if (arguments.size() != 2) {
1544 B2FATAL(
"Wrong number of arguments (2 required) for meta function hasHighestProbInCat");
1547 auto particleListName = arguments[0];
1548 auto extraInfoName = arguments[1];
1550 bool isAvailable =
false;
1551 for (
const auto& name : availableForIsRightTrack) {
1552 if (extraInfoName ==
"isRightTrack(" + name +
")") {
1557 for (
const auto& name : availableForIsRightCategory) {
1558 if (extraInfoName ==
"isRightCategory(" + name +
")") {
1563 if (extraInfoName ==
"isRightTrack(MaximumPstar)")
1568 string strAvailableForIsRightTrack;
1569 for (
const auto& name : availableForIsRightTrack)
1570 strAvailableForIsRightTrack += name +
" ";
1571 string strAvailableForIsRightCategory;
1572 for (
const auto& name : availableForIsRightCategory)
1573 strAvailableForIsRightCategory += name +
" ";
1575 B2FATAL(
"hasHighestProbInCat: Not available category" << extraInfoName <<
1576 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1577 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1580 auto func = [particleListName, extraInfoName](
const Particle * particle) ->
bool {
1581 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1582 if (!ListOfParticles.isValid())
return 0;
1584 double maximumProb = 0;
1585 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1587 const Particle* particlei = ListOfParticles->getParticle(i);
1588 if (!particlei)
continue;
1591 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
1593 if (momParticlei == momParticlei) {
1594 prob = momParticlei.P();
1597 if (particlei->hasExtraInfo(extraInfoName)) {
1598 prob = particlei->getExtraInfo(extraInfoName);
1601 if (prob > maximumProb) {
1607 bool output =
false;
1608 if ((extraInfoName ==
"isRightTrack(MaximumPstar)") && (
PCmsLabTransform::labToCms(particle->get4Vector()).P() == maximumProb))
1611 }
else if (extraInfoName !=
"isRightTrack(MaximumPstar)" && particle->hasExtraInfo(extraInfoName))
1613 if (particle->getExtraInfo(extraInfoName) == maximumProb) output =
true;
1623 if (arguments.size() != 2) {
1624 B2FATAL(
"Wrong number of arguments (2 required) for meta function HighestProbInCat");
1627 auto particleListName = arguments[0];
1628 auto extraInfoName = arguments[1];
1630 bool isAvailable =
false;
1631 for (
const auto& name : availableForIsRightTrack) {
1632 if (extraInfoName ==
"isRightTrack(" + name +
")") {
1637 for (
const auto& name : availableForIsRightCategory) {
1638 if (extraInfoName ==
"isRightCategory(" + name +
")") {
1643 if (extraInfoName ==
"isRightTrack(MaximumPstar)")
1648 string strAvailableForIsRightTrack;
1649 for (
const auto& name : availableForIsRightTrack)
1650 strAvailableForIsRightTrack += name +
" ";
1651 string strAvailableForIsRightCategory;
1652 for (
const auto& name : availableForIsRightCategory)
1653 strAvailableForIsRightCategory += name +
" ";
1655 B2FATAL(
"HighestProbInCat: Not available category" << extraInfoName <<
1656 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1657 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1660 auto func = [particleListName, extraInfoName](
const Particle*) ->
double {
1661 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1662 if (!ListOfParticles.isValid())
return 0;
1664 double maximumProb = 0;
1665 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1667 const Particle* particlei = ListOfParticles->getParticle(i);
1668 if (!particlei)
continue;
1671 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
1673 if (momParticlei == momParticlei) {
1674 prob = momParticlei.P();
1677 if (particlei->hasExtraInfo(extraInfoName)) {
1678 prob = particlei->getExtraInfo(extraInfoName);
1681 maximumProb = max(maximumProb, prob);
1691 const std::vector<std::string> availableExtraInfos = {
"isRightTrack(Electron)",
1692 "isRightTrack(IntermediateElectron)",
1693 "isRightTrack(Muon)",
1694 "isRightTrack(IntermediateMuon)",
1695 "isRightTrack(KinLepton)",
1696 "isRightTrack(IntermediateKinLepton)",
1697 "isRightTrack(Kaon)",
1698 "isRightTrack(SlowPion)",
1699 "isRightTrack(FastHadron)",
1700 "isRightTrack(MaximumPstar)",
1701 "isRightTrack(Lambda)",
1702 "isRightCategory(Electron)",
1703 "isRightCategory(IntermediateElectron)",
1704 "isRightCategory(Muon)",
1705 "isRightCategory(IntermediateMuon)",
1706 "isRightCategory(KinLepton)",
1707 "isRightCategory(IntermediateKinLepton)",
1708 "isRightCategory(Kaon)",
1709 "isRightCategory(SlowPion)",
1710 "isRightCategory(FastHadron)",
1711 "isRightCategory(MaximumPstar)",
1712 "isRightCategory(Lambda)",
1713 "isRightCategory(KaonPion)",
1714 "isRightCategory(FSC)",
1719 if (arguments.size() != 3) {
1720 B2FATAL(
"Wrong number of arguments (3 required) for meta function QpOf");
1723 auto particleListName = arguments[0];
1724 auto outputExtraInfo = arguments[1];
1725 auto rankingExtraInfo = arguments[2];
1727 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1728 rankingExtraInfo) - availableExtraInfos.begin();
1729 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1730 outputExtraInfo) - availableExtraInfos.begin();
1732 if (indexRanking == availableExtraInfos.size() or indexOutput == availableExtraInfos.size()) {
1733 string strAvailableForIsRightTrack;
1734 for (
const auto& name : availableForIsRightTrack)
1735 strAvailableForIsRightTrack += name +
" ";
1736 string strAvailableForIsRightCategory;
1737 for (
const auto& name : availableForIsRightCategory)
1738 strAvailableForIsRightCategory += name +
" ";
1740 B2FATAL(
"QpOf: Not available category " << rankingExtraInfo <<
1741 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1742 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1745 auto func = [particleListName, indexOutput, indexRanking](
const Particle*) ->
double {
1746 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1747 if (!ListOfParticles.isValid())
return 0;
1749 Particle* target =
nullptr;
1750 double maximumTargetProb = 0;
1751 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1753 Particle* particlei = ListOfParticles->getParticle(i);
1754 if (!particlei)
continue;
1756 double target_prob = 0;
1757 if (indexRanking == 9 || indexRanking == 20) {
1759 if (momParticlei == momParticlei) {
1760 target_prob = momParticlei.P();
1763 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
1764 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
1768 if (target_prob > maximumTargetProb) {
1769 maximumTargetProb = target_prob;
1775 if (!target)
return 0;
1779 if (indexRanking == 10 || indexRanking == 21)
1781 qTarget = (-1) * target->getPDGCode() / abs(target->getPDGCode());
1783 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1784 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18)
1786 qTarget = (-1) * target->getCharge();
1789 qTarget = target->getCharge();
1793 double prob = target->getExtraInfo(availableExtraInfos[indexOutput]);
1797 return qTarget * prob;
1804 if (arguments.size() != 3) {
1805 B2FATAL(
"Wrong number of arguments (3 required) for meta function weightedQpOf");
1810 auto particleListName = arguments[0];
1811 auto outputExtraInfo = arguments[1];
1812 auto rankingExtraInfo = arguments[2];
1815 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1816 rankingExtraInfo) - availableExtraInfos.begin();
1817 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1818 outputExtraInfo) - availableExtraInfos.begin();
1821 if (indexRanking == availableExtraInfos.size() or indexOutput == availableExtraInfos.size()) {
1822 string strAvailableForIsRightTrack;
1823 for (
const auto& name : availableForIsRightTrack)
1824 strAvailableForIsRightTrack += name +
" ";
1825 string strAvailableForIsRightCategory;
1826 for (
const auto& name : availableForIsRightCategory)
1827 strAvailableForIsRightCategory += name +
" ";
1829 B2FATAL(
"weightedQpOf: Not available category " << rankingExtraInfo <<
1830 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1831 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1835 auto func = [particleListName, indexOutput, indexRanking, rankingExtraInfo](
const Particle*) ->
double {
1837 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1838 if (!ListOfParticles)
return 0;
1839 if (ListOfParticles->getListSize() == 0)
return 0;
1842 auto compare = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1845 if (part1->hasExtraInfo(rankingExtraInfo)) info1 = part1->getExtraInfo(rankingExtraInfo);
1846 if (part2->hasExtraInfo(rankingExtraInfo)) info2 = part2->getExtraInfo(rankingExtraInfo);
1847 return (info1 > info2);
1850 auto compareMomentum = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1853 return (info1 > info2);
1856 std::vector<const Particle*> ParticleVector(ListOfParticles->getListSize());
1857 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1859 ParticleVector[i] = ListOfParticles->getParticle(i);
1862 if (indexRanking == 9 || indexRanking == 20)
1863 std::sort(ParticleVector.begin(), ParticleVector.end(), compareMomentum);
1865 std::sort(ParticleVector.begin(), ParticleVector.end(), compare);
1868 double final_value = 0.0;
1869 if (ParticleVector.size() != 0) final_value = 1.0;
1872 int Limit = min(3,
int(ParticleVector.size()));
1875 for (
int i = 0; i < Limit; ++i)
1877 if (ParticleVector[i]->hasExtraInfo(availableExtraInfos[indexOutput])) {
1878 double flavor = 0.0;
1879 if (indexRanking == 10 || indexRanking == 21) {
1880 flavor = - copysign(1, ParticleVector[i]->getPDGCode());
1882 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1883 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18) {
1884 flavor = - ParticleVector[i]->getCharge();
1886 flavor = + ParticleVector[i]->getCharge();
1889 double p = ParticleVector[i]->getExtraInfo(availableExtraInfos[indexOutput]);
1892 double qp = (flavor * p);
1897 final_value = (val1 - val2) / (val1 + val2);
1907 if (arguments.size() != 3) {
1908 B2FATAL(
"Wrong number of arguments (3 required) for meta function QpTrack");
1911 auto particleListName = arguments[0];
1912 auto outputExtraInfo = arguments[1];
1913 auto rankingExtraInfo = arguments[2];
1915 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1916 rankingExtraInfo) - availableExtraInfos.begin();
1917 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1918 outputExtraInfo) - availableExtraInfos.begin();
1920 if (indexRanking == availableExtraInfos.size() or indexOutput == availableExtraInfos.size()) {
1921 string strAvailableForIsRightTrack;
1922 for (
const auto& name : availableForIsRightTrack)
1923 strAvailableForIsRightTrack += name +
" ";
1924 string strAvailableForIsRightCategory;
1925 for (
const auto& name : availableForIsRightCategory)
1926 strAvailableForIsRightCategory += name +
" ";
1928 B2FATAL(
"QpTrack: Not available category " << rankingExtraInfo <<
1929 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1930 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1933 auto func = [particleListName, indexOutput, indexRanking](
const Particle * particle) ->
double {
1934 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1935 if (!ListOfParticles.isValid())
return 0;
1937 const auto mdstIndex = particle->getMdstArrayIndex();
1939 Particle* target =
nullptr;
1940 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1942 Particle* particlei = ListOfParticles->getParticle(i);
1946 if (particlei->getMdstArrayIndex() == mdstIndex) {
1953 if (!target)
return 0;
1957 if (indexRanking == 10 || indexRanking == 21)
1959 qTarget = (-1) * target->getPDGCode() / abs(target->getPDGCode());
1961 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1962 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18)
1964 qTarget = (-1) * target->getCharge();
1967 qTarget = target->getCharge();
1971 double prob = target->getExtraInfo(availableExtraInfos[indexOutput]);
1973 return qTarget * prob;
1981 if (arguments.size() != 3)
1982 B2FATAL(
"Wrong number of arguments (3 required) for meta function variableOfTarget");
1984 std::string particleListName = arguments[0];
1985 std::string inputVariable = arguments[1];
1986 std::string rankingExtraInfo = arguments[2];
1988 int indexRanking = -1;
1990 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1991 if (rankingExtraInfo == availableExtraInfos[i]) {indexRanking = i;
break;}
1994 if (indexRanking == -1) {
1995 string strAvailableForIsRightTrack;
1996 for (
const auto& name : availableForIsRightTrack)
1997 strAvailableForIsRightTrack += name +
" ";
1998 string strAvailableForIsRightCategory;
1999 for (
const auto& name : availableForIsRightCategory)
2000 strAvailableForIsRightCategory += name +
" ";
2002 B2FATAL(
"variableOfTarget: Not available category " << rankingExtraInfo <<
2003 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
2004 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
2008 auto func = [particleListName, var, indexRanking](
const Particle*) ->
double {
2009 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
2012 Particle* target =
nullptr;
2014 double maximumTargetProb = 0;
2015 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
2017 Particle* particlei = ListOfParticles->getParticle(i);
2018 if (!particlei)
continue;
2020 double target_prob = 0;
2021 if (indexRanking == 9 || indexRanking == 20) {
2023 if (momParticlei == momParticlei) {
2024 target_prob = momParticlei.P();
2027 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
2028 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
2031 if (target_prob > maximumTargetProb) {
2032 maximumTargetProb = target_prob;
2040 if (std::holds_alternative<double>(var->function(target)))
2042 return std::get<double>(var->function(target));
2043 }
else if (std::holds_alternative<int>(var->function(target)))
2045 return std::get<int>(var->function(target));
2046 }
else if (std::holds_alternative<bool>(var->function(target)))
2048 return std::get<bool>(var->function(target));
2056 if (arguments.size() != 1) {
2057 B2FATAL(
"Wrong number of arguments (1 required) for meta function hasTrueTarget");
2060 auto categoryName = arguments[0];
2062 bool isAvailable =
false;
2063 for (
const auto& name : availableForIsRightCategory) {
2064 if (categoryName == name) {
2069 if (categoryName ==
"mcAssociated")
2070 isAvailable =
false;
2073 string strAvailableForIsRightCategory;
2074 for (
const auto& name : availableForIsRightCategory) {
2075 if (name ==
"mcAssociated")
continue;
2076 strAvailableForIsRightCategory += name +
" ";
2078 B2FATAL(
"hasTrueTarget: Not available category" << categoryName <<
2079 ". The possibilities for the category name are " << endl << strAvailableForIsRightCategory);
2082 auto func = [categoryName](
const Particle*) ->
double {
2083 std::string particleListName;
2084 std::string trackTargetName = categoryName;
2086 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron") particleListName =
"e+:inRoe";
2087 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton") particleListName =
"mu+:inRoe";
2088 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
2089 else if (categoryName ==
"Lambda") particleListName =
"Lambda0:inRoe";
2090 else particleListName =
"pi+:inRoe";
2092 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
2094 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
2099 bool particlesHaveMCAssociated =
false;
2101 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
2103 Particle* iParticle = ListOfParticles->getParticle(i);
2104 if (!iParticle)
continue;
2106 if (categoryName ==
"MaximumPstar") {
2108 hasHighestProbInCat({
"pi+:inRoe",
"isRightTrack(MaximumPstar)"});
2109 bool targetFlag = std::get<bool>(selectionFunction(iParticle));
2111 particlesHaveMCAssociated =
true;
2115 int targetFlag = std::get<int>(manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->function(iParticle));
2116 if (targetFlag != -2) particlesHaveMCAssociated =
true;
2117 if (targetFlag == 1) ++nTargets;
2122 return (nTargets > 0);
2129 if (arguments.size() != 1) {
2130 B2FATAL(
"Wrong number of arguments (1 required) for meta function isTrueCategory");
2132 auto categoryName = arguments[0];
2134 bool isAvailable =
false;
2135 for (
const auto& name : availableForIsRightCategory) {
2136 if (categoryName == name) {
2141 if (categoryName ==
"mcAssociated")
2142 isAvailable =
false;
2145 string strAvailableForIsRightCategory;
2146 for (
const auto& name : availableForIsRightCategory) {
2147 if (name ==
"mcAssociated")
continue;
2148 strAvailableForIsRightCategory += name +
" ";
2150 B2FATAL(
"isTrueCategory: Not available category" << categoryName <<
2151 ". The possibilities for the category name are " << endl << strAvailableForIsRightCategory);
2154 auto func = [categoryName](
const Particle*) ->
double {
2155 std::string particleListName;
2156 std::string trackTargetName = categoryName;
2158 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron") particleListName =
"e+:inRoe";
2159 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton") particleListName =
"mu+:inRoe";
2160 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
2161 else if (categoryName ==
"Lambda") particleListName =
"Lambda0:inRoe";
2162 else particleListName =
"pi+:inRoe";
2164 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
2166 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
2169 std::vector<Particle*> targetParticles;
2170 std::vector<Particle*> targetParticlesCategory;
2175 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
2177 Particle* iParticle = ListOfParticles->getParticle(i);
2178 if (!iParticle)
continue;
2180 if (categoryName ==
"MaximumPstar") {
2182 hasHighestProbInCat({
"pi+:inRoe",
"isRightTrack(MaximumPstar)"});
2183 if (std::get<bool>(selectionFunction(iParticle)))
2184 targetParticles.push_back(iParticle);
2185 }
else if (std::get<int>(manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->function(iParticle))) {
2186 targetParticles.push_back(iParticle);
2190 for (
const auto& targetParticle : targetParticles)
2192 int isTargetOfRightCategory = std::get<int>(manager.getVariable(
"isRightCategory(" + categoryName +
")")->function(
2194 if (isTargetOfRightCategory == 1) {
2196 targetParticlesCategory.push_back(targetParticle);
2197 }
else if (isTargetOfRightCategory == -2 && output != 1)
2208 if (arguments.size() != 1)
2209 B2FATAL(
"Wrong number of arguments for meta function qrOutput");
2211 std::string combinerMethod = arguments[0];
2212 auto func = [combinerMethod](
const Particle * particle) ->
double {
2215 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2217 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2218 output = flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined();
2227 if (arguments.size() != 1)
2228 B2FATAL(
"Wrong number of arguments for meta function qOutput");
2230 std::string combinerMethod = arguments[0];
2231 auto func = [combinerMethod](
const Particle * particle) ->
double {
2234 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2236 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2237 output = TMath::Sign(1, flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
2246 if (arguments.size() != 1)
2247 B2FATAL(
"Wrong number of arguments for meta function rBinBelle");
2250 std::string combinerMethod = arguments[0];
2251 auto func = [combinerMethod](
const Particle * particle) ->
int {
2254 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2256 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2258 double r = std::abs(flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
2259 if (r < 0.1) output = 0;
2260 if (r > 0.1 && r < 0.25) output = 1;
2261 if (r > 0.25 && r < 0.5) output = 2;
2262 if (r > 0.5 && r < 0.625) output = 3;
2263 if (r > 0.625 && r < 0.75) output = 4;
2264 if (r > 0.75 && r < 0.875) output = 5;
2265 if (r > 0.875 && r < 1.10) output = 6;
2275 if (arguments.size() != 1)
2276 B2FATAL(
"Wrong number of arguments for meta function qpCategory");
2278 std::string categoryName = arguments[0];
2279 auto func = [categoryName](
const Particle * particle) ->
double {
2282 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2284 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2286 std::map<std::string, float> iQpCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getQpCategory();
2287 if (iQpCategories.find(categoryName) != iQpCategories.end()) output = iQpCategories.at(categoryName);
2288 else if (iQpCategories.size() != 0) B2FATAL(
"qpCategory: Category with name " << categoryName
2289 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2298 if (arguments.size() != 1)
2299 B2FATAL(
"Wrong number of arguments for meta function isTrueFTCategory");
2301 std::string categoryName = arguments[0];
2302 auto func = [categoryName](
const Particle * particle) ->
double {
2305 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2307 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2309 std::map<std::string, float> iIsTrueCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getIsTrueCategory();
2310 if (iIsTrueCategories.find(categoryName) != iIsTrueCategories.end()) output = iIsTrueCategories.at(categoryName);
2311 else if (iIsTrueCategories.size() != 0) B2FATAL(
"isTrueFTCategory: Category with name " << categoryName
2312 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2322 if (arguments.size() != 1)
2323 B2FATAL(
"Wrong number of arguments for meta function hasTrueTargets");
2325 std::string categoryName = arguments[0];
2326 auto func = [categoryName](
const Particle * particle) ->
double {
2329 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2331 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2333 std::map<std::string, float> iHasTrueTargets = flavorTaggerInfo->getMethodMap(
"FBDT")->getHasTrueTarget();
2334 if (iHasTrueTargets.find(categoryName) != iHasTrueTargets.end()) output = iHasTrueTargets.at(categoryName);
2335 else if (iHasTrueTargets.size() != 0) B2FATAL(
"hasTrueTargets: Category with name " << categoryName
2336 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2344 VARIABLE_GROUP(
"Flavor Tagger Expert Variables");
2346 REGISTER_VARIABLE(
"pMissTag", momentumMissingTagSide, R
"DOC(
2347[Expert] Calculates the missing momentum for a given particle on the tag side.
2350 REGISTER_METAVARIABLE("pMissTag(maskName)", momentumMissingTagSideWithMask,
2351 "[Expert] Calculates the missing momentum for a given particle on the tag side. The unit of the missing momentum is ``GeV/c`` ",
2352 Manager::VariableDataType::c_double);
2353 REGISTER_VARIABLE("cosTPTO" , cosTPTO, R"DOC(
2354[Expert] Returns cosine of angle between thrust axis of given particle and thrust axis of ROE.
2357 REGISTER_METAVARIABLE("cosTPTO(maskName)", cosTPTOWithMask,
2358 "[Expert] Returns cosine of angle between thrust axis of given particle and thrust axis of ROE.",
2359 Manager::VariableDataType::c_double);
2360 REGISTER_VARIABLE(
"lambdaFlavor", lambdaFlavor,
2361 "[Expert] Returns 1.0 if particle is ``Lambda0``, -1.0 in case of ``anti-Lambda0``, 0.0 otherwise.");
2362 REGISTER_VARIABLE(
"isLambda", isLambda,
"[Expert] Returns 1.0 if particle is truth-matched to ``Lambda0``, 0.0 otherwise.");
2363 REGISTER_VARIABLE(
"lambdaZError", lambdaZError,
"[Expert] Returns the variance of the z-component of the decay vertex.\n\n",
":math:`\\text{cm}^2`");
2364 REGISTER_VARIABLE(
"momentumOfSecondDaughter", momentumOfSecondDaughter,
2365 "[Expert] Returns the momentum of second daughter if exists, 0. otherwise.\n\n",
"GeV/c");
2366 REGISTER_VARIABLE(
"momentumOfSecondDaughterCMS", momentumOfSecondDaughterCMS,
2367 "[Expert] Returns the momentum of the second daughter in the centre-of-mass system, 0. if this daughter doesn't exist.\n\n",
"GeV/c");
2368 REGISTER_VARIABLE(
"chargeTimesKaonLiklihood", chargeTimesKaonLiklihood,
2369 "[Expert] Returns ``q*(highest PID_Likelihood for Kaons)``, 0. otherwise.");
2370 REGISTER_VARIABLE(
"ptTracksRoe", transverseMomentumOfChargeTracksInRoe, R
"DOC(
2371[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.
2374 REGISTER_METAVARIABLE("ptTracksRoe(maskName)", transverseMomentumOfChargeTracksInRoeWithMask,
2375 "[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. The unit of the momentum is ``GeV/c`` ",
2376 Manager::VariableDataType::c_double);
2377 REGISTER_METAVARIABLE("pt2TracksRoe(maskName)", transverseMomentumSquaredOfChargeTracksInRoeWithMask,
2378 "[Expert] Returns the transverse momentum squared of all charged tracks of the ROE related to the given particle, 0.0 if particle has no related ROE. The unit of the momentum squared is :math:`[\\text{GeV}/\\text{c}]^2` ",
2379 Manager::VariableDataType::c_double);
2380 REGISTER_VARIABLE("NumberOfKShortsInRoe", NumberOfKShortsInRoe,
2381 "[Expert] Returns the number of ``K_S0`` in the rest of event. The particle list ``K_S0:inRoe`` has to be filled beforehand.");
2383 REGISTER_VARIABLE("isInElectronOrMuonCat", isInElectronOrMuonCat,
2384 "[Expert] Returns 1.0 if the particle has been selected as target in the Muon or Electron Category, 0.0 otherwise.");
2386 REGISTER_VARIABLE("isMajorityInRestOfEventFromB0", isMajorityInRestOfEventFromB0, R"DOC(
2387[Eventbased][Expert] Checks if the majority of the tracks in the current RestOfEvent are from a ``B0``.
2390 REGISTER_METAVARIABLE("isMajorityInRestOfEventFromB0(maskName)", isMajorityInRestOfEventFromB0WithMask,
2391 "[Eventbased][Expert] Checks if the majority of the tracks in the current RestOfEvent are from a ``B0``.",
2392 Manager::VariableDataType::c_bool);
2393 REGISTER_VARIABLE(
"isMajorityInRestOfEventFromB0bar", isMajorityInRestOfEventFromB0bar, R
"DOC(
2394[Eventbased][Expert] Check if the majority of the tracks in the current RestOfEvent are from a ``anti-B0``.
2397 REGISTER_METAVARIABLE("isMajorityInRestOfEventFromB0bar(maskName)", isMajorityInRestOfEventFromB0barWithMask,
2398 "[Eventbased][Expert] Check if the majority of the tracks in the current RestOfEvent are from a ``anti-B0``.",
2399 Manager::VariableDataType::c_bool);
2400 REGISTER_VARIABLE(
"hasRestOfEventTracks", hasRestOfEventTracks, R
"DOC(
2401[Expert] Returns the number of tracks in the RestOfEvent related to the given Particle. -2 if the RestOfEvent is empty.
2404 REGISTER_METAVARIABLE("hasRestOfEventTracks(maskName)", hasRestOfEventTracksWithMask,
2405 "[Expert] Returns the number of tracks in the RestOfEvent related to the given Particle. -2 if the RestOfEvent is empty.",
2406 Manager::VariableDataType::c_bool);
2408 REGISTER_VARIABLE(
"qrCombined", isRestOfEventB0Flavor, R
"DOC(
2409[Eventbased][Expert] Returns -1 (1) if current RestOfEvent is related to a ``anti-B0`` (``B0``).
2410The ``MCError`` bit of Breco has to be 0, 1, 2, 16 or 1024.
2411The output of the variable is 0 otherwise.
2412If 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.
2414 REGISTER_VARIABLE("ancestorHasWhichFlavor", ancestorHasWhichFlavor,
2415 "[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.");
2416 REGISTER_VARIABLE(
"B0mcErrors", B0mcErrors,
"[Expert] Returns MC-matching flag, see :b2:var:`mcErrors` for the particle, e.g. ``B0`` .");
2417 REGISTER_VARIABLE(
"isRelatedRestOfEventMajorityB0Flavor", isRelatedRestOfEventMajorityB0Flavor, R
"DOC(
2418[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``).
2421 REGISTER_METAVARIABLE("isRelatedRestOfEventMajorityB0Flavor(maskName)", isRelatedRestOfEventMajorityB0FlavorWithMask,
2422 "[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``).",
2423 Manager::VariableDataType::c_int);
2424 REGISTER_VARIABLE(
"isRestOfEventMajorityB0Flavor", isRestOfEventMajorityB0Flavor,
2425 "[Expert] Returns 0 (1) if the majority of tracks and clusters of the current RestOfEvent are related to a ``anti-B0`` (``B0``).");
2426 REGISTER_VARIABLE(
"mcFlavorOfOtherB", mcFlavorOfOtherB, R
"DOC(
2427[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.
2428In other words, this variable checks the generated flavor of the other generated ``Upsilon(4S)`` daughter.
2432 REGISTER_METAVARIABLE("BtagToWBosonVariables(requestedVariable[, maskName])", BtagToWBosonVariables, R
"DOC(
2433[Eventbased][Expert] Returns values of FlavorTagging-specific kinematical variables assuming a semileptonic decay with the given particle as target.
2434The input values of ``requestedVariable`` can be the following: recoilMass in GeV/c^2 , pMissCMS in ``GeV/c``, cosThetaMissCMS and EW90.
2435)DOC", Manager::VariableDataType::c_double);
2436 REGISTER_METAVARIABLE("KaonPionVariables(requestedVariable)" , KaonPionVariables , R
"DOC(
2437[Expert] Returns values of FlavorTagging-specific kinematical variables for ``KaonPion`` category.
2438The input values of ``requestedVariable`` can be the following: cosKaonPion, HaveOpositeCharges.
2439)DOC", Manager::VariableDataType::c_double);
2440 REGISTER_METAVARIABLE("FSCVariables(requestedVariable)", FSCVariables, R
"DOC(
2441[Eventbased][Expert] Returns values of FlavorTagging-specific kinematical variables for ``FastSlowCorrelated`` category.
2442The input values of ``requestedVariable`` can be the following: pFastCMS in ``GeV/c``, cosSlowFast, SlowFastHaveOpositeCharges, or cosTPTOFast.
2443)DOC", Manager::VariableDataType::c_double);
2444 REGISTER_METAVARIABLE("hasHighestProbInCat(particleListName, extraInfoName)", hasHighestProbInCat, R
"DOC(
2445[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.
2446The probability is accessed via ``extraInfoName``, which can have the following input values:
2448* isRightTrack(Electron),
2449* isRightTrack(IntermediateElectron),
2450* isRightTrack(Muon),
2451* isRightTrack(IntermediateMuon),
2452* isRightTrack(KinLepton),
2453* isRightTrack(IntermediateKinLepton),
2454* isRightTrack(Kaon),
2455* isRightTrack(SlowPion),
2456* isRightTrack(FastHadron),
2457* isRightTrack(MaximumPstar),
2458* isRightTrack(Lambda),
2459* isRightCategory(Electron),
2460* isRightCategory(IntermediateElectron),
2461* isRightCategory(Muon),
2462* isRightCategory(IntermediateMuon),
2463* isRightCategory(KinLepton),
2464* isRightCategory(IntermediateKinLepton),
2465* isRightCategory(Kaon),
2466* isRightCategory(SlowPion),
2467* isRightCategory(FastHadron),
2468* isRightCategory(MaximumPstar),
2469* isRightCategory(Lambda),
2470* isRightCategory(KaonPion),
2471* isRightCategory(FSC).
2473)DOC", Manager::VariableDataType::c_bool);
2474 REGISTER_METAVARIABLE("HighestProbInCat(particleListName, extraInfoName)", HighestProbInCat,
2475 "[Expert] Returns the highest target track probability value for the given category, for allowed input values for ``extraInfoName`` see :b2:var:`hasHighestProbInCat`.", Manager::VariableDataType::c_double);
2477 REGISTER_METAVARIABLE(
"isRightTrack(particleName)", isRightTrack, R
"DOC(
2478[Expert] Returns 1.0 if the given particle was really from a B-meson depending on category provided in ``particleName`` argument, 0.0 otherwise.
2479Allowed input values for ``particleName`` argument in this variable are the following:
2482* IntermediateElectron,
2486* IntermediateKinLepton,
2493)DOC", Manager::VariableDataType::c_int);
2494 REGISTER_METAVARIABLE("isRightCategory(particleName)", isRightCategory, R
"DOC(
2495[Expert] Returns 1.0 if the class track by ``particleName`` category has the same flavor as the MC target track, 0.0 otherwise.
2496Allowed input values for ``particleName`` argument in this variable are the following:
2499* IntermediateElectron,
2503* IntermediateKinLepton
2513)DOC", Manager::VariableDataType::c_int);
2514 REGISTER_METAVARIABLE("QpOf(particleListName, outputExtraInfo, rankingExtraInfo)", QpOf, R
"DOC(
2515[Eventbased][Expert] Returns the :math:`q*p` value for a given particle list provided as the 1st argument,
2516where :math:`p` is the probability of a category stored as extraInfo, provided as the 2nd argument,
2517allowed values are same as in :b2:var:`hasHighestProbInCat`.
2518The particle is selected after ranking according to a flavor tagging extraInfo, provided as the 3rd argument,
2519allowed values are same as in :b2:var:`hasHighestProbInCat`.
2520)DOC", Manager::VariableDataType::c_double);
2521 REGISTER_METAVARIABLE("weightedQpOf(particleListName, outputExtraInfo, rankingExtraInfo)", weightedQpOf, R
"DOC(
2522[Eventbased][Expert] Returns the weighted :math:`q*p` value for a given particle list, provided as the 1st argument,
2523where :math:`p` is the probability of a category stored as extraInfo, provided in the 2nd argument,
2524allowed values are same as in :b2:var:`hasHighestProbInCat`.
2525The particles in the list are ranked according to a flavor tagging extraInfo, provided as the 3rd argument,
2526allowed values are same as in :b2:var:`hasHighestProbInCat`.
2527The values for the three top particles is combined into an effective (weighted) output.
2528)DOC", Manager::VariableDataType::c_double);
2529 REGISTER_METAVARIABLE("QpTrack(particleListName, outputExtraInfo, rankingExtraInfo)", QpTrack, R
"DOC(
2530[Expert] Returns the :math:`q*p` value of the particle in a given particle list provided as the 1st argument that is originated from the same Track of given particle.
2531where :math:`p` is the probability of a category stored as extraInfo, provided as the 2nd argument,
2532allowed values are same as in :b2:var:`hasHighestProbInCat`.
2533The particle is selected after ranking according to a flavor tagging extraInfo, provided as the 3rd argument,
2534allowed values are same as in :b2:var:`hasHighestProbInCat`.
2535)DOC", Manager::VariableDataType::c_double);
2537 REGISTER_METAVARIABLE("variableOfTarget(particleListName, inputVariable, rankingExtraInfo)", variableOfTarget, R
"DOC(
2538[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.
2539The particles are ranked according to a flavor tagging extraInfo, provided as the 2nd argument,
2540allowed values are same as in :b2:var:`hasHighestProbInCat`.
2541)DOC", Manager::VariableDataType::c_double);
2543 REGISTER_METAVARIABLE("hasTrueTarget(categoryName)", hasTrueTarget,
2544 "[Expert] Returns 1 if the given category has a target, 0 otherwise.", Manager::VariableDataType::c_double);
2545 REGISTER_METAVARIABLE(
"isTrueCategory(categoryName)", isTrueCategory,
2546 "[Expert] Returns 1 if the given category tags the B0 MC flavor correctly, 0 otherwise.", Manager::VariableDataType::c_double);
2548 REGISTER_METAVARIABLE(
"qpCategory(categoryName)", qpCategory, R
"DOC(
2549[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.
2550The allowed categories are the official Flavor Tagger Category Names.
2551)DOC", Manager::VariableDataType::c_double);
2552 REGISTER_METAVARIABLE("isTrueFTCategory(categoryName)", isTrueFTCategory, R
"DOC(
2553[Expert] Returns 1 if the target particle (checking the decay chain) of the category with the given name is found in the MC particles,
2554and if it provides the right flavor. The allowed categories are the official Flavor Tagger Category Names.
2555)DOC", Manager::VariableDataType::c_double);
2556 REGISTER_METAVARIABLE("hasTrueTargets(categoryName)", hasTrueTargets, R
"DOC(
2557[Expert] Returns 1 if target particles (checking only the decay chain) of the category with the given name is found in the MC particles.
2558The allowed categories are the official Flavor Tagger Category Names.
2559)DOC", Manager::VariableDataType::c_double);
2561 VARIABLE_GROUP("Flavor Tagger Analysis Variables")
2563 REGISTER_METAVARIABLE("rBinBelle(combinerMethod)", rBinBelle, R"DOC(
2564Returns the corresponding :math:`r` (dilution) bin according to the Belle binning for the given ``combinerMethod``.
2565The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2566The return values and the corresponding dilution ranges are the following:
2568* 0: :math:`0.000 < r < 0.100`;
2569* 1: :math:`0.100 < r < 0.250`;
2570* 2: :math:`0.250 < r < 0.500`;
2571* 3: :math:`0.500 < r < 0.625`;
2572* 4: :math:`0.625 < r < 0.750`;
2573* 5: :math:`0.750 < r < 0.875`;
2574* 6: :math:`0.875 < r < 1.000`.
2576.. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2577.. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2578)DOC", Manager::VariableDataType::c_int);
2579 REGISTER_METAVARIABLE("qrOutput(combinerMethod)", qrOutput, R"DOC(
2580Returns the output of the flavorTagger, flavor tag :math:`q` times the dilution factor :math:`r`, for the given combiner method.
2581The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2583.. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2584.. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2585)DOC", Manager::VariableDataType::c_double);
2586 REGISTER_METAVARIABLE("qOutput(combinerMethod)", qOutput, R"DOC(
2587Returns the flavor tag :math:`q` output of the flavorTagger for the given combinerMethod.
2588The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2590.. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2591.. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2592)DOC", Manager::VariableDataType::c_double);
2593 REGISTER_VARIABLE("isRelatedRestOfEventB0Flavor", isRelatedRestOfEventB0Flavor, R"DOC(
2594Returns -1 (1) if the RestOfEvent related to the given particle is related to a ``anti-B0`` (``B0``).
2595The ``MCError`` bit of Breco has to be 0, 1, 2, 16 or 1024.
2596The output of the variable is 0 otherwise.
2597If 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.
int getPDGCode() const
PDG code.
static const ParticleType Lambda
Lambda particle.
static const ChargedStable muon
muon particle
static const ChargedStable pion
charged pion particle
static const ParticleType antiLambda
Anti-Lambda particle.
static const double doubleNaN
quiet_NaN
static const ChargedStable kaon
charged kaon particle
static const ChargedStable electron
electron particle
@ c_nPhotons
CR is split into n photons (N1)
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
static constexpr const char * c_defaultMaskName
Default mask name.
static ROOT::Math::XYZVector calculateThrust(const std::vector< ROOT::Math::XYZVector > &momenta)
calculates the thrust axis
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
B2Vector3< double > B2Vector3D
typedef for common usage with double
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.
Abstract base class for different kinds of events.
static int getMCErrors(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle=nullptr)
Returns quality indicator of the match as a bit pattern where the individual bits indicate the the ty...