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/dataobjects/FlavorTaggerInfoMap.h>
30#include <analysis/ContinuumSuppression/Thrust.h>
32#include <mdst/dataobjects/MCParticle.h>
33#include <mdst/dataobjects/Track.h>
34#include <mdst/dataobjects/ECLCluster.h>
35#include <mdst/dataobjects/KLMCluster.h>
36#include <mdst/dataobjects/PIDLikelihood.h>
39#include <framework/gearbox/Const.h>
40#include <framework/logging/Logger.h>
42#include <Math/Vector3D.h>
43#include <Math/Vector4D.h>
44#include <Math/VectorUtil.h>
62 double momentumMissingTagSide(
const Particle*)
64 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
65 if (!roe.isValid())
return 0;
67 ROOT::Math::PxPyPzEVector roeCMSVec;
69 const auto& roeChargedParticles = roe->getChargedParticles();
70 for (
auto roeChargedParticle : roeChargedParticles) {
74 double missMom = -roeCMSVec.P();
81 if (arguments.size() == 0)
83 else if (arguments.size() == 1)
84 maskName = arguments[0];
86 B2FATAL(
"At most 1 argument (name of mask) accepted.");
88 auto func = [maskName](
const Particle*) ->
double {
89 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
90 if (!roe.isValid())
return 0;
92 ROOT::Math::PxPyPzEVector roeCMSVec;
94 const auto& roeChargedParticles = roe->getChargedParticles(maskName);
95 for (
auto roeChargedParticle : roeChargedParticles)
99 double missMom = -roeCMSVec.P();
105 double cosTPTO(
const Particle* part)
107 StoreObjPtr<RestOfEvent> roeobject(
"RestOfEvent");
108 const RestOfEvent* roe;
109 if (roeobject.isValid()) {
112 roe = getRelatedROEObject(part);
117 std::vector<ROOT::Math::PxPyPzEVector> p_cms_roe;
118 static const double P_MAX(3.2);
121 const auto& roeTracks = roe->getChargedParticles();
122 for (
auto& roeChargedParticle : roeTracks) {
126 if (p_cms != p_cms)
continue;
127 if (p_cms.P() > P_MAX)
continue;
128 p_cms_roe.push_back(p_cms);
132 const auto& roePhotons = roe->getPhotons();
133 for (
auto& roePhoton : roePhotons) {
135 ROOT::Math::PxPyPzEVector p_lab = roePhoton->get4Vector();
136 if (p_lab != p_lab)
continue;
137 if (p_lab.P() < 0.05)
continue;
139 if (p_cms != p_cms)
continue;
140 if (p_cms.P() > P_MAX)
continue;
141 p_cms_roe.push_back(p_cms);
145 const auto& roeKlongs = roe->getHadrons();
146 for (
auto& roeKlong : roeKlongs) {
147 if (nKLMClusterTrackMatches(roeKlong) == 0 && !(roeKlong->getKLMCluster()->getAssociatedEclClusterFlag())) {
148 ROOT::Math::PxPyPzEVector p_lab = roeKlong->get4Vector();
149 if (p_lab != p_lab)
continue;
150 if (p_lab.P() < 0.05)
continue;
152 if (p_cms != p_cms)
continue;
153 if (p_cms.P() > P_MAX)
continue;
154 p_cms_roe.push_back(p_cms);
162 if (pAxis == pAxis) result = abs(ROOT::Math::VectorUtil::CosTheta(pAxis, thrustO));
169 std::string maskName;
170 if (arguments.size() == 0)
172 else if (arguments.size() == 1)
173 maskName = arguments[0];
175 B2FATAL(
"At most 1 argument (name of mask) accepted.");
177 auto func = [maskName](
const Particle * particle) ->
double {
178 StoreObjPtr<RestOfEvent> roeobject(
"RestOfEvent");
179 const RestOfEvent* roe;
180 if (roeobject.isValid())
185 roe = getRelatedROEObject(particle);
190 std::vector<ROOT::Math::PxPyPzEVector> p_cms_roe;
194 const auto& roeTracks = roe->getChargedParticles(maskName);
195 for (
auto& roeChargedParticle : roeTracks)
200 if (p_cms != p_cms)
continue;
202 p_cms_roe.push_back(p_cms);
206 const auto& roePhotons = roe->getPhotons(maskName);
207 for (
auto& roePhoton : roePhotons)
210 ROOT::Math::PxPyPzEVector p_lab = roePhoton->get4Vector();
211 if (p_lab != p_lab)
continue;
214 if (p_cms != p_cms)
continue;
216 p_cms_roe.push_back(p_cms);
221 const auto& roeKlongs = roe->getHadrons(maskName);
222 for (
auto& roeKlong : roeKlongs)
224 if (nKLMClusterTrackMatches(roeKlong) == 0 && !(roeKlong->getKLMCluster()->getAssociatedEclClusterFlag())) {
225 ROOT::Math::PxPyPzEVector p_lab = roeKlong->get4Vector();
226 if (p_lab != p_lab)
continue;
229 if (p_cms != p_cms)
continue;
231 p_cms_roe.push_back(p_cms);
240 result = abs(ROOT::Math::VectorUtil::CosTheta(pAxis, thrustO));
248 int lambdaFlavor(
const Particle* particle)
255 bool isLambda(
const Particle* particle)
257 const MCParticle* mcparticle = particle->getMCParticle();
258 if (!mcparticle)
return false;
262 double lambdaZError(
const Particle* particle)
266 TMatrixFSym ErrorPositionMatrix = particle->getVertexErrorMatrix();
267 return ErrorPositionMatrix[2][2];
270 double momentumOfSecondDaughter(
const Particle* part)
272 if (!part->getDaughter(1))
return 0.0;
273 return part->getDaughter(1)->getP();
276 double momentumOfSecondDaughterCMS(
const Particle* part)
278 if (!part->getDaughter(1))
return 0.0;
283 double chargeTimesKaonLiklihood(
const Particle*)
285 StoreObjPtr<ParticleList> KaonList(
"K+:inRoe");
286 if (!KaonList.isValid())
return 0;
288 double maximumKaonid = 0;
289 double maximum_charge = 0;
290 for (
unsigned int i = 0; i < KaonList->getListSize(); ++i) {
291 const Particle* p = KaonList->getParticle(i);
293 if (Kid > maximumKaonid) {
295 maximum_charge = p->getCharge();
298 return maximumKaonid * maximum_charge;
301 double transverseMomentumOfChargeTracksInRoe(
const Particle* part)
303 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
304 if (!roe.isValid())
return 0;
308 for (
const auto& track : roe->getChargedParticles()) {
309 if (part->isCopyOf(track,
true))
continue;
310 sum += track->getMomentum().Perp2();
317 Manager::FunctionPtr transverseMomentumOfChargeTracksInRoeWithMask(
const std::vector<std::string>& arguments)
319 std::string maskName;
320 if (arguments.size() == 0)
322 else if (arguments.size() == 1)
323 maskName = arguments[0];
325 B2FATAL(
"At most 1 argument (name of mask) accepted.");
327 auto func = [maskName](
const Particle * particle) ->
double {
328 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
329 if (!roe.isValid())
return 0;
333 for (
const auto& track : roe->getChargedParticles(maskName))
335 if (particle->isCopyOf(track,
true))
continue;
336 sum += track->getMomentum().Rho();
344 Manager::FunctionPtr transverseMomentumSquaredOfChargeTracksInRoeWithMask(
const std::vector<std::string>& arguments)
346 std::string maskName;
347 if (arguments.size() == 0)
349 else if (arguments.size() == 1)
350 maskName = arguments[0];
352 B2FATAL(
"At most 1 argument (name of mask) accepted.");
354 auto func = [maskName](
const Particle * particle) ->
double {
355 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
356 if (!roe.isValid())
return 0;
360 for (
const auto& track : roe->getChargedParticles(maskName))
362 if (particle->isCopyOf(track,
true))
continue;
363 sum += track->getMomentum().Perp2();
371 int NumberOfKShortsInRoe(
const Particle* particle)
373 StoreObjPtr<ParticleList> KShortList(
"K_S0:inRoe");
374 if (!KShortList.isValid())
375 B2FATAL(
"NumberOfKShortsInRoe cannot be calculated because the required particleList K_S0:inRoe could not be found or is not valid");
378 for (
unsigned int i = 0; i < KShortList->getListSize(); ++i) {
379 if (!particle->overlapsWith(KShortList->getParticle(i)))
387 bool isInElectronOrMuonCat(
const Particle* particle)
390 StoreObjPtr<ParticleList> MuonList(
"mu+:inRoe");
391 const Track* trackTargetMuon =
nullptr;
392 if (MuonList.isValid()) {
393 double maximumProbMuon = 0;
394 for (
unsigned int i = 0; i < MuonList->getListSize(); ++i) {
395 Particle* pMuon = MuonList->getParticle(i);
396 double probMuon = pMuon->getExtraInfo(
"isRightTrack(Muon)");
397 if (probMuon > maximumProbMuon) {
398 maximumProbMuon = probMuon;
399 trackTargetMuon = pMuon->getTrack();
403 if (particle->getTrack() == trackTargetMuon)
408 StoreObjPtr<ParticleList> ElectronList(
"e+:inRoe");
409 const Track* trackTargetElectron =
nullptr;
410 if (ElectronList.isValid()) {
411 double maximumProbElectron = 0;
412 for (
unsigned int i = 0; i < ElectronList->getListSize(); ++i) {
413 Particle* pElectron = ElectronList->getParticle(i);
414 double probElectron = pElectron->getExtraInfo(
"isRightTrack(Electron)");
415 if (probElectron > maximumProbElectron) {
416 maximumProbElectron = probElectron;
417 trackTargetElectron = pElectron->getTrack();
421 if (particle->getTrack() == trackTargetElectron)
428 static int getB0flavourMC(
const MCParticle* mcParticle)
431 if (mcParticle->getPDG() == 511) {
433 }
else if (mcParticle->getPDG() == -511) {
436 mcParticle = mcParticle->getMother();
443 bool isMajorityInRestOfEventFromB0(
const Particle*)
445 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
446 if (!roe.isValid())
return 0;
449 for (
auto& track : roe->getChargedParticles()) {
450 const MCParticle* mcParticle = track->getMCParticle();
451 vote += getB0flavourMC(mcParticle);
457 Manager::FunctionPtr isMajorityInRestOfEventFromB0WithMask(
const std::vector<std::string>& arguments)
459 std::string maskName;
460 if (arguments.size() == 0)
462 else if (arguments.size() == 1)
463 maskName = arguments[0];
465 B2FATAL(
"At most 1 argument (name of mask) accepted.");
467 auto func = [maskName](
const Particle*) ->
bool {
468 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
469 if (!roe.isValid())
return 0;
472 for (
auto& track : roe->getChargedParticles(maskName))
474 const MCParticle* mcParticle = track->getMCParticle();
475 vote += getB0flavourMC(mcParticle);
484 bool isMajorityInRestOfEventFromB0bar(
const Particle*)
486 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
487 if (!roe.isValid())
return 0;
490 for (
auto& track : roe->getChargedParticles()) {
491 const MCParticle* mcParticle = track->getMCParticle();
492 vote += getB0flavourMC(mcParticle);
498 Manager::FunctionPtr isMajorityInRestOfEventFromB0barWithMask(
const std::vector<std::string>& arguments)
500 std::string maskName;
501 if (arguments.size() == 0)
503 else if (arguments.size() == 1)
504 maskName = arguments[0];
506 B2FATAL(
"At most 1 argument (name of mask) accepted.");
508 auto func = [maskName](
const Particle*) ->
bool {
509 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
510 if (!roe.isValid())
return 0;
513 for (
auto& track : roe->getChargedParticles(maskName))
515 const MCParticle* mcParticle = track->getMCParticle();
516 vote += getB0flavourMC(mcParticle);
525 bool hasRestOfEventTracks(
const Particle* part)
527 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
528 return (roe && roe-> getNTracks() > 0);
533 std::string maskName;
534 if (arguments.size() == 0)
536 else if (arguments.size() == 1)
537 maskName = arguments[0];
539 B2FATAL(
"At most 1 argument (name of mask) accepted.");
541 auto func = [maskName](
const Particle*) ->
bool {
542 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
543 if (!roe.isValid())
return 0;
545 return roe->getNTracks(maskName) > 0;
550 int isRelatedRestOfEventB0Flavor(
const Particle* particle)
552 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
555 const MCParticle* BcpMC = particle->getMCParticle();
556 if (!BcpMC)
return 0;
557 if (Variable::isSignal(particle) <= 0)
return 0;
559 const MCParticle* Y4S = BcpMC->getMother();
565 for (
auto& roeChargedParticle : roe->getChargedParticles()) {
566 const MCParticle* mcParticle = roeChargedParticle->getMCParticle();
568 if (mcParticle->getMother() == Y4S) {
569 if (mcParticle == BcpMC) {
570 if (mcParticle->getPDG() > 0) BcpFlavor = 2;
572 }
else if (BtagFlavor == 0) {
573 if (abs(mcParticle->getPDG()) == 511 || abs(mcParticle->getPDG()) == 521) {
574 if (mcParticle->getPDG() > 0) BtagFlavor = 1;
575 else BtagFlavor = -1;
576 }
else BtagFlavor = 5;
580 mcParticle = mcParticle->getMother();
582 if (BcpFlavor != 0 || BtagFlavor == 5)
break;
586 return (BcpFlavor != 0) ? BcpFlavor : BtagFlavor;
589 Manager::FunctionPtr isRelatedRestOfEventB0FlavorWithMask(
const std::vector<std::string>& arguments)
591 std::string maskName;
592 if (arguments.size() == 0)
594 else if (arguments.size() == 1)
595 maskName = arguments[0];
597 B2FATAL(
"At most 1 argument (name of mask) accepted.");
599 auto func = [maskName](
const Particle * particle) ->
int {
600 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
601 if (!roe.isValid())
return 0;
603 const MCParticle* BcpMC = particle->getMCParticle();
604 if (!BcpMC)
return 0;
605 if (Variable::isSignal(particle) <= 0)
return 0;
607 const MCParticle* Y4S = BcpMC->getMother();
613 for (
auto& roeChargedParticle : roe->getChargedParticles(maskName))
615 const MCParticle* mcParticle = roeChargedParticle->getMCParticle();
617 if (mcParticle->getMother() != Y4S) {
618 mcParticle = mcParticle->getMother();
622 if (mcParticle == BcpMC) {
623 if (mcParticle->getPDG() > 0)
627 }
else if (BtagFlavor == 0) {
628 if (abs(mcParticle->getPDG()) == 511 || abs(mcParticle->getPDG()) == 521) {
629 if (mcParticle->getPDG() > 0)
639 if (BcpFlavor != 0 || BtagFlavor == 5)
break;
642 return (BcpFlavor != 0) ? BcpFlavor : BtagFlavor;
648 int isRestOfEventB0Flavor(
const Particle*)
650 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
651 if (!roe.isValid())
return 0;
653 const Particle* Bcp = roe->getRelatedFrom<Particle>();
654 return Variable::isRelatedRestOfEventB0Flavor(Bcp);
657 int ancestorHasWhichFlavor(
const Particle* particle)
659 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
660 if (!roe.isValid())
return 0;
662 const MCParticle* BcpMC = roe->getRelatedFrom<Particle>()->getMCParticle();
663 const MCParticle* Y4S = BcpMC->getMother();
664 const MCParticle* mcParticle = particle->getMCParticle();
666 int outputB0tagQ = 0;
668 if (mcParticle->getMother() == Y4S) {
669 if (mcParticle != BcpMC && abs(mcParticle->getPDG()) == 511) {
670 if (mcParticle->getPDG() == 511) outputB0tagQ = 1;
671 else outputB0tagQ = -1;
672 }
else if (mcParticle == BcpMC) {
673 if (mcParticle->getPDG() == 511) outputB0tagQ = 2;
674 else outputB0tagQ = -2;
675 }
else outputB0tagQ = 5;
678 mcParticle = mcParticle->getMother();
684 int B0mcErrors(
const Particle*)
686 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
687 if (!roe.isValid())
return -1;
689 const Particle* Bcp = roe->getRelatedFrom<Particle>();
690 const MCParticle* BcpMC = roe->getRelatedFrom<Particle>()->getMCParticle();
694 int isRelatedRestOfEventMajorityB0Flavor(
const Particle* part)
696 const RestOfEvent* roe = part->getRelatedTo<RestOfEvent>();
701 if (roe->getNTracks() > 0) {
702 for (
auto& track : roe->getChargedParticles()) {
703 const MCParticle* mcParticle = track->getMCParticle();
704 q_MC += getB0flavourMC(mcParticle);
706 }
else if (roe->getNECLClusters() > 0) {
707 for (
auto& cluster : roe->getPhotons()) {
709 const MCParticle* mcParticle = cluster->getMCParticle();
710 q_MC += getB0flavourMC(mcParticle);
712 }
else if (roe->getNKLMClusters() > 0) {
713 for (
auto& klmcluster : roe->getHadrons()) {
714 const MCParticle* mcParticle = klmcluster->getMCParticle();
715 q_MC += getB0flavourMC(mcParticle);
725 Manager::FunctionPtr isRelatedRestOfEventMajorityB0FlavorWithMask(
const std::vector<std::string>& arguments)
727 std::string maskName;
728 if (arguments.size() == 0)
730 else if (arguments.size() == 1)
731 maskName = arguments[0];
733 B2FATAL(
"At most 1 argument (name of mask) accepted.");
735 auto func = [maskName](
const Particle*) ->
int {
736 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
737 if (!roe.isValid())
return -2;
741 if (roe->getNTracks(maskName) > 0)
743 for (
auto& track : roe->getChargedParticles(maskName)) {
744 const MCParticle* mcParticle = track->getMCParticle();
745 q_MC += getB0flavourMC(mcParticle);
747 }
else if (roe->getNECLClusters(maskName) > 0)
749 for (
auto& cluster : roe->getPhotons(maskName)) {
751 const MCParticle* mcParticle = cluster->getMCParticle();
752 q_MC += getB0flavourMC(mcParticle);
754 }
else if (roe->getNKLMClusters(maskName) > 0)
756 for (
auto& klmcluster : roe->getHadrons(maskName)) {
757 const MCParticle* mcParticle = klmcluster->getMCParticle();
758 q_MC += getB0flavourMC(mcParticle);
765 return int(q_MC > 0);
771 int isRestOfEventMajorityB0Flavor(
const Particle*)
773 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
774 if (!roe.isValid())
return -2;
776 const Particle* Bcp = roe->getRelatedFrom<Particle>();
777 return Variable::isRelatedRestOfEventMajorityB0Flavor(Bcp);
780 double mcFlavorOfOtherB(
const Particle* particle)
783 if (std::abs(particle->getPDGCode()) != 511 && std::abs(particle->getPDGCode()) != 521) {
784 B2ERROR(
"MCFlavorOfOtherB: this variable works only for B mesons.\n"
785 "The given particle with PDG code " << particle->getPDGCode() <<
786 " is not a B-meson candidate (PDG code 511 or 521). ");
790 const MCParticle* mcParticle = particle->getMCParticle();
793 const MCParticle* mcMother = mcParticle->getMother();
796 if (Variable::isSignal(particle) < 1.0)
return 0;
798 for (
auto& upsilon4SDaughter : mcMother->getDaughters()) {
799 if (upsilon4SDaughter == mcParticle)
continue;
800 return (upsilon4SDaughter->getPDG() > 0) ? 1 : -1;
814 std::string requestedVariable;
815 std::string maskName;
816 if (arguments.size() == 1) {
817 requestedVariable = arguments[0];
819 }
else if (arguments.size() == 2) {
820 requestedVariable = arguments[0];
821 maskName = arguments[1];
823 B2FATAL(
"Number of arguments must be 1 (requestedVariable) or 2 (requestedVariable, maskName).");
826 const std::vector<string> availableVariables = {
"recoilMass",
833 if (std::find(availableVariables.begin(), availableVariables.end(), requestedVariable) == availableVariables.end()) {
834 B2FATAL(
"Wrong variable " << requestedVariable <<
835 " requested. The possibilities are recoilMass, recoilMassSqrd, pMissCMS, cosThetaMissCMS or EW90");
838 auto func = [requestedVariable, maskName](
const Particle * particle) ->
double {
839 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
843 ROOT::Math::PxPyPzEVector momXChargedTracks;
844 const auto& roeChargedParticles = roe->getChargedParticles(maskName);
845 for (
auto& roeChargedParticle : roeChargedParticles)
847 if (roeChargedParticle->isCopyOf(particle,
true))
continue;
848 momXChargedTracks += roeChargedParticle->get4Vector();
851 ROOT::Math::PxPyPzEVector momXNeutralClusters = roe->get4VectorNeutralECLClusters(maskName);
852 const auto& klongs = roe->getHadrons(maskName);
853 for (
auto& klong : klongs)
855 if (nKLMClusterTrackMatches(klong) == 0 && !(klong->getKLMCluster()->getAssociatedEclClusterFlag())) {
856 momXNeutralClusters += klong->get4Vector();
862 ROOT::Math::PxPyPzEVector momMiss = -(momX + momTarget);
865 if (requestedVariable ==
"recoilMass") output = momX.M();
866 if (requestedVariable ==
"recoilMassSqrd") output = momX.M2();
867 if (requestedVariable ==
"pMissCMS") output = momMiss.P();
868 if (requestedVariable ==
"cosThetaMissCMS") output = momTarget.Vect().Unit().Dot(momMiss.Vect().Unit());
869 if (requestedVariable ==
"EW90")
872 ROOT::Math::PxPyPzEVector momW = momTarget + momMiss;
875 const auto& photons = roe->getPhotons(maskName);
876 for (
auto& photon : photons) {
878 E_W_90 += photon->getECLClusterEnergy();
881 for (
auto& roeChargedParticle : roeChargedParticles) {
882 if (roeChargedParticle->isCopyOf(particle,
true))
885 for (
const ECLCluster& chargedCluster : roeChargedParticle->getTrack()->getRelationsWith<ECLCluster>()) {
890 if (iEnergy == iEnergy) {
908 if (arguments.size() != 1)
909 B2FATAL(
"Wrong number of arguments (1 required) for meta function KaonPionVariables");
912 auto requestedVariable = arguments[0];
913 auto func = [requestedVariable](
const Particle * particle) ->
double {
915 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
918 if ((requestedVariable !=
"HaveOpositeCharges") && (requestedVariable !=
"cosKaonPion"))
919 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are cosKaonPion or HaveOpositeCharges");
922 ROOT::Math::PxPyPzEVector momTargetSlowPion;
923 double chargeTargetSlowPion = 0;
924 if (SlowPionList.isValid())
926 double maximumProbSlowPion = 0;
927 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
928 Particle* pSlowPion = SlowPionList->getParticle(i);
929 if (!pSlowPion)
continue;
930 if (!pSlowPion->hasExtraInfo(
"isRightCategory(SlowPion)"))
continue;
932 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
933 if (probSlowPion > maximumProbSlowPion) {
934 maximumProbSlowPion = probSlowPion;
935 chargeTargetSlowPion = pSlowPion->getCharge();
943 double chargeTargetKaon = particle->getCharge();
944 if (requestedVariable ==
"HaveOpositeCharges")
946 if (chargeTargetKaon * chargeTargetSlowPion == -1)
950 else if (requestedVariable ==
"cosKaonPion")
953 if (momTargetKaon == momTargetKaon && momTargetSlowPion == momTargetSlowPion)
954 output = momTargetKaon.Vect().Unit().Dot(momTargetSlowPion.Vect().Unit());
964 if (arguments.size() != 1)
965 B2FATAL(
"Wrong number of arguments (1 required) for meta function FSCVariables");
968 auto requestedVariable = arguments[0];
969 auto func = [requestedVariable](
const Particle * particle) ->
double {
970 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
971 if (!FastParticleList.isValid())
return 0;
974 if ((requestedVariable !=
"pFastCMS") && (requestedVariable !=
"cosSlowFast") && (requestedVariable !=
"cosTPTOFast") && (requestedVariable !=
"SlowFastHaveOpositeCharges"))
975 B2FATAL(
"Wrong variable " << requestedVariable <<
" requested. The possibilities are pFastCMS, cosSlowFast, cosTPTOFast or SlowFastHaveOpositeCharges");
978 double maximumProbFastest = 0;
979 ROOT::Math::PxPyPzEVector momFastParticle;
980 Particle* TargetFastParticle =
nullptr;
981 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i)
983 Particle* particlei = FastParticleList->getParticle(i);
984 if (!particlei)
continue;
987 if (momParticlei != momParticlei)
continue;
989 double probFastest = momParticlei.P();
990 if (probFastest > maximumProbFastest) {
991 maximumProbFastest = probFastest;
992 TargetFastParticle = particlei;
993 momFastParticle = momParticlei;
998 if (!TargetFastParticle)
return 0;
1001 double output = 0.0;
1003 if (requestedVariable ==
"cosTPTOFast")
1004 output = cosTPTO(TargetFastParticle);
1007 if (momSlowPion == momSlowPion)
1009 if (requestedVariable ==
"cosSlowFast") {
1010 output = momSlowPion.Vect().Unit().Dot(momFastParticle.Vect().Unit());
1011 }
else if (requestedVariable ==
"SlowFastHaveOpositeCharges") {
1012 if (particle->getCharge()*TargetFastParticle->getCharge() == -1) {
1016 output = momFastParticle.P();
1029 constexpr std::array<int, 18> charmMesons = {
1030 411 , 413 , 415, 421 , 423 , 425, 431, 433, 435,
1031 10411 , 10413 , 10421 , 10423 , 10431 , 10433,
1032 20413 , 20423 , 20433,
1035 constexpr std::array<int, 22> charmBaryons = {
1036 4112 , 4114 , 4122 , 4132 ,
1037 4212 , 4214 , 4222 , 4224 , 4232 ,
1038 4312 , 4314 , 4322 , 4324 , 4332 , 4334 ,
1039 4412 , 4414 , 4422 , 4424 , 4432 , 4434 ,
1044 constexpr std::array<int, 80> qqbarMesons = {
1046 111 , 113 , 115 , 117 , 119 ,
1047 10111 , 10113 , 10115 ,
1050 9000111 , 9000113 , 9010113 , 9040113 ,
1053 200111 , 9020113 , 9030113 , 100115 , 9000115 ,
1057 221 , 223 , 225 , 227 , 229 ,
1058 331 , 333 , 335 , 337 ,
1059 10223 , 10225 , 10331 , 10333 ,
1060 20223 , 20333 , 30223 ,
1062 9000221 , 9010221 , 9020221 , 9030221 ,
1068 9000223 , 9000225 , 9000229 ,
1069 9010223 , 9010225 , 9020225 , 9030225 ,
1070 9040221 , 9040225 , 9050221 ,
1071 9060221 , 9070221 , 9070225 ,
1079 10441 , 10443 , 20443 , 30443 ,
1081 9000443 , 9010443 , 9020443 ,
1085 constexpr std::array<int, 63> flavorConservingMesons = {
1087 213 , 215 , 217 , 219 ,
1088 10211 , 10213 , 10215 ,
1091 9000211 , 9000213 , 9010213 ,
1095 9010217 , 9020213 , 9030213 , 9040213 ,
1100 313 , 315 , 317 , 319 ,
1101 323 , 325 , 327 , 329 ,
1102 10311 , 10313 , 10315 ,
1103 10321 , 10323 , 10325 ,
1106 30313 , 30323 , 30343 ,
1111 9000311 , 9000313 , 9000315 ,
1112 9000321 , 9000323 , 9000325 ,
1121 const std::vector<std::string> availableForIsRightTrack = {
"Electron",
1122 "IntermediateElectron",
1126 "IntermediateKinLepton",
1134 const std::vector<std::string> availableForIsRightCategory = {
"Electron",
1135 "IntermediateElectron",
1139 "IntermediateKinLepton",
1154 if (arguments.size() != 1) {
1155 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightTrack");
1160 unsigned index = std::find(availableForIsRightTrack.begin(), availableForIsRightTrack.end(), particleName)
1161 - availableForIsRightTrack.begin();
1162 if (index == availableForIsRightTrack.size()) {
1163 B2FATAL(
"isRightTrack: Not available category " << particleName <<
1164 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron and Lambda");
1167 auto func = [index](
const Particle * particle) ->
int {
1169 const MCParticle* mcParticle = particle->getMCParticle();
1170 if (!mcParticle)
return -2;
1172 int mcPDG = abs(mcParticle->getPDG());
1175 std::vector<int> mothersPDG;
1176 std::vector<const MCParticle*> mothersPointers;
1178 const MCParticle* mcMother = mcParticle->getMother();
1181 mothersPDG.push_back(abs(mcMother->getPDG()));
1182 mothersPointers.push_back(mcMother);
1183 if (abs(mcMother->getPDG()) == 511)
break;
1184 mcMother = mcMother->getMother();
1187 if (mothersPDG.size() == 0)
return -2;
1190 if (index == 10)
return 1;
1194 bool isCharmedMesonInChain =
false;
1195 for (
auto& iMCMotherPDG : mothersPDG)
1197 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1198 isCharmedMesonInChain =
true;
1205 bool isCharmedBaryonInChain =
false;
1206 for (
auto& iMCMotherPDG : mothersPDG)
1208 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1209 isCharmedBaryonInChain =
true;
1216 bool isQQbarMesonInChain =
false;
1217 for (
auto& iMCMotherPDG : mothersPDG)
1219 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1220 isQQbarMesonInChain =
true;
1227 bool isB0DaughterConservingFlavor =
false;
1228 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1229 mothersPDG.rbegin()[1]) != flavorConservingMesons.end())
1231 isB0DaughterConservingFlavor =
true;
1236 bool isHadronSingleTauDaughter =
false;
1237 if (mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1239 int numberOfChargedDaughters = 0;
1240 for (
auto& tauDaughter : mothersPointers.rbegin()[1]->getDaughters()) {
1241 if (tauDaughter->getCharge() != 0)
1242 numberOfChargedDaughters += 1;
1244 if (numberOfChargedDaughters == 1)
1245 isHadronSingleTauDaughter =
true;
1252 }
else if (index == 1
1253 && mcPDG ==
Const::electron.getPDGCode() && mothersPDG.size() > 1 && isQQbarMesonInChain ==
false)
1256 }
else if (index == 2
1257 && mcPDG ==
Const::muon.getPDGCode() && mothersPDG[0] == 511)
1260 }
else if (index == 3
1261 && mcPDG ==
Const::muon.getPDGCode() && mothersPDG.size() > 1 && isQQbarMesonInChain ==
false)
1264 }
else if (index == 4
1268 }
else if (index == 5
1270 && isQQbarMesonInChain ==
false)
1273 }
else if (index == 6
1274 && mcPDG ==
Const::kaon.getPDGCode() && isQQbarMesonInChain ==
false
1275 && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1278 }
else if (index == 7
1279 && mcPDG ==
Const::pion.getPDGCode() && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1282 }
else if (index == 8
1284 && isQQbarMesonInChain ==
false
1285 && (mothersPDG[0] == 511
1286 || (mothersPDG.rbegin()[0] == 511 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1289 }
else if (index == 9
1290 && mcPDG ==
Const::Lambda.getPDGCode() && isCharmedBaryonInChain ==
true)
1303 if (arguments.size() != 1) {
1304 B2FATAL(
"Wrong number of arguments (1 required) for meta function isRightCategory");
1309 unsigned index = find(availableForIsRightCategory.begin(), availableForIsRightCategory.end(), particleName)
1310 - availableForIsRightCategory.begin();
1311 if (index == availableForIsRightCategory.size()) {
1312 B2FATAL(
"isRightCategory: Not available category " << particleName <<
1313 ". The possibilities are Electron, IntermediateElectron, Muon, IntermediateMuon, KinLepton, IntermediateKinLepton, Kaon, SlowPion, FastHadron, KaonPion, MaximumPstar, FSC and Lambda");
1316 auto func = [index](
const Particle * particle) ->
int {
1318 Particle* nullParticle =
nullptr;
1319 double qTarget = particle->getCharge();
1320 double qMC = Variable::isRestOfEventB0Flavor(nullParticle);
1322 const MCParticle* mcParticle = particle->getMCParticle();
1323 if (!mcParticle)
return -2;
1325 int mcPDG = abs(mcParticle->getPDG());
1328 std::vector<int> mothersPDG;
1329 std::vector<const MCParticle*> mothersPointers;
1331 const MCParticle* mcMother = mcParticle->getMother();
1334 mothersPDG.push_back(abs(mcMother->getPDG()));
1335 mothersPointers.push_back(mcMother);
1336 if (abs(mcMother->getPDG()) == 511)
break;
1337 mcMother = mcMother->getMother();
1340 if (mothersPDG.size() == 0)
return -2;
1342 if (index == 13)
return 1;
1346 bool isCharmedMesonInChain =
false;
1347 for (
auto& iMCMotherPDG : mothersPDG)
1349 if (std::find(charmMesons.begin(), charmMesons.end(), iMCMotherPDG) != charmMesons.end()) {
1350 isCharmedMesonInChain =
true;
1357 bool isCharmedBaryonInChain =
false;
1358 for (
auto& iMCMotherPDG : mothersPDG)
1360 if (std::find(charmBaryons.begin(), charmBaryons.end(), iMCMotherPDG) != charmBaryons.end()) {
1361 isCharmedBaryonInChain =
true;
1368 bool isQQbarMesonInChain =
false;
1369 for (
auto& iMCMotherPDG : mothersPDG)
1371 if (std::find(qqbarMesons.begin(), qqbarMesons.end(), iMCMotherPDG) != qqbarMesons.end()) {
1372 isQQbarMesonInChain =
true;
1379 bool isB0DaughterConservingFlavor =
false;
1380 if (mothersPDG.size() > 1)
1382 if (std::find(flavorConservingMesons.begin(), flavorConservingMesons.end(),
1383 mothersPDG.rbegin()[1]) != flavorConservingMesons.end()) {
1384 isB0DaughterConservingFlavor =
true;
1390 bool isHadronSingleTauDaughter =
false;
1391 if (mothersPDG.size() > 1 && mothersPDG.rbegin()[1] == 15)
1393 int numberOfChargedDaughters = 0;
1394 for (
auto& tauDaughter : mothersPointers.rbegin()[1]->getDaughters()) {
1395 if (tauDaughter->getCharge() != 0)
1396 numberOfChargedDaughters += 1;
1398 if (numberOfChargedDaughters == 1)
1399 isHadronSingleTauDaughter =
true;
1403 bool haveKaonPionSameMother =
false;
1406 const MCParticle* mcSlowPionMother =
nullptr;
1407 StoreObjPtr<ParticleList> SlowPionList(
"pi+:inRoe");
1408 Particle* targetSlowPion =
nullptr;
1409 if (SlowPionList.isValid()) {
1410 double mcProbSlowPion = 0;
1411 for (
unsigned int i = 0; i < SlowPionList->getListSize(); ++i) {
1412 Particle* pSlowPion = SlowPionList->getParticle(i);
1413 if (!pSlowPion)
continue;
1414 if (pSlowPion->hasExtraInfo(
"isRightCategory(SlowPion)")) {
1415 double probSlowPion = pSlowPion->getExtraInfo(
"isRightCategory(SlowPion)");
1416 if (probSlowPion > mcProbSlowPion) {
1417 mcProbSlowPion = probSlowPion;
1418 targetSlowPion = pSlowPion;
1422 if (targetSlowPion !=
nullptr) {
1423 const MCParticle* mcSlowPion = targetSlowPion ->getMCParticle();
1425 if (mcSlowPion !=
nullptr && mcSlowPion->getMother() !=
nullptr
1426 && abs(mcSlowPion->getPDG()) ==
Const::pion.
getPDGCode() && abs(mcSlowPion->getMother()->getPDG()) == 413) {
1427 mcSlowPionMother = mcSlowPion->getMother();
1432 if (std::find(mothersPointers.begin(), mothersPointers.end(), mcSlowPionMother) != mothersPointers.end())
1433 haveKaonPionSameMother =
true;
1438 int FastParticlePDGMother = 0;
1442 StoreObjPtr<ParticleList> FastParticleList(
"pi+:inRoe");
1443 Particle* targetFastParticle =
nullptr;
1444 if (FastParticleList.isValid()) {
1445 double mcProbFastest = 0;
1446 for (
unsigned int i = 0; i < FastParticleList->getListSize(); ++i) {
1447 Particle* particlei = FastParticleList->getParticle(i);
1448 if (!particlei)
continue;
1451 if (momParticlei == momParticlei) {
1452 double probFastest = momParticlei.P();
1453 if (probFastest > mcProbFastest) {
1454 mcProbFastest = probFastest;
1455 targetFastParticle = particlei;
1459 if (targetFastParticle !=
nullptr) {
1460 const MCParticle* mcFastParticle = targetFastParticle ->getMCParticle();
1462 if (mcFastParticle !=
nullptr && mcFastParticle->getMother() !=
nullptr) {
1463 FastParticlePDGMother = abs(mcFastParticle->getMother()->getPDG());
1464 qFSC = mcFastParticle->getCharge();
1472 && qTarget == qMC && mcPDG ==
Const::electron.getPDGCode() && mothersPDG[0] == 511)
1475 }
else if (index == 1
1476 && qTarget != qMC && mcPDG ==
Const::electron.getPDGCode() && mothersPDG.size() > 1
1477 && isQQbarMesonInChain ==
false)
1480 }
else if (index == 2
1481 && qTarget == qMC && mcPDG ==
Const::muon.getPDGCode() && mothersPDG[0] == 511)
1484 }
else if (index == 3
1485 && qTarget != qMC && mcPDG ==
Const::muon.getPDGCode() && mothersPDG.size() > 1
1486 && isQQbarMesonInChain ==
false)
1489 }
else if (index == 4
1494 }
else if (index == 5
1496 && mothersPDG.size() > 1 && isQQbarMesonInChain ==
false)
1499 }
else if (index == 6
1500 && qTarget == qMC && mcPDG ==
Const::kaon.getPDGCode() && isQQbarMesonInChain ==
false
1501 && (isCharmedMesonInChain ==
true || isCharmedBaryonInChain ==
true))
1504 }
else if (index == 7
1505 && qTarget != qMC && mcPDG ==
Const::pion.getPDGCode()
1506 && mothersPDG.size() > 1 && mothersPDG[0] == 413 && mothersPDG[1] == 511)
1509 }
else if (index == 8
1511 && isQQbarMesonInChain ==
false
1512 && (mothersPDG[0] == 511 || (mothersPDG.rbegin()[0] == 511
1513 && (isB0DaughterConservingFlavor ==
true || isHadronSingleTauDaughter ==
true))))
1516 }
else if (index == 9
1517 && qTarget == qMC && mcPDG ==
Const::kaon.getPDGCode() && haveKaonPionSameMother ==
true)
1520 }
else if (index == 10 && qTarget == qMC)
1523 }
else if (index == 11
1524 && qTarget != qMC && mothersPDG.size() > 1 && qFSC == qMC
1525 && mcPDG ==
Const::pion.
getPDGCode() && FastParticlePDGMother == 511 && isQQbarMesonInChain ==
false)
1528 }
else if (index == 12
1529 && (particle->getPDGCode() / abs(particle->getPDGCode())) != qMC
1544 if (arguments.size() != 2) {
1545 B2FATAL(
"Wrong number of arguments (2 required) for meta function hasHighestProbInCat");
1548 auto particleListName = arguments[0];
1549 auto extraInfoName = arguments[1];
1551 bool isAvailable =
false;
1552 for (
const auto& name : availableForIsRightTrack) {
1553 if (extraInfoName ==
"isRightTrack(" + name +
")") {
1558 for (
const auto& name : availableForIsRightCategory) {
1559 if (extraInfoName ==
"isRightCategory(" + name +
")") {
1564 if (extraInfoName ==
"isRightTrack(MaximumPstar)")
1569 string strAvailableForIsRightTrack;
1570 for (
const auto& name : availableForIsRightTrack)
1571 strAvailableForIsRightTrack += name +
" ";
1572 string strAvailableForIsRightCategory;
1573 for (
const auto& name : availableForIsRightCategory)
1574 strAvailableForIsRightCategory += name +
" ";
1576 B2FATAL(
"hasHighestProbInCat: Not available category" << extraInfoName <<
1577 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1578 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1581 auto func = [particleListName, extraInfoName](
const Particle * particle) ->
bool {
1582 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1583 if (!ListOfParticles.isValid())
return 0;
1585 double maximumProb = 0;
1586 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1588 const Particle* particlei = ListOfParticles->getParticle(i);
1589 if (!particlei)
continue;
1592 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
1594 if (momParticlei == momParticlei) {
1595 prob = momParticlei.P();
1598 if (particlei->hasExtraInfo(extraInfoName)) {
1599 prob = particlei->getExtraInfo(extraInfoName);
1602 if (prob > maximumProb) {
1608 bool output =
false;
1609 if ((extraInfoName ==
"isRightTrack(MaximumPstar)") && (
PCmsLabTransform::labToCms(particle->get4Vector()).P() == maximumProb))
1612 }
else if (extraInfoName !=
"isRightTrack(MaximumPstar)" && particle->hasExtraInfo(extraInfoName))
1614 if (particle->getExtraInfo(extraInfoName) == maximumProb) output =
true;
1624 if (arguments.size() != 2) {
1625 B2FATAL(
"Wrong number of arguments (2 required) for meta function HighestProbInCat");
1628 auto particleListName = arguments[0];
1629 auto extraInfoName = arguments[1];
1631 bool isAvailable =
false;
1632 for (
const auto& name : availableForIsRightTrack) {
1633 if (extraInfoName ==
"isRightTrack(" + name +
")") {
1638 for (
const auto& name : availableForIsRightCategory) {
1639 if (extraInfoName ==
"isRightCategory(" + name +
")") {
1644 if (extraInfoName ==
"isRightTrack(MaximumPstar)")
1649 string strAvailableForIsRightTrack;
1650 for (
const auto& name : availableForIsRightTrack)
1651 strAvailableForIsRightTrack += name +
" ";
1652 string strAvailableForIsRightCategory;
1653 for (
const auto& name : availableForIsRightCategory)
1654 strAvailableForIsRightCategory += name +
" ";
1656 B2FATAL(
"HighestProbInCat: Not available category" << extraInfoName <<
1657 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1658 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1661 auto func = [particleListName, extraInfoName](
const Particle*) ->
double {
1662 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1663 if (!ListOfParticles.isValid())
return 0;
1665 double maximumProb = 0;
1666 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1668 const Particle* particlei = ListOfParticles->getParticle(i);
1669 if (!particlei)
continue;
1672 if (extraInfoName ==
"isRightTrack(MaximumPstar)") {
1674 if (momParticlei == momParticlei) {
1675 prob = momParticlei.P();
1678 if (particlei->hasExtraInfo(extraInfoName)) {
1679 prob = particlei->getExtraInfo(extraInfoName);
1682 maximumProb = max(maximumProb, prob);
1692 const std::vector<std::string> availableExtraInfos = {
"isRightTrack(Electron)",
1693 "isRightTrack(IntermediateElectron)",
1694 "isRightTrack(Muon)",
1695 "isRightTrack(IntermediateMuon)",
1696 "isRightTrack(KinLepton)",
1697 "isRightTrack(IntermediateKinLepton)",
1698 "isRightTrack(Kaon)",
1699 "isRightTrack(SlowPion)",
1700 "isRightTrack(FastHadron)",
1701 "isRightTrack(MaximumPstar)",
1702 "isRightTrack(Lambda)",
1703 "isRightCategory(Electron)",
1704 "isRightCategory(IntermediateElectron)",
1705 "isRightCategory(Muon)",
1706 "isRightCategory(IntermediateMuon)",
1707 "isRightCategory(KinLepton)",
1708 "isRightCategory(IntermediateKinLepton)",
1709 "isRightCategory(Kaon)",
1710 "isRightCategory(SlowPion)",
1711 "isRightCategory(FastHadron)",
1712 "isRightCategory(MaximumPstar)",
1713 "isRightCategory(Lambda)",
1714 "isRightCategory(KaonPion)",
1715 "isRightCategory(FSC)",
1720 if (arguments.size() != 3) {
1721 B2FATAL(
"Wrong number of arguments (3 required) for meta function QpOf");
1724 auto particleListName = arguments[0];
1725 auto outputExtraInfo = arguments[1];
1726 auto rankingExtraInfo = arguments[2];
1728 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1729 rankingExtraInfo) - availableExtraInfos.begin();
1730 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1731 outputExtraInfo) - availableExtraInfos.begin();
1733 if (indexRanking == availableExtraInfos.size() or indexOutput == availableExtraInfos.size()) {
1734 string strAvailableForIsRightTrack;
1735 for (
const auto& name : availableForIsRightTrack)
1736 strAvailableForIsRightTrack += name +
" ";
1737 string strAvailableForIsRightCategory;
1738 for (
const auto& name : availableForIsRightCategory)
1739 strAvailableForIsRightCategory += name +
" ";
1741 B2FATAL(
"QpOf: Not available category " << rankingExtraInfo <<
1742 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1743 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1746 auto func = [particleListName, indexOutput, indexRanking](
const Particle*) ->
double {
1747 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1748 if (!ListOfParticles.isValid())
return 0;
1750 Particle* target =
nullptr;
1751 double maximumTargetProb = 0;
1752 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1754 Particle* particlei = ListOfParticles->getParticle(i);
1755 if (!particlei)
continue;
1757 double target_prob = 0;
1758 if (indexRanking == 9 || indexRanking == 20) {
1760 if (momParticlei == momParticlei) {
1761 target_prob = momParticlei.P();
1764 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
1765 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
1769 if (target_prob > maximumTargetProb) {
1770 maximumTargetProb = target_prob;
1776 if (!target)
return 0;
1780 if (indexRanking == 10 || indexRanking == 21)
1782 qTarget = (-1) * target->getPDGCode() / abs(target->getPDGCode());
1784 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1785 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18)
1787 qTarget = (-1) * target->getCharge();
1790 qTarget = target->getCharge();
1794 double prob = target->getExtraInfo(availableExtraInfos[indexOutput]);
1798 return qTarget * prob;
1805 if (arguments.size() != 3) {
1806 B2FATAL(
"Wrong number of arguments (3 required) for meta function weightedQpOf");
1811 auto particleListName = arguments[0];
1812 auto outputExtraInfo = arguments[1];
1813 auto rankingExtraInfo = arguments[2];
1816 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1817 rankingExtraInfo) - availableExtraInfos.begin();
1818 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1819 outputExtraInfo) - availableExtraInfos.begin();
1822 if (indexRanking == availableExtraInfos.size() or indexOutput == availableExtraInfos.size()) {
1823 string strAvailableForIsRightTrack;
1824 for (
const auto& name : availableForIsRightTrack)
1825 strAvailableForIsRightTrack += name +
" ";
1826 string strAvailableForIsRightCategory;
1827 for (
const auto& name : availableForIsRightCategory)
1828 strAvailableForIsRightCategory += name +
" ";
1830 B2FATAL(
"weightedQpOf: Not available category " << rankingExtraInfo <<
1831 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1832 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1836 auto func = [particleListName, indexOutput, indexRanking, rankingExtraInfo](
const Particle*) ->
double {
1838 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1839 if (!ListOfParticles)
return 0;
1840 if (ListOfParticles->getListSize() == 0)
return 0;
1843 auto compare = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1846 if (part1->hasExtraInfo(rankingExtraInfo)) info1 = part1->getExtraInfo(rankingExtraInfo);
1847 if (part2->hasExtraInfo(rankingExtraInfo)) info2 = part2->getExtraInfo(rankingExtraInfo);
1848 return (info1 > info2);
1851 auto compareMomentum = [rankingExtraInfo](
const Particle * part1,
const Particle * part2)->
bool {
1854 return (info1 > info2);
1857 std::vector<const Particle*> ParticleVector(ListOfParticles->getListSize());
1858 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1860 ParticleVector[i] = ListOfParticles->getParticle(i);
1863 if (indexRanking == 9 || indexRanking == 20)
1864 std::sort(ParticleVector.begin(), ParticleVector.end(), compareMomentum);
1866 std::sort(ParticleVector.begin(), ParticleVector.end(), compare);
1869 double final_value = 0.0;
1870 if (ParticleVector.size() != 0) final_value = 1.0;
1873 int Limit = min(3,
int(ParticleVector.size()));
1876 for (
int i = 0; i < Limit; ++i)
1878 if (ParticleVector[i]->hasExtraInfo(availableExtraInfos[indexOutput])) {
1879 double flavor = 0.0;
1880 if (indexRanking == 10 || indexRanking == 21) {
1881 flavor = - copysign(1, ParticleVector[i]->getPDGCode());
1883 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1884 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18) {
1885 flavor = - ParticleVector[i]->getCharge();
1887 flavor = + ParticleVector[i]->getCharge();
1890 double p = ParticleVector[i]->getExtraInfo(availableExtraInfos[indexOutput]);
1893 double qp = (flavor * p);
1898 final_value = (val1 - val2) / (val1 + val2);
1908 if (arguments.size() != 3) {
1909 B2FATAL(
"Wrong number of arguments (3 required) for meta function QpTrack");
1912 auto particleListName = arguments[0];
1913 auto outputExtraInfo = arguments[1];
1914 auto rankingExtraInfo = arguments[2];
1916 unsigned indexRanking = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1917 rankingExtraInfo) - availableExtraInfos.begin();
1918 unsigned indexOutput = find(availableExtraInfos.begin(), availableExtraInfos.end(),
1919 outputExtraInfo) - availableExtraInfos.begin();
1921 if (indexRanking == availableExtraInfos.size() or indexOutput == availableExtraInfos.size()) {
1922 string strAvailableForIsRightTrack;
1923 for (
const auto& name : availableForIsRightTrack)
1924 strAvailableForIsRightTrack += name +
" ";
1925 string strAvailableForIsRightCategory;
1926 for (
const auto& name : availableForIsRightCategory)
1927 strAvailableForIsRightCategory += name +
" ";
1929 B2FATAL(
"QpTrack: Not available category " << rankingExtraInfo <<
1930 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
1931 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
1934 auto func = [particleListName, indexOutput, indexRanking](
const Particle * particle) ->
double {
1935 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
1936 if (!ListOfParticles.isValid())
return 0;
1938 const auto mdstSource = particle->getMdstSource();
1940 Particle* target =
nullptr;
1941 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
1943 Particle* particlei = ListOfParticles->getParticle(i);
1947 if (particlei->getMdstSource() == mdstSource) {
1954 if (!target)
return 0;
1958 if (indexRanking == 10 || indexRanking == 21)
1960 qTarget = (-1) * target->getPDGCode() / abs(target->getPDGCode());
1962 }
else if (indexRanking == 1 || indexRanking == 3 || indexRanking == 5 || indexRanking == 7 ||
1963 indexRanking == 12 || indexRanking == 14 || indexRanking == 16 || indexRanking == 18)
1965 qTarget = (-1) * target->getCharge();
1968 qTarget = target->getCharge();
1972 double prob = target->getExtraInfo(availableExtraInfos[indexOutput]);
1974 return qTarget * prob;
1982 if (arguments.size() != 3)
1983 B2FATAL(
"Wrong number of arguments (3 required) for meta function variableOfTarget");
1985 std::string particleListName = arguments[0];
1986 std::string inputVariable = arguments[1];
1987 std::string rankingExtraInfo = arguments[2];
1989 int indexRanking = -1;
1991 for (
unsigned i = 0; i < availableExtraInfos.size(); ++i) {
1992 if (rankingExtraInfo == availableExtraInfos[i]) {indexRanking = i;
break;}
1995 if (indexRanking == -1) {
1996 string strAvailableForIsRightTrack;
1997 for (
const auto& name : availableForIsRightTrack)
1998 strAvailableForIsRightTrack += name +
" ";
1999 string strAvailableForIsRightCategory;
2000 for (
const auto& name : availableForIsRightCategory)
2001 strAvailableForIsRightCategory += name +
" ";
2003 B2FATAL(
"variableOfTarget: Not available category " << rankingExtraInfo <<
2004 ". The possibilities for isRightTrack() are " << endl << strAvailableForIsRightTrack <<
" MaximumPstar" << endl <<
2005 "The possibilities for isRightCategory() are " << endl << strAvailableForIsRightCategory);
2009 auto func = [particleListName, var, indexRanking](
const Particle*) ->
double {
2010 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
2013 Particle* target =
nullptr;
2015 double maximumTargetProb = 0;
2016 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
2018 Particle* particlei = ListOfParticles->getParticle(i);
2019 if (!particlei)
continue;
2021 double target_prob = 0;
2022 if (indexRanking == 9 || indexRanking == 20) {
2024 if (momParticlei == momParticlei) {
2025 target_prob = momParticlei.P();
2028 if (particlei->hasExtraInfo(availableExtraInfos[indexRanking])) {
2029 target_prob = particlei->getExtraInfo(availableExtraInfos[indexRanking]);
2032 if (target_prob > maximumTargetProb) {
2033 maximumTargetProb = target_prob;
2041 if (std::holds_alternative<double>(var->function(target)))
2043 return std::get<double>(var->function(target));
2044 }
else if (std::holds_alternative<int>(var->function(target)))
2046 return std::get<int>(var->function(target));
2047 }
else if (std::holds_alternative<bool>(var->function(target)))
2049 return std::get<bool>(var->function(target));
2057 if (arguments.size() != 1) {
2058 B2FATAL(
"Wrong number of arguments (1 required) for meta function hasTrueTarget");
2061 auto categoryName = arguments[0];
2063 bool isAvailable =
false;
2064 for (
const auto& name : availableForIsRightCategory) {
2065 if (categoryName == name) {
2070 if (categoryName ==
"mcAssociated")
2071 isAvailable =
false;
2074 string strAvailableForIsRightCategory;
2075 for (
const auto& name : availableForIsRightCategory) {
2076 if (name ==
"mcAssociated")
continue;
2077 strAvailableForIsRightCategory += name +
" ";
2079 B2FATAL(
"hasTrueTarget: Not available category" << categoryName <<
2080 ". The possibilities for the category name are " << endl << strAvailableForIsRightCategory);
2083 auto func = [categoryName](
const Particle*) ->
double {
2084 std::string particleListName;
2085 std::string trackTargetName = categoryName;
2087 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron") particleListName =
"e+:inRoe";
2088 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton") particleListName =
"mu+:inRoe";
2089 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
2090 else if (categoryName ==
"Lambda") particleListName =
"Lambda0:inRoe";
2091 else particleListName =
"pi+:inRoe";
2093 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
2095 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
2100 bool particlesHaveMCAssociated =
false;
2102 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
2104 Particle* iParticle = ListOfParticles->getParticle(i);
2105 if (!iParticle)
continue;
2107 if (categoryName ==
"MaximumPstar") {
2109 hasHighestProbInCat({
"pi+:inRoe",
"isRightTrack(MaximumPstar)"});
2110 bool targetFlag = std::get<bool>(selectionFunction(iParticle));
2112 particlesHaveMCAssociated =
true;
2116 int targetFlag = std::get<int>(manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->function(iParticle));
2117 if (targetFlag != -2) particlesHaveMCAssociated =
true;
2118 if (targetFlag == 1) ++nTargets;
2123 return (nTargets > 0);
2130 if (arguments.size() != 1) {
2131 B2FATAL(
"Wrong number of arguments (1 required) for meta function isTrueCategory");
2133 auto categoryName = arguments[0];
2135 bool isAvailable =
false;
2136 for (
const auto& name : availableForIsRightCategory) {
2137 if (categoryName == name) {
2142 if (categoryName ==
"mcAssociated")
2143 isAvailable =
false;
2146 string strAvailableForIsRightCategory;
2147 for (
const auto& name : availableForIsRightCategory) {
2148 if (name ==
"mcAssociated")
continue;
2149 strAvailableForIsRightCategory += name +
" ";
2151 B2FATAL(
"isTrueCategory: Not available category" << categoryName <<
2152 ". The possibilities for the category name are " << endl << strAvailableForIsRightCategory);
2155 auto func = [categoryName](
const Particle*) ->
double {
2156 std::string particleListName;
2157 std::string trackTargetName = categoryName;
2159 if (categoryName ==
"Electron" || categoryName ==
"IntermediateElectron") particleListName =
"e+:inRoe";
2160 else if (categoryName ==
"Muon" || categoryName ==
"IntermediateMuon" || categoryName ==
"KinLepton" || categoryName ==
"IntermediateKinLepton") particleListName =
"mu+:inRoe";
2161 else if (categoryName ==
"Kaon" || categoryName ==
"KaonPion") {particleListName =
"K+:inRoe"; trackTargetName =
"Kaon";}
2162 else if (categoryName ==
"Lambda") particleListName =
"Lambda0:inRoe";
2163 else particleListName =
"pi+:inRoe";
2165 if (categoryName ==
"FSC") trackTargetName =
"SlowPion";
2167 StoreObjPtr<ParticleList> ListOfParticles(particleListName);
2170 std::vector<Particle*> targetParticles;
2171 std::vector<Particle*> targetParticlesCategory;
2176 for (
unsigned int i = 0; i < ListOfParticles->getListSize(); ++i)
2178 Particle* iParticle = ListOfParticles->getParticle(i);
2179 if (!iParticle)
continue;
2181 if (categoryName ==
"MaximumPstar") {
2183 hasHighestProbInCat({
"pi+:inRoe",
"isRightTrack(MaximumPstar)"});
2184 if (std::get<bool>(selectionFunction(iParticle)))
2185 targetParticles.push_back(iParticle);
2186 }
else if (std::get<int>(manager.getVariable(
"isRightTrack(" + trackTargetName +
")")->function(iParticle))) {
2187 targetParticles.push_back(iParticle);
2191 for (
const auto& targetParticle : targetParticles)
2193 int isTargetOfRightCategory = std::get<int>(manager.getVariable(
"isRightCategory(" + categoryName +
")")->function(
2195 if (isTargetOfRightCategory == 1) {
2197 targetParticlesCategory.push_back(targetParticle);
2198 }
else if (isTargetOfRightCategory == -2 && output != 1)
2209 if (arguments.size() != 1)
2210 B2FATAL(
"Wrong number of arguments for meta function qrOutput");
2212 std::string combinerMethod = arguments[0];
2213 auto func = [combinerMethod](
const Particle * particle) ->
double {
2216 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2218 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2219 output = flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined();
2228 if (arguments.size() != 1)
2229 B2FATAL(
"Wrong number of arguments for meta function qOutput");
2231 std::string combinerMethod = arguments[0];
2232 auto func = [combinerMethod](
const Particle * particle) ->
double {
2235 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2237 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2238 output = TMath::Sign(1, flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
2247 if (arguments.size() != 1)
2248 B2FATAL(
"Wrong number of arguments for meta function rBinBelle");
2251 std::string combinerMethod = arguments[0];
2252 auto func = [combinerMethod](
const Particle * particle) ->
int {
2255 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2257 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2259 double r = std::abs(flavorTaggerInfo->getMethodMap(combinerMethod)->getQrCombined());
2260 if (r < 0.1) output = 0;
2261 if (r > 0.1 && r < 0.25) output = 1;
2262 if (r > 0.25 && r < 0.5) output = 2;
2263 if (r > 0.5 && r < 0.625) output = 3;
2264 if (r > 0.625 && r < 0.75) output = 4;
2265 if (r > 0.75 && r < 0.875) output = 5;
2266 if (r > 0.875 && r < 1.10) output = 6;
2276 if (arguments.size() != 1)
2277 B2FATAL(
"Wrong number of arguments for meta function qpCategory");
2279 std::string categoryName = arguments[0];
2280 auto func = [categoryName](
const Particle * particle) ->
double {
2283 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2285 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2287 std::map<std::string, float> iQpCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getQpCategory();
2288 if (iQpCategories.find(categoryName) != iQpCategories.end()) output = iQpCategories.at(categoryName);
2289 else if (iQpCategories.size() != 0) B2FATAL(
"qpCategory: Category with name " << categoryName
2290 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2299 if (arguments.size() != 1)
2300 B2FATAL(
"Wrong number of arguments for meta function isTrueFTCategory");
2302 std::string categoryName = arguments[0];
2303 auto func = [categoryName](
const Particle * particle) ->
double {
2306 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2308 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2310 std::map<std::string, float> iIsTrueCategories = flavorTaggerInfo->getMethodMap(
"FBDT")->getIsTrueCategory();
2311 if (iIsTrueCategories.find(categoryName) != iIsTrueCategories.end()) output = iIsTrueCategories.at(categoryName);
2312 else if (iIsTrueCategories.size() != 0) B2FATAL(
"isTrueFTCategory: Category with name " << categoryName
2313 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2323 if (arguments.size() != 1)
2324 B2FATAL(
"Wrong number of arguments for meta function hasTrueTargets");
2326 std::string categoryName = arguments[0];
2327 auto func = [categoryName](
const Particle * particle) ->
double {
2330 auto* flavorTaggerInfo = particle->getRelatedTo<FlavorTaggerInfo>();
2332 if (flavorTaggerInfo && flavorTaggerInfo->getUseModeFlavorTagger() ==
"Expert")
2334 std::map<std::string, float> iHasTrueTargets = flavorTaggerInfo->getMethodMap(
"FBDT")->getHasTrueTarget();
2335 if (iHasTrueTargets.find(categoryName) != iHasTrueTargets.end()) output = iHasTrueTargets.at(categoryName);
2336 else if (iHasTrueTargets.size() != 0) B2FATAL(
"hasTrueTargets: Category with name " << categoryName
2337 <<
" not found. Check the official category names or if this category is included in the flavor tagger categories list.");
2345 VARIABLE_GROUP(
"Flavor Tagger Expert Variables");
2347 REGISTER_VARIABLE(
"pMissTag", momentumMissingTagSide, R
"DOC(
2348[Expert] Calculates the missing momentum for a given particle on the tag side.
2351 REGISTER_METAVARIABLE("pMissTag(maskName)", momentumMissingTagSideWithMask,
2352 "[Expert] Calculates the missing momentum for a given particle on the tag side. The unit of the missing momentum is ``GeV/c`` ",
2353 Manager::VariableDataType::c_double);
2354 REGISTER_VARIABLE("cosTPTO" , cosTPTO, R"DOC(
2355[Expert] Returns cosine of angle between thrust axis of given particle and thrust axis of ROE.
2358 REGISTER_METAVARIABLE("cosTPTO(maskName)", cosTPTOWithMask,
2359 "[Expert] Returns cosine of angle between thrust axis of given particle and thrust axis of ROE.",
2360 Manager::VariableDataType::c_double);
2361 REGISTER_VARIABLE(
"lambdaFlavor", lambdaFlavor,
2362 "[Expert] Returns 1.0 if particle is ``Lambda0``, -1.0 in case of ``anti-Lambda0``, 0.0 otherwise.");
2363 REGISTER_VARIABLE(
"isLambda", isLambda,
"[Expert] Returns 1.0 if particle is truth-matched to ``Lambda0``, 0.0 otherwise.");
2364 REGISTER_VARIABLE(
"lambdaZError", lambdaZError,
"[Expert] Returns the variance of the z-component of the decay vertex.\n\n",
":math:`\\text{cm}^2`");
2365 REGISTER_VARIABLE(
"momentumOfSecondDaughter", momentumOfSecondDaughter,
2366 "[Expert] Returns the momentum of second daughter if exists, 0. otherwise.\n\n",
"GeV/c");
2367 REGISTER_VARIABLE(
"momentumOfSecondDaughterCMS", momentumOfSecondDaughterCMS,
2368 "[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");
2369 REGISTER_VARIABLE(
"chargeTimesKaonLiklihood", chargeTimesKaonLiklihood,
2370 "[Expert] Returns ``q*(highest PID_Likelihood for Kaons)``, 0. otherwise.");
2371 REGISTER_VARIABLE(
"ptTracksRoe", transverseMomentumOfChargeTracksInRoe, R
"DOC(
2372[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.
2375 REGISTER_METAVARIABLE("ptTracksRoe(maskName)", transverseMomentumOfChargeTracksInRoeWithMask,
2376 "[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`` ",
2377 Manager::VariableDataType::c_double);
2378 REGISTER_METAVARIABLE("pt2TracksRoe(maskName)", transverseMomentumSquaredOfChargeTracksInRoeWithMask,
2379 "[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` ",
2380 Manager::VariableDataType::c_double);
2381 REGISTER_VARIABLE("NumberOfKShortsInRoe", NumberOfKShortsInRoe,
2382 "[Expert] Returns the number of ``K_S0`` in the rest of event. The particle list ``K_S0:inRoe`` has to be filled beforehand.");
2384 REGISTER_VARIABLE("isInElectronOrMuonCat", isInElectronOrMuonCat,
2385 "[Expert] Returns 1.0 if the particle has been selected as target in the Muon or Electron Category, 0.0 otherwise.");
2387 REGISTER_VARIABLE("isMajorityInRestOfEventFromB0", isMajorityInRestOfEventFromB0, R"DOC(
2388[Eventbased][Expert] Checks if the majority of the tracks in the current RestOfEvent are from a ``B0``.
2391 REGISTER_METAVARIABLE("isMajorityInRestOfEventFromB0(maskName)", isMajorityInRestOfEventFromB0WithMask,
2392 "[Eventbased][Expert] Checks if the majority of the tracks in the current RestOfEvent are from a ``B0``.",
2393 Manager::VariableDataType::c_bool);
2394 REGISTER_VARIABLE(
"isMajorityInRestOfEventFromB0bar", isMajorityInRestOfEventFromB0bar, R
"DOC(
2395[Eventbased][Expert] Check if the majority of the tracks in the current RestOfEvent are from a ``anti-B0``.
2398 REGISTER_METAVARIABLE("isMajorityInRestOfEventFromB0bar(maskName)", isMajorityInRestOfEventFromB0barWithMask,
2399 "[Eventbased][Expert] Check if the majority of the tracks in the current RestOfEvent are from a ``anti-B0``.",
2400 Manager::VariableDataType::c_bool);
2401 REGISTER_VARIABLE(
"hasRestOfEventTracks", hasRestOfEventTracks, R
"DOC(
2402[Expert] Returns the number of tracks in the RestOfEvent related to the given Particle. -2 if the RestOfEvent is empty.
2405 REGISTER_METAVARIABLE("hasRestOfEventTracks(maskName)", hasRestOfEventTracksWithMask,
2406 "[Expert] Returns the number of tracks in the RestOfEvent related to the given Particle. -2 if the RestOfEvent is empty.",
2407 Manager::VariableDataType::c_bool);
2409 REGISTER_VARIABLE(
"qrCombined", isRestOfEventB0Flavor, R
"DOC(
2410[Eventbased][Expert] Returns -1 (1) if current RestOfEvent is related to a ``anti-B0`` (``B0``).
2411The ``MCError`` bit of Breco has to be 0, 1, 2, 16 or 1024.
2412The output of the variable is 0 otherwise.
2413If 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.
2415 REGISTER_VARIABLE("ancestorHasWhichFlavor", ancestorHasWhichFlavor,
2416 "[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.");
2417 REGISTER_VARIABLE(
"B0mcErrors", B0mcErrors,
"[Expert] Returns MC-matching flag, see :b2:var:`mcErrors` for the particle, e.g. ``B0`` .");
2418 REGISTER_VARIABLE(
"isRelatedRestOfEventMajorityB0Flavor", isRelatedRestOfEventMajorityB0Flavor, R
"DOC(
2419[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``).
2422 REGISTER_METAVARIABLE("isRelatedRestOfEventMajorityB0Flavor(maskName)", isRelatedRestOfEventMajorityB0FlavorWithMask,
2423 "[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``).",
2424 Manager::VariableDataType::c_int);
2425 REGISTER_VARIABLE(
"isRestOfEventMajorityB0Flavor", isRestOfEventMajorityB0Flavor,
2426 "[Expert] Returns 0 (1) if the majority of tracks and clusters of the current RestOfEvent are related to a ``anti-B0`` (``B0``).");
2427 REGISTER_VARIABLE(
"mcFlavorOfOtherB", mcFlavorOfOtherB, R
"DOC(
2428[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.
2429In other words, this variable checks the generated flavor of the other generated ``Upsilon(4S)`` daughter.
2433 REGISTER_METAVARIABLE("BtagToWBosonVariables(requestedVariable[, maskName])", BtagToWBosonVariables, R
"DOC(
2434[Eventbased][Expert] Returns values of FlavorTagging-specific kinematical variables assuming a semileptonic decay with the given particle as target.
2435The input values of ``requestedVariable`` can be the following: recoilMass in GeV/c^2 , pMissCMS in ``GeV/c``, cosThetaMissCMS and EW90.
2436)DOC", Manager::VariableDataType::c_double);
2437 REGISTER_METAVARIABLE("KaonPionVariables(requestedVariable)" , KaonPionVariables , R
"DOC(
2438[Expert] Returns values of FlavorTagging-specific kinematical variables for ``KaonPion`` category.
2439The input values of ``requestedVariable`` can be the following: cosKaonPion, HaveOpositeCharges.
2440)DOC", Manager::VariableDataType::c_double);
2441 REGISTER_METAVARIABLE("FSCVariables(requestedVariable)", FSCVariables, R
"DOC(
2442[Eventbased][Expert] Returns values of FlavorTagging-specific kinematical variables for ``FastSlowCorrelated`` category.
2443The input values of ``requestedVariable`` can be the following: pFastCMS in ``GeV/c``, cosSlowFast, SlowFastHaveOpositeCharges, or cosTPTOFast.
2444)DOC", Manager::VariableDataType::c_double);
2445 REGISTER_METAVARIABLE("hasHighestProbInCat(particleListName, extraInfoName)", hasHighestProbInCat, R
"DOC(
2446[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.
2447The probability is accessed via ``extraInfoName``, which can have the following input values:
2449* isRightTrack(Electron),
2450* isRightTrack(IntermediateElectron),
2451* isRightTrack(Muon),
2452* isRightTrack(IntermediateMuon),
2453* isRightTrack(KinLepton),
2454* isRightTrack(IntermediateKinLepton),
2455* isRightTrack(Kaon),
2456* isRightTrack(SlowPion),
2457* isRightTrack(FastHadron),
2458* isRightTrack(MaximumPstar),
2459* isRightTrack(Lambda),
2460* isRightCategory(Electron),
2461* isRightCategory(IntermediateElectron),
2462* isRightCategory(Muon),
2463* isRightCategory(IntermediateMuon),
2464* isRightCategory(KinLepton),
2465* isRightCategory(IntermediateKinLepton),
2466* isRightCategory(Kaon),
2467* isRightCategory(SlowPion),
2468* isRightCategory(FastHadron),
2469* isRightCategory(MaximumPstar),
2470* isRightCategory(Lambda),
2471* isRightCategory(KaonPion),
2472* isRightCategory(FSC).
2474)DOC", Manager::VariableDataType::c_bool);
2475 REGISTER_METAVARIABLE("HighestProbInCat(particleListName, extraInfoName)", HighestProbInCat,
2476 "[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);
2478 REGISTER_METAVARIABLE(
"isRightTrack(particleName)", isRightTrack, R
"DOC(
2479[Expert] Returns 1.0 if the given particle was really from a B-meson depending on category provided in ``particleName`` argument, 0.0 otherwise.
2480Allowed input values for ``particleName`` argument in this variable are the following:
2483* IntermediateElectron,
2487* IntermediateKinLepton,
2494)DOC", Manager::VariableDataType::c_int);
2495 REGISTER_METAVARIABLE("isRightCategory(particleName)", isRightCategory, R
"DOC(
2496[Expert] Returns 1.0 if the class track by ``particleName`` category has the same flavor as the MC target track, 0.0 otherwise.
2497Allowed input values for ``particleName`` argument in this variable are the following:
2500* IntermediateElectron,
2504* IntermediateKinLepton
2514)DOC", Manager::VariableDataType::c_int);
2515 REGISTER_METAVARIABLE("QpOf(particleListName, outputExtraInfo, rankingExtraInfo)", QpOf, R
"DOC(
2516[Eventbased][Expert] Returns the :math:`q*p` value for a given particle list provided as the 1st argument,
2517where :math:`p` is the probability of a category stored as extraInfo, provided as the 2nd argument,
2518allowed values are same as in :b2:var:`hasHighestProbInCat`.
2519The particle is selected after ranking according to a flavor tagging extraInfo, provided as the 3rd argument,
2520allowed values are same as in :b2:var:`hasHighestProbInCat`.
2521)DOC", Manager::VariableDataType::c_double);
2522 REGISTER_METAVARIABLE("weightedQpOf(particleListName, outputExtraInfo, rankingExtraInfo)", weightedQpOf, R
"DOC(
2523[Eventbased][Expert] Returns the weighted :math:`q*p` value for a given particle list, provided as the 1st argument,
2524where :math:`p` is the probability of a category stored as extraInfo, provided in the 2nd argument,
2525allowed values are same as in :b2:var:`hasHighestProbInCat`.
2526The particles in the list are ranked according to a flavor tagging extraInfo, provided as the 3rd argument,
2527allowed values are same as in :b2:var:`hasHighestProbInCat`.
2528The values for the three top particles is combined into an effective (weighted) output.
2529)DOC", Manager::VariableDataType::c_double);
2530 REGISTER_METAVARIABLE("QpTrack(particleListName, outputExtraInfo, rankingExtraInfo)", QpTrack, R
"DOC(
2531[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.
2532where :math:`p` is the probability of a category stored as extraInfo, provided as the 2nd argument,
2533allowed values are same as in :b2:var:`hasHighestProbInCat`.
2534The particle is selected after ranking according to a flavor tagging extraInfo, provided as the 3rd argument,
2535allowed values are same as in :b2:var:`hasHighestProbInCat`.
2536)DOC", Manager::VariableDataType::c_double);
2538 REGISTER_METAVARIABLE("variableOfTarget(particleListName, inputVariable, rankingExtraInfo)", variableOfTarget, R
"DOC(
2539[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.
2540The particles are ranked according to a flavor tagging extraInfo, provided as the 2nd argument,
2541allowed values are same as in :b2:var:`hasHighestProbInCat`.
2542)DOC", Manager::VariableDataType::c_double);
2544 REGISTER_METAVARIABLE("hasTrueTarget(categoryName)", hasTrueTarget,
2545 "[Expert] Returns 1 if the given category has a target, 0 otherwise.", Manager::VariableDataType::c_double);
2546 REGISTER_METAVARIABLE(
"isTrueCategory(categoryName)", isTrueCategory,
2547 "[Expert] Returns 1 if the given category tags the B0 MC flavor correctly, 0 otherwise.", Manager::VariableDataType::c_double);
2549 REGISTER_METAVARIABLE(
"qpCategory(categoryName)", qpCategory, R
"DOC(
2550[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.
2551The allowed categories are the official Flavor Tagger Category Names.
2552)DOC", Manager::VariableDataType::c_double);
2553 REGISTER_METAVARIABLE("isTrueFTCategory(categoryName)", isTrueFTCategory, R
"DOC(
2554[Expert] Returns 1 if the target particle (checking the decay chain) of the category with the given name is found in the MC particles,
2555and if it provides the right flavor. The allowed categories are the official Flavor Tagger Category Names.
2556)DOC", Manager::VariableDataType::c_double);
2557 REGISTER_METAVARIABLE("hasTrueTargets(categoryName)", hasTrueTargets, R
"DOC(
2558[Expert] Returns 1 if target particles (checking only the decay chain) of the category with the given name is found in the MC particles.
2559The allowed categories are the official Flavor Tagger Category Names.
2560)DOC", Manager::VariableDataType::c_double);
2562 VARIABLE_GROUP("Flavor Tagger Analysis Variables")
2564 REGISTER_METAVARIABLE(
"rBinBelle(combinerMethod)", rBinBelle,
R"DOC(
2565Returns the corresponding :math:`r` (dilution) bin according to the Belle binning for the given ``combinerMethod``.
2566The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2567The return values and the corresponding dilution ranges are the following:
2569* 0: :math:`0.000 < r < 0.100`;
2570* 1: :math:`0.100 < r < 0.250`;
2571* 2: :math:`0.250 < r < 0.500`;
2572* 3: :math:`0.500 < r < 0.625`;
2573* 4: :math:`0.625 < r < 0.750`;
2574* 5: :math:`0.750 < r < 0.875`;
2575* 6: :math:`0.875 < r < 1.000`.
2577.. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2578.. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2579)DOC",
Manager::VariableDataType::c_int);
2580 REGISTER_METAVARIABLE(
"qrOutput(combinerMethod)", qrOutput,
R"DOC(
2581Returns the output of the flavorTagger, flavor tag :math:`q` times the dilution factor :math:`r`, for the given combiner method.
2582The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2584.. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2585.. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2586)DOC",
Manager::VariableDataType::c_double);
2587 REGISTER_METAVARIABLE(
"qOutput(combinerMethod)", qOutput,
R"DOC(
2588Returns the flavor tag :math:`q` output of the flavorTagger for the given combinerMethod.
2589The available methods are 'FBDT' and 'FANN' (category-based combiners), and 'DNN' (DNN tagger output).
2591.. warning:: You have to run the Flavor Tagger for this variable to be meaningful.
2592.. seealso:: :ref:`FlavorTagger` and :func:`flavorTagger.flavorTagger`.
2593)DOC",
Manager::VariableDataType::c_double);
2594 REGISTER_VARIABLE(
"isRelatedRestOfEventB0Flavor", isRelatedRestOfEventB0Flavor,
R"DOC(
2595Returns -1 (1) if the RestOfEvent related to the given particle is related to a ``anti-B0`` (``B0``).
2596The ``MCError`` bit of Breco has to be 0, 1, 2, 16 or 1024.
2597The output of the variable is 0 otherwise.
2598If 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)
static constexpr const char * c_defaultMaskName
Default mask name.
static ROOT::Math::XYZVector calculateThrust(const std::vector< ROOT::Math::PxPyPzEVector > &momenta)
calculates the thrust axis
Global list of available variables.
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.
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 Particle *particle, const MCParticle *mcParticle=nullptr)
Returns quality indicator of the match as a bit pattern where the individual bits indicate the the ty...