10#include <analysis/variables/MetaVariables.h>
11#include <analysis/variables/MCTruthVariables.h>
13#include <analysis/VariableManager/Utility.h>
14#include <analysis/dataobjects/Particle.h>
15#include <analysis/dataobjects/ParticleList.h>
16#include <analysis/dataobjects/RestOfEvent.h>
17#include <analysis/utility/PCmsLabTransform.h>
18#include <analysis/utility/ReferenceFrame.h>
19#include <analysis/utility/EvtPDLUtil.h>
20#include <analysis/utility/ParticleCopy.h>
21#include <analysis/utility/ValueIndexPairSorting.h>
22#include <analysis/ClusterUtility/ClusterUtils.h>
23#include <analysis/variables/VariableFormulaConstructor.h>
25#include <framework/logging/Logger.h>
26#include <framework/datastore/StoreArray.h>
27#include <framework/datastore/StoreObjPtr.h>
28#include <framework/dataobjects/EventExtraInfo.h>
29#include <framework/utilities/Conversion.h>
30#include <framework/utilities/MakeROOTCompatible.h>
31#include <framework/gearbox/Const.h>
33#include <mdst/dataobjects/Track.h>
34#include <mdst/dataobjects/MCParticle.h>
35#include <mdst/dataobjects/ECLCluster.h>
36#include <mdst/dataobjects/TrackFitResult.h>
38#include <boost/algorithm/string.hpp>
46#include <TDatabasePDG.h>
47#include <Math/Vector4D.h>
58 if (arguments.size() == 1) {
60 auto func = [var](
const Particle * particle) ->
double {
61 UseReferenceFrame<RestFrame> frame(particle);
62 double result = std::get<double>(var->function(particle));
67 B2FATAL(
"Wrong number of arguments for meta function useRestFrame");
73 if (arguments.size() == 1) {
75 auto func = [var](
const Particle * particle) ->
double {
76 UseReferenceFrame<CMSFrame> frame;
77 double result = std::get<double>(var->function(particle));
82 B2FATAL(
"Wrong number of arguments for meta function useCMSFrame");
88 if (arguments.size() == 1) {
90 auto func = [var](
const Particle * particle) ->
double {
91 UseReferenceFrame<LabFrame> frame;
92 double result = std::get<double>(var->function(particle));
97 B2FATAL(
"Wrong number of arguments for meta function useLabFrame");
103 if (arguments.size() == 2) {
106 int daughterIndexTagB = 0;
108 daughterIndexTagB = Belle2::convertString<int>(arguments[1]);
109 }
catch (std::invalid_argument&) {
110 B2FATAL(
"Second argument of useTagSideRecoilRestFrame meta function must be integer!");
113 auto func = [var, daughterIndexTagB](
const Particle * particle) ->
double {
114 if (particle->getPDGCode() != 300553)
116 B2ERROR(
"Variable should only be used on a Upsilon(4S) Particle List!");
121 ROOT::Math::PxPyPzEVector pSigB = T.getBeamFourMomentum() - particle->getDaughter(daughterIndexTagB)->get4Vector();
122 Particle tmp(pSigB, -particle->getDaughter(daughterIndexTagB)->getPDGCode());
124 UseReferenceFrame<RestFrame> frame(&tmp);
125 double result = std::get<double>(var->function(particle));
131 B2FATAL(
"Wrong number of arguments for meta function useTagSideRecoilRestFrame");
137 if (arguments.size() == 2) {
139 std::string listName = arguments[1];
140 auto func = [var, listName](
const Particle * particle) ->
double {
141 StoreObjPtr<ParticleList> list(listName);
142 unsigned listSize = list->getListSize();
146 B2WARNING(
"The selected ParticleList contains more than 1 Particles in this event. The variable useParticleRestFrame will use only the first candidate, and the result may not be the expected one."
147 <<
LogVar(
"ParticleList", listName)
148 <<
LogVar(
"Number of candidates in the list", listSize));
149 const Particle* p = list->getParticle(0);
150 UseReferenceFrame<RestFrame> frame(p);
151 double result = std::get<double>(var->function(particle));
156 B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
162 if (arguments.size() == 2) {
164 std::string listName = arguments[1];
165 auto func = [var, listName](
const Particle * particle) ->
double {
166 StoreObjPtr<ParticleList> list(listName);
167 unsigned listSize = list->getListSize();
171 B2WARNING(
"The selected ParticleList contains more than 1 Particles in this event. The variable useParticleRestFrame will use only the first candidate, and the result may not be the expected one."
172 <<
LogVar(
"ParticleList", listName)
173 <<
LogVar(
"Number of candidates in the list", listSize));
174 const Particle* p = list->getParticle(0);
176 ROOT::Math::PxPyPzEVector recoil = T.getBeamFourMomentum() - p->get4Vector();
178 Particle pRecoil(recoil, 0);
179 pRecoil.setVertex(particle->getVertex());
180 UseReferenceFrame<RestFrame> frame(&pRecoil);
181 double result = std::get<double>(var->function(particle));
186 B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
192 if (arguments.size() >= 2) {
194 auto func = [var, arguments](
const Particle * particle) ->
double {
197 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
199 for (
unsigned int i = 1; i < arguments.size(); i++)
201 auto generalizedIndex = arguments[i];
202 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
204 pSum += dauPart->get4Vector();
208 Particle tmp(pSum, 0);
209 UseReferenceFrame<RestFrame> frame(&tmp);
210 double result = std::get<double>(var->function(particle));
215 B2FATAL(
"Wrong number of arguments for meta function useDaughterRestFrame.");
221 if (arguments.size() == 1) {
222 auto extraInfoName = arguments[0];
223 auto func = [extraInfoName](
const Particle * particle) ->
double {
224 if (particle ==
nullptr)
226 B2WARNING(
"Returns NaN because the particle is nullptr! If you want EventExtraInfo variables, please use eventExtraInfo() instead");
229 if (particle->hasExtraInfo(extraInfoName))
231 return particle->getExtraInfo(extraInfoName);
239 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
245 if (arguments.size() == 1) {
246 auto extraInfoName = arguments[0];
247 auto func = [extraInfoName](
const Particle*) ->
double {
248 StoreObjPtr<EventExtraInfo> eventExtraInfo;
249 if (not eventExtraInfo.isValid())
251 if (eventExtraInfo->hasExtraInfo(extraInfoName))
253 return eventExtraInfo->getExtraInfo(extraInfoName);
261 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
267 if (arguments.size() == 1) {
270 auto func = [var, key](
const Particle*) ->
double {
272 StoreObjPtr<EventExtraInfo> eventExtraInfo;
273 if (not eventExtraInfo.isValid())
274 eventExtraInfo.create();
275 if (eventExtraInfo->hasExtraInfo(key))
277 return eventExtraInfo->getExtraInfo(key);
281 auto var_result = var->function(
nullptr);
282 if (std::holds_alternative<double>(var_result)) {
283 value = std::get<double>(var_result);
284 }
else if (std::holds_alternative<int>(var_result)) {
285 return std::get<int>(var_result);
286 }
else if (std::holds_alternative<bool>(var_result)) {
287 return std::get<bool>(var_result);
289 eventExtraInfo->addExtraInfo(key, value);
295 B2FATAL(
"Wrong number of arguments for meta function eventCached");
301 if (arguments.size() == 1) {
304 auto func = [var, key](
const Particle * particle) ->
double {
306 if (particle->hasExtraInfo(key))
308 return particle->getExtraInfo(key);
311 double value = std::get<double>(var->function(particle));
319 const_cast<Particle*
>(particle)->addExtraInfo(key, value);
325 B2FATAL(
"Wrong number of arguments for meta function particleCached");
334 if (arguments.size() != 1) B2FATAL(
"Wrong number of arguments for meta function formula");
335 FormulaParser<VariableFormulaConstructor> parser;
337 return parser.parse(arguments[0]);
338 }
catch (std::runtime_error& e) {
345 if (arguments.size() <= 1) {
347 std::string cutString;
348 if (arguments.size() == 1)
349 cutString = arguments[0];
351 auto func = [cut](
const Particle*) ->
int {
353 int number_of_tracks = 0;
354 StoreArray<Track> tracks;
355 for (
const auto& track : tracks)
357 const TrackFitResult* trackFit = track.getTrackFitResultWithClosestMass(
Const::pion);
358 if (trackFit->getChargeSign() == 0) {
362 if (cut->check(&particle))
367 return number_of_tracks;
372 B2FATAL(
"Wrong number of arguments for meta function nCleanedTracks");
378 if (arguments.size() <= 1) {
380 std::string cutString;
381 if (arguments.size() == 1)
382 cutString = arguments[0];
384 auto func = [cut](
const Particle*) ->
int {
386 int number_of_clusters = 0;
387 StoreArray<ECLCluster> clusters;
388 for (
const auto& cluster : clusters)
394 Particle particle(&cluster);
395 if (cut->check(&particle))
396 number_of_clusters++;
399 return number_of_clusters;
404 B2FATAL(
"Wrong number of arguments for meta function nCleanedECLClusters");
410 if (arguments.size() == 1) {
411 std::string cutString = arguments[0];
413 auto func = [cut](
const Particle * particle) ->
bool {
414 if (cut->check(particle))
421 B2FATAL(
"Wrong number of arguments for meta function passesCut");
427 if (arguments.size() == 1) {
428 std::string cutString = arguments[0];
430 auto func = [cut](
const Particle*) ->
bool {
431 if (cut->check(
nullptr))
438 B2FATAL(
"Wrong number of arguments for meta function passesEventCut");
444 if (arguments.size() == 2) {
447 pdgCode = Belle2::convertString<int>(arguments[0]);
448 }
catch (std::invalid_argument&) {
449 B2FATAL(
"The first argument of varFor meta function must be a positive integer!");
452 auto func = [pdgCode, var](
const Particle * particle) ->
double {
453 if (std::abs(particle->getPDGCode()) == std::abs(pdgCode))
455 auto var_result = var->function(particle);
456 if (std::holds_alternative<double>(var_result)) {
457 return std::get<double>(var_result);
458 }
else if (std::holds_alternative<int>(var_result)) {
459 return std::get<int>(var_result);
460 }
else if (std::holds_alternative<bool>(var_result)) {
461 return std::get<bool>(var_result);
467 B2FATAL(
"Wrong number of arguments for meta function varFor");
473 if (arguments.size() == 1) {
475 auto func = [var](
const Particle * particle) ->
double {
476 if (particle->getMCParticle())
481 auto var_result = var->function(particle);
482 if (std::holds_alternative<double>(var_result)) {
483 return std::get<double>(var_result);
484 }
else if (std::holds_alternative<int>(var_result)) {
485 return std::get<int>(var_result);
486 }
else if (std::holds_alternative<bool>(var_result)) {
487 return std::get<bool>(var_result);
494 B2FATAL(
"Wrong number of arguments for meta function varForMCGen");
500 if (arguments.size() == 1) {
501 std::string listName = arguments[0];
502 auto func = [listName](
const Particle * particle) ->
int {
505 StoreObjPtr<ParticleList> listOfParticles(listName);
507 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to nParticlesInList");
509 return listOfParticles->getListSize();
514 B2FATAL(
"Wrong number of arguments for meta function nParticlesInList");
521 if (arguments.size() != 1) {
522 B2FATAL(
"Wrong number of arguments for isInList");
524 auto listName = arguments[0];
526 auto func = [listName](
const Particle * particle) ->
bool {
529 StoreObjPtr<ParticleList> list(listName);
530 if (!(list.isValid()))
532 B2FATAL(
"Invalid Listname " << listName <<
" given to isInList");
536 return list->contains(particle);
545 if (arguments.size() != 1) {
546 B2FATAL(
"Wrong number of arguments for sourceObjectIsInList");
548 auto listName = arguments[0];
550 auto func = [listName](
const Particle * particle) ->
int {
553 StoreObjPtr<ParticleList> list(listName);
554 if (!(list.isValid()))
556 B2FATAL(
"Invalid Listname " << listName <<
" given to sourceObjectIsInList");
562 if (particlesource == Particle::EParticleSourceObject::c_Composite
563 or particlesource == Particle::EParticleSourceObject::c_Undefined)
569 for (
unsigned i = 0; i < list->getListSize(); ++i)
571 Particle* iparticle = list->getParticle(i);
572 if (particlesource == iparticle->getParticleSource())
573 if (particle->getMdstArrayIndex() == iparticle->getMdstArrayIndex())
585 if (arguments.size() != 1) {
586 B2FATAL(
"Wrong number of arguments for mcParticleIsInMCList");
588 auto listName = arguments[0];
590 auto func = [listName](
const Particle * particle) ->
bool {
593 StoreObjPtr<ParticleList> list(listName);
594 if (!(list.isValid()))
595 B2FATAL(
"Invalid Listname " << listName <<
" given to mcParticleIsInMCList");
599 if (mcp ==
nullptr)
return false;
602 for (
unsigned i = 0; i < list->getListSize(); ++i)
604 const MCParticle* imcp = list->getParticle(i)->
getMCParticle();
605 if ((imcp !=
nullptr) and (mcp->getArrayIndex() == imcp->getArrayIndex()))
615 B2WARNING(
"isDaughterOfList is outdated and replaced by isDescendantOfList.");
616 std::vector<std::string> new_arguments = arguments;
617 new_arguments.push_back(std::string(
"1"));
618 return isDescendantOfList(new_arguments);
623 B2WARNING(
"isGrandDaughterOfList is outdated and replaced by isDescendantOfList.");
624 std::vector<std::string> new_arguments = arguments;
625 new_arguments.push_back(std::string(
"2"));
626 return isDescendantOfList(new_arguments);
631 if (arguments.size() > 0) {
632 auto listNames = arguments;
633 auto func = [listNames](
const Particle * particle) ->
bool {
635 int generation_flag = -1;
638 generation_flag = Belle2::convertString<int>(listNames.back());
639 }
catch (std::exception& e) {}
641 for (
auto& iListName : listNames)
644 Belle2::convertString<int>(iListName);
646 }
catch (std::exception& e) {}
649 auto list_comparison = [](
auto&& self,
const Particle * m,
const Particle * p,
int flag)->
bool {
651 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
653 const Particle* daughter = m->getDaughter(i);
654 if ((flag == 1.) or (flag < 0)) {
655 if (p->isCopyOf(daughter)) {
661 if (daughter->getNDaughters() > 0) {
662 result = self(self, daughter, p, flag - 1);
672 StoreObjPtr<ParticleList> listOfParticles(iListName);
674 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isDescendantOfList");
676 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
677 Particle* iParticle = listOfParticles->getParticle(i);
678 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
688 B2FATAL(
"Wrong number of arguments for meta function isDescendantOfList");
694 if (arguments.size() > 0) {
695 auto listNames = arguments;
696 auto func = [listNames](
const Particle * particle) ->
bool {
698 int generation_flag = -1;
701 generation_flag = Belle2::convertString<int>(listNames.back());
702 }
catch (std::exception& e) {}
704 if (particle->getMCParticle() ==
nullptr)
709 for (
auto& iListName : listNames)
712 std::stod(iListName);
714 }
catch (std::exception& e) {}
716 auto list_comparison = [](
auto&& self,
const Particle * m,
const Particle * p,
int flag)->
bool {
718 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
720 const Particle* daughter = m->getDaughter(i);
721 if ((flag == 1.) or (flag < 0)) {
722 if (daughter->getMCParticle() !=
nullptr) {
723 if (p->getMCParticle()->getArrayIndex() == daughter->getMCParticle()->getArrayIndex()) {
729 if (daughter->getNDaughters() > 0) {
730 result = self(self, daughter, p, flag - 1);
740 StoreObjPtr<ParticleList> listOfParticles(iListName);
742 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isMCDescendantOfList");
744 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
745 Particle* iParticle = listOfParticles->getParticle(i);
746 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
756 B2FATAL(
"Wrong number of arguments for meta function isMCDescendantOfList");
762 if (arguments.size() == 1) {
764 auto func = [var](
const Particle * particle) ->
double {
765 double product = 1.0;
766 if (particle->getNDaughters() == 0)
770 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
772 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
773 product *= std::get<double>(var->function(particle->getDaughter(j)));
775 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
777 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
778 product *= std::get<int>(var->function(particle->getDaughter(j)));
785 B2FATAL(
"Wrong number of arguments for meta function daughterProductOf");
791 if (arguments.size() == 1) {
793 auto func = [var](
const Particle * particle) ->
double {
795 if (particle->getNDaughters() == 0)
799 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
801 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
802 sum += std::get<double>(var->function(particle->getDaughter(j)));
804 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
806 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
807 sum += std::get<int>(var->function(particle->getDaughter(j)));
814 B2FATAL(
"Wrong number of arguments for meta function daughterSumOf");
820 if (arguments.size() == 1) {
822 auto func = [var](
const Particle * particle) ->
double {
824 if (particle->getNDaughters() == 0)
828 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
830 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
831 double iValue = std::get<double>(var->function(particle->getDaughter(j)));
832 if (std::isnan(iValue))
continue;
833 if (std::isnan(min)) min = iValue;
834 if (iValue < min) min = iValue;
836 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
838 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
839 int iValue = std::get<int>(var->function(particle->getDaughter(j)));
840 if (std::isnan(min)) min = iValue;
841 if (iValue < min) min = iValue;
848 B2FATAL(
"Wrong number of arguments for meta function daughterLowest");
854 if (arguments.size() == 1) {
856 auto func = [var](
const Particle * particle) ->
double {
858 if (particle->getNDaughters() == 0)
862 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
864 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
865 double iValue = std::get<double>(var->function(particle->getDaughter(j)));
866 if (std::isnan(iValue))
continue;
867 if (std::isnan(max)) max = iValue;
868 if (iValue > max) max = iValue;
870 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
872 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
873 int iValue = std::get<int>(var->function(particle->getDaughter(j)));
874 if (std::isnan(max)) max = iValue;
875 if (iValue > max) max = iValue;
882 B2FATAL(
"Wrong number of arguments for meta function daughterHighest");
888 if (arguments.size() == 3) {
889 auto func = [arguments](
const Particle * particle) ->
double {
890 if (particle ==
nullptr)
892 const Particle* dau_i = particle->getParticleFromGeneralizedIndexString(arguments[0]);
893 const Particle* dau_j = particle->getParticleFromGeneralizedIndexString(arguments[1]);
894 auto variablename = arguments[2];
895 if (dau_i ==
nullptr || dau_j ==
nullptr)
897 B2ERROR(
"One of the first two arguments doesn't specify a valid (grand-)daughter!");
901 auto result_j = var->function(dau_j);
902 auto result_i = var->function(dau_i);
904 if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i))
906 diff = std::get<double>(result_j) - std::get<double>(result_i);
907 }
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i))
909 diff = std::get<int>(result_j) - std::get<int>(result_i);
912 throw std::runtime_error(
"Bad variant access");
914 if (variablename ==
"phi" or variablename ==
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))
915 or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)")))
917 if (fabs(diff) > M_PI) {
919 diff = diff - 2 * M_PI;
921 diff = 2 * M_PI + diff;
929 B2FATAL(
"Wrong number of arguments for meta function daughterDiffOf");
935 if (arguments.size() == 3) {
936 auto func = [arguments](
const Particle * particle) ->
double {
937 if (particle ==
nullptr)
939 const Particle* dau_i = particle->getParticleFromGeneralizedIndexString(arguments[0]);
940 const Particle* dau_j = particle->getParticleFromGeneralizedIndexString(arguments[1]);
941 auto variablename = arguments[2];
942 if (dau_i ==
nullptr || dau_j ==
nullptr)
944 B2ERROR(
"One of the first two arguments doesn't specify a valid (grand-)daughter!");
949 if (iMcDaughter ==
nullptr || jMcDaughter ==
nullptr)
951 Particle iTmpPart(iMcDaughter);
952 Particle jTmpPart(jMcDaughter);
954 auto result_j = var->function(&jTmpPart);
955 auto result_i = var->function(&iTmpPart);
957 if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i))
959 diff = std::get<double>(result_j) - std::get<double>(result_i);
960 }
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i))
962 diff = std::get<int>(result_j) - std::get<int>(result_i);
965 throw std::runtime_error(
"Bad variant access");
967 if (variablename ==
"phi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)")))
969 if (fabs(diff) > M_PI) {
971 diff = diff - 2 * M_PI;
973 diff = 2 * M_PI + diff;
981 B2FATAL(
"Wrong number of arguments for meta function mcDaughterDiffOf");
987 if (arguments.size() == 5) {
989 Belle2::convertString<int>(arguments[0]);
990 Belle2::convertString<int>(arguments[1]);
991 Belle2::convertString<int>(arguments[2]);
992 Belle2::convertString<int>(arguments[3]);
993 }
catch (std::invalid_argument&) {
994 B2FATAL(
"First four arguments of grandDaughterDiffOf meta function must be integers!");
996 std::vector<std::string> new_arguments;
997 new_arguments.push_back(std::string(arguments[0] +
":" + arguments[2]));
998 new_arguments.push_back(std::string(arguments[1] +
":" + arguments[3]));
999 new_arguments.push_back(arguments[4]);
1000 return daughterDiffOf(new_arguments);
1002 B2FATAL(
"Wrong number of arguments for meta function grandDaughterDiffOf");
1008 std::vector<std::string> new_arguments = arguments;
1009 new_arguments.push_back(std::string(
"phi"));
1010 return daughterDiffOf(new_arguments);
1015 std::vector<std::string> new_arguments = arguments;
1016 new_arguments.push_back(std::string(
"phi"));
1017 return mcDaughterDiffOf(new_arguments);
1022 std::vector<std::string> new_arguments = arguments;
1023 new_arguments.push_back(std::string(
"phi"));
1024 return grandDaughterDiffOf(new_arguments);
1029 std::vector<std::string> new_arguments = arguments;
1030 new_arguments.push_back(std::string(
"clusterPhi"));
1031 return daughterDiffOf(new_arguments);
1036 std::vector<std::string> new_arguments = arguments;
1037 new_arguments.push_back(std::string(
"clusterPhi"));
1038 return grandDaughterDiffOf(new_arguments);
1043 std::vector<std::string> new_arguments = arguments;
1044 new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
1045 return daughterDiffOf(new_arguments);
1050 std::vector<std::string> new_arguments = arguments;
1051 new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
1052 return mcDaughterDiffOf(new_arguments);
1057 std::vector<std::string> new_arguments = arguments;
1058 new_arguments.push_back(std::string(
"useCMSFrame(clusterPhi)"));
1059 return daughterDiffOf(new_arguments);
1064 if (arguments.size() == 3) {
1065 auto func = [arguments](
const Particle * particle) ->
double {
1066 if (particle ==
nullptr)
1068 const Particle* dau_i = particle->getParticleFromGeneralizedIndexString(arguments[0]);
1069 const Particle* dau_j = particle->getParticleFromGeneralizedIndexString(arguments[1]);
1070 if (!(dau_i && dau_j))
1072 B2ERROR(
"One of the first two arguments doesn't specify a valid (grand-)daughter!");
1076 double iValue, jValue;
1077 if (std::holds_alternative<double>(var->function(dau_j)))
1079 iValue = std::get<double>(var->function(dau_i));
1080 jValue = std::get<double>(var->function(dau_j));
1081 }
else if (std::holds_alternative<int>(var->function(dau_j)))
1083 iValue = std::get<int>(var->function(dau_i));
1084 jValue = std::get<int>(var->function(dau_j));
1086 return (jValue - iValue) / (jValue + iValue);
1090 B2FATAL(
"Wrong number of arguments for meta function daughterNormDiffOf");
1096 if (arguments.size() == 2) {
1097 int daughterNumber = 0;
1099 daughterNumber = Belle2::convertString<int>(arguments[0]);
1100 }
catch (std::invalid_argument&) {
1101 B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
1103 auto variablename = arguments[1];
1104 auto func = [variablename, daughterNumber](
const Particle * particle) ->
double {
1105 if (particle ==
nullptr)
1107 if (daughterNumber >=
int(particle->getNDaughters()))
1112 auto result_mother = var->function(particle);
1113 auto result_daughter = var->function(particle->getDaughter(daughterNumber));
1115 if (std::holds_alternative<double>(result_mother) && std::holds_alternative<double>(result_daughter)) {
1116 diff = std::get<double>(result_mother) - std::get<double>(result_daughter);
1117 }
else if (std::holds_alternative<int>(result_mother) && std::holds_alternative<int>(result_daughter)) {
1118 diff = std::get<int>(result_mother) - std::get<int>(result_daughter);
1120 throw std::runtime_error(
"Bad variant access");
1123 if (variablename ==
"phi" or variablename ==
"useCMSFrame(phi)") {
1124 if (fabs(diff) > M_PI) {
1126 diff = diff - 2 * M_PI;
1128 diff = 2 * M_PI + diff;
1137 B2FATAL(
"Wrong number of arguments for meta function daughterMotherDiffOf");
1143 if (arguments.size() == 2) {
1144 int daughterNumber = 0;
1146 daughterNumber = Belle2::convertString<int>(arguments[0]);
1147 }
catch (std::invalid_argument&) {
1148 B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
1151 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1152 if (particle ==
nullptr)
1154 if (daughterNumber >=
int(particle->getNDaughters()))
1158 double daughterValue = 0.0, motherValue = 0.0;
1159 if (std::holds_alternative<double>(var->function(particle))) {
1160 daughterValue = std::get<double>(var->function(particle->getDaughter(daughterNumber)));
1161 motherValue = std::get<double>(var->function(particle));
1162 }
else if (std::holds_alternative<int>(var->function(particle))) {
1163 daughterValue = std::get<int>(var->function(particle->getDaughter(daughterNumber)));
1164 motherValue = std::get<int>(var->function(particle));
1166 return (motherValue - daughterValue) / (motherValue + daughterValue);
1171 B2FATAL(
"Wrong number of arguments for meta function daughterMotherNormDiffOf");
1177 if (arguments.size() == 2 || arguments.size() == 3) {
1179 auto func = [arguments](
const Particle * particle) ->
double {
1180 if (particle ==
nullptr)
1183 std::vector<ROOT::Math::PxPyPzEVector> pDaus;
1187 for (
auto& generalizedIndex : arguments)
1189 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1191 pDaus.push_back(frame.getMomentum(dauPart));
1193 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
1199 if (pDaus.size() == 2)
1206 B2FATAL(
"Wrong number of arguments for meta function daughterAngle");
1210 double grandDaughterDecayAngle(
const Particle* particle,
const std::vector<double>& arguments)
1212 if (arguments.size() == 2) {
1217 int daughterIndex = std::lround(arguments[0]);
1218 if (daughterIndex >=
int(particle->getNDaughters()))
1220 const Particle* dau = particle->getDaughter(daughterIndex);
1222 int grandDaughterIndex = std::lround(arguments[1]);
1223 if (grandDaughterIndex >=
int(dau->getNDaughters()))
1226 B2Vector3D boost = dau->get4Vector().BoostToCM();
1228 ROOT::Math::PxPyPzEVector motherMomentum = - particle->get4Vector();
1229 motherMomentum = ROOT::Math::Boost(boost) * motherMomentum;
1231 ROOT::Math::PxPyPzEVector grandDaughterMomentum = dau->getDaughter(grandDaughterIndex)->get4Vector();
1232 grandDaughterMomentum = ROOT::Math::Boost(boost) * grandDaughterMomentum;
1237 B2FATAL(
"The variable grandDaughterDecayAngle needs exactly two integers as arguments!");
1243 if (arguments.size() == 2 || arguments.size() == 3) {
1245 auto func = [arguments](
const Particle * particle) ->
double {
1246 if (particle ==
nullptr)
1249 std::vector<ROOT::Math::PxPyPzEVector> pDaus;
1253 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_MCParticle)
1255 for (
auto& generalizedIndex : arguments) {
1257 if (mcPart ==
nullptr)
1260 if (dauMcPart ==
nullptr)
1263 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1267 for (
auto& generalizedIndex : arguments) {
1268 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1269 if (dauPart ==
nullptr)
1273 if (dauMcPart ==
nullptr)
1276 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1281 if (pDaus.size() == 2)
1288 B2FATAL(
"Wrong number of arguments for meta function mcDaughterAngle");
1292 double daughterClusterAngleInBetween(
const Particle* particle,
const std::vector<double>& daughterIndices)
1294 if (daughterIndices.size() == 2) {
1295 int daughterIndexi = std::lround(daughterIndices[0]);
1296 int daughterIndexj = std::lround(daughterIndices[1]);
1297 if (std::max(daughterIndexi, daughterIndexj) >=
int(particle->getNDaughters())) {
1300 const ECLCluster* clusteri = particle->getDaughter(daughterIndexi)->getECLCluster();
1301 const ECLCluster* clusterj = particle->getDaughter(daughterIndexj)->getECLCluster();
1302 if (clusteri and clusterj) {
1306 ClusterUtils clusutils;
1307 B2Vector3D pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
1308 B2Vector3D pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
1309 return pi.Angle(pj);
1313 }
else if (daughterIndices.size() == 3) {
1314 int daughterIndexi = std::lround(daughterIndices[0]);
1315 int daughterIndexj = std::lround(daughterIndices[1]);
1316 int daughterIndexk = std::lround(daughterIndices[2]);
1317 if (std::max(std::max(daughterIndexi, daughterIndexj), daughterIndexk) >=
int(particle->getNDaughters())) {
1320 const ECLCluster* clusteri = (particle->getDaughter(daughterIndices[0]))->getECLCluster();
1321 const ECLCluster* clusterj = (particle->getDaughter(daughterIndices[1]))->getECLCluster();
1322 const ECLCluster* clusterk = (particle->getDaughter(daughterIndices[2]))->getECLCluster();
1323 if (clusteri and clusterj and clusterk) {
1328 ClusterUtils clusutils;
1329 B2Vector3D pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
1330 B2Vector3D pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
1331 B2Vector3D pk = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterk, clusterkBit)).Vect();
1332 return pk.
Angle(pi + pj);
1337 B2FATAL(
"Wrong number of arguments for daughterClusterAngleInBetween!");
1343 if (arguments.size() > 1) {
1344 auto func = [arguments](
const Particle * particle) ->
double {
1346 ROOT::Math::PxPyPzEVector pSum;
1348 for (
auto& generalizedIndex : arguments)
1350 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1352 pSum += frame.getMomentum(dauPart);
1361 B2FATAL(
"Wrong number of arguments for meta function daughterInvM. At least two integers are needed.");
1367 if (arguments.size() == 2) {
1371 divideBy = Belle2::convertString<int>(arguments[1]);
1372 }
catch (std::invalid_argument&) {
1373 B2FATAL(
"Second argument of modulo meta function must be integer!");
1375 auto func = [var, divideBy](
const Particle * particle) ->
int {
1376 auto var_result = var->function(particle);
1377 if (std::holds_alternative<double>(var_result))
1379 return int(std::get<double>(var_result)) % divideBy;
1380 }
else if (std::holds_alternative<int>(var_result))
1382 return std::get<int>(var_result) % divideBy;
1383 }
else if (std::holds_alternative<bool>(var_result))
1385 return int(std::get<bool>(var_result)) % divideBy;
1390 B2FATAL(
"Wrong number of arguments for meta function modulo");
1396 if (arguments.size() == 1) {
1399 auto func = [var](
const Particle * particle) ->
bool {
return std::isnan(std::get<double>(var->function(particle))); };
1402 B2FATAL(
"Wrong number of arguments for meta function isNAN");
1408 if (arguments.size() == 2) {
1410 double defaultOutput;
1412 defaultOutput = Belle2::convertString<double>(arguments[1]);
1413 }
catch (std::invalid_argument&) {
1414 B2FATAL(
"The second argument of ifNANgiveX meta function must be a number!");
1416 auto func = [var, defaultOutput](
const Particle * particle) ->
double {
1417 double output = std::get<double>(var->function(particle));
1418 if (std::isnan(output))
return defaultOutput;
1423 B2FATAL(
"Wrong number of arguments for meta function ifNANgiveX");
1429 if (arguments.size() == 1) {
1432 auto func = [var](
const Particle * particle) ->
bool {
return std::isinf(std::get<double>(var->function(particle))); };
1435 B2FATAL(
"Wrong number of arguments for meta function isInfinity");
1441 if (arguments.size() >= 2) {
1447 for (
size_t i = 1; i < arguments.size(); ++i) {
1449 finalMask |= Belle2::convertString<int>(arguments[i]);
1450 }
catch (std::invalid_argument&) {
1451 B2FATAL(
"The input flags to meta function unmask() should be integer!");
1457 auto func = [var, finalMask](
const Particle * particle) ->
double {
1459 auto var_result = var->function(particle);
1460 if (std::holds_alternative<double>(var_result))
1463 if (std::isnan(std::get<double>(var_result))) {
1466 value = int(std::get<double>(var_result));
1467 }
else if (std::holds_alternative<int>(var_result))
1469 value = std::get<int>(var_result);
1473 value &= (~finalMask);
1480 B2FATAL(
"Meta function unmask needs at least two arguments!");
1486 if (arguments.size() == 3) {
1488 std::string cutString = arguments[0];
1494 auto func = [cut, variableIfTrue, variableIfFalse](
const Particle * particle) ->
double {
1495 if (particle ==
nullptr)
1497 if (cut->check(particle))
1499 auto var_result = variableIfTrue->function(particle);
1500 if (std::holds_alternative<double>(var_result)) {
1501 return std::get<double>(var_result);
1502 }
else if (std::holds_alternative<int>(var_result)) {
1503 return std::get<int>(var_result);
1504 }
else if (std::holds_alternative<bool>(var_result)) {
1505 return std::get<bool>(var_result);
1509 auto var_result = variableIfFalse->function(particle);
1510 if (std::holds_alternative<double>(var_result)) {
1511 return std::get<double>(var_result);
1512 }
else if (std::holds_alternative<int>(var_result)) {
1513 return std::get<int>(var_result);
1514 }
else if (std::holds_alternative<bool>(var_result)) {
1515 return std::get<bool>(var_result);
1522 B2FATAL(
"Wrong number of arguments for meta function conditionalVariableSelector");
1528 if (arguments.size() > 0) {
1529 std::vector<const Variable::Manager::Var*> variables;
1530 for (
auto& argument : arguments)
1533 auto func = [variables, arguments](
const Particle * particle) ->
double {
1534 double pValueProduct = 1.;
1535 for (
auto variable : variables)
1537 double pValue = std::get<double>(variable->function(particle));
1541 pValueProduct *= pValue;
1543 double pValueSum = 1.;
1544 double factorial = 1.;
1545 for (
unsigned int i = 1; i < arguments.size(); ++i)
1548 pValueSum += pow(-std::log(pValueProduct), i) / factorial;
1550 return pValueProduct * pValueSum;
1554 B2FATAL(
"Wrong number of arguments for meta function pValueCombination");
1560 if (arguments.size() == 1) {
1562 auto func = [var](
const Particle * particle) ->
double {
1563 auto var_result = var->function(particle);
1564 if (std::holds_alternative<double>(var_result))
1566 return std::abs(std::get<double>(var_result));
1567 }
else if (std::holds_alternative<int>(var_result))
1569 return std::abs(std::get<int>(var_result));
1574 B2FATAL(
"Wrong number of arguments for meta function abs");
1580 if (arguments.size() == 2) {
1585 B2FATAL(
"One or both of the used variables doesn't exist!");
1587 auto func = [var1, var2](
const Particle * particle) ->
double {
1589 auto var_result1 = var1->function(particle);
1590 auto var_result2 = var2->function(particle);
1591 if (std::holds_alternative<double>(var_result1))
1593 val1 = std::get<double>(var_result1);
1594 }
else if (std::holds_alternative<int>(var_result1))
1596 val1 = std::get<int>(var_result1);
1598 if (std::holds_alternative<double>(var_result2))
1600 val2 = std::get<double>(var_result2);
1601 }
else if (std::holds_alternative<int>(var_result2))
1603 val2 = std::get<int>(var_result2);
1605 return std::max(val1, val2);
1609 B2FATAL(
"Wrong number of arguments for meta function max");
1615 if (arguments.size() == 2) {
1620 B2FATAL(
"One or both of the used variables doesn't exist!");
1622 auto func = [var1, var2](
const Particle * particle) ->
double {
1624 auto var_result1 = var1->function(particle);
1625 auto var_result2 = var2->function(particle);
1626 if (std::holds_alternative<double>(var_result1))
1628 val1 = std::get<double>(var_result1);
1629 }
else if (std::holds_alternative<int>(var_result1))
1631 val1 = std::get<int>(var_result1);
1633 if (std::holds_alternative<double>(var_result2))
1635 val2 = std::get<double>(var_result2);
1636 }
else if (std::holds_alternative<int>(var_result2))
1638 val2 = std::get<int>(var_result2);
1640 return std::min(val1, val2);
1644 B2FATAL(
"Wrong number of arguments for meta function min");
1650 if (arguments.size() == 1) {
1652 auto func = [var](
const Particle * particle) ->
double {
1653 auto var_result = var->function(particle);
1654 if (std::holds_alternative<double>(var_result))
1655 return std::sin(std::get<double>(var_result));
1656 else if (std::holds_alternative<int>(var_result))
1657 return std::sin(std::get<int>(var_result));
1662 B2FATAL(
"Wrong number of arguments for meta function sin");
1668 if (arguments.size() == 1) {
1670 auto func = [var](
const Particle * particle) ->
double {
1671 auto var_result = var->function(particle);
1672 if (std::holds_alternative<double>(var_result))
1673 return std::asin(std::get<double>(var_result));
1674 else if (std::holds_alternative<int>(var_result))
1675 return std::asin(std::get<int>(var_result));
1680 B2FATAL(
"Wrong number of arguments for meta function asin");
1686 if (arguments.size() == 1) {
1688 auto func = [var](
const Particle * particle) ->
double {
1689 auto var_result = var->function(particle);
1690 if (std::holds_alternative<double>(var_result))
1691 return std::cos(std::get<double>(var_result));
1692 else if (std::holds_alternative<int>(var_result))
1693 return std::cos(std::get<int>(var_result));
1698 B2FATAL(
"Wrong number of arguments for meta function cos");
1704 if (arguments.size() == 1) {
1706 auto func = [var](
const Particle * particle) ->
double {
1707 auto var_result = var->function(particle);
1708 if (std::holds_alternative<double>(var_result))
1709 return std::acos(std::get<double>(var_result));
1710 else if (std::holds_alternative<int>(var_result))
1711 return std::acos(std::get<int>(var_result));
1716 B2FATAL(
"Wrong number of arguments for meta function acos");
1722 if (arguments.size() == 1) {
1724 auto func = [var](
const Particle * particle) ->
double {
return std::tan(std::get<double>(var->function(particle))); };
1727 B2FATAL(
"Wrong number of arguments for meta function tan");
1733 if (arguments.size() == 1) {
1735 auto func = [var](
const Particle * particle) ->
double {
return std::atan(std::get<double>(var->function(particle))); };
1738 B2FATAL(
"Wrong number of arguments for meta function atan");
1744 if (arguments.size() == 1) {
1746 auto func = [var](
const Particle * particle) ->
double {
1747 auto var_result = var->function(particle);
1748 if (std::holds_alternative<double>(var_result))
1749 return std::exp(std::get<double>(var_result));
1750 else if (std::holds_alternative<int>(var_result))
1751 return std::exp(std::get<int>(var_result));
1756 B2FATAL(
"Wrong number of arguments for meta function exp");
1762 if (arguments.size() == 1) {
1764 auto func = [var](
const Particle * particle) ->
double {
1765 auto var_result = var->function(particle);
1766 if (std::holds_alternative<double>(var_result))
1767 return std::log(std::get<double>(var_result));
1768 else if (std::holds_alternative<int>(var_result))
1769 return std::log(std::get<int>(var_result));
1774 B2FATAL(
"Wrong number of arguments for meta function log");
1780 if (arguments.size() == 1) {
1782 auto func = [var](
const Particle * particle) ->
double {
1783 auto var_result = var->function(particle);
1784 if (std::holds_alternative<double>(var_result))
1785 return std::log10(std::get<double>(var_result));
1786 else if (std::holds_alternative<int>(var_result))
1787 return std::log10(std::get<int>(var_result));
1792 B2FATAL(
"Wrong number of arguments for meta function log10");
1798 if (arguments.size() == 1) {
1800 auto func = [var](
const Particle * particle) ->
double {
1801 if (particle ==
nullptr)
1804 StoreArray<Particle> particles;
1805 if (!particle->hasExtraInfo(
"original_index"))
1808 auto originalParticle = particles[particle->getExtraInfo(
"original_index")];
1809 if (!originalParticle)
1811 auto var_result = var->function(originalParticle);
1812 if (std::holds_alternative<double>(var_result))
1814 return std::get<double>(var_result);
1815 }
else if (std::holds_alternative<int>(var_result))
1817 return std::get<int>(var_result);
1818 }
else if (std::holds_alternative<bool>(var_result))
1820 return std::get<bool>(var_result);
1825 B2FATAL(
"Wrong number of arguments for meta function originalParticle");
1831 if (arguments.size() == 2) {
1832 int daughterNumber = 0;
1834 daughterNumber = Belle2::convertString<int>(arguments[0]);
1835 }
catch (std::invalid_argument&) {
1836 B2FATAL(
"First argument of daughter meta function must be integer!");
1839 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1840 if (particle ==
nullptr)
1842 if (daughterNumber >=
int(particle->getNDaughters()))
1846 auto var_result = var->function(particle->getDaughter(daughterNumber));
1847 if (std::holds_alternative<double>(var_result)) {
1848 return std::get<double>(var_result);
1849 }
else if (std::holds_alternative<int>(var_result)) {
1850 return std::get<int>(var_result);
1851 }
else if (std::holds_alternative<bool>(var_result)) {
1852 return std::get<bool>(var_result);
1858 B2FATAL(
"Wrong number of arguments for meta function daughter");
1864 if (arguments.size() == 2) {
1865 int daughterNumber = 0;
1867 daughterNumber = Belle2::convertString<int>(arguments[0]);
1868 }
catch (std::invalid_argument&) {
1869 B2FATAL(
"First argument of daughter meta function must be integer!");
1872 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1873 if (particle ==
nullptr)
1875 if (daughterNumber >=
int(particle->getNDaughters()))
1879 StoreArray<Particle> particles;
1880 if (!particle->getDaughter(daughterNumber)->hasExtraInfo(
"original_index"))
1882 auto originalDaughter = particles[particle->getDaughter(daughterNumber)->getExtraInfo(
"original_index")];
1883 if (!originalDaughter)
1886 auto var_result = var->function(originalDaughter);
1887 if (std::holds_alternative<double>(var_result)) {
1888 return std::get<double>(var_result);
1889 }
else if (std::holds_alternative<int>(var_result)) {
1890 return std::get<int>(var_result);
1891 }
else if (std::holds_alternative<bool>(var_result)) {
1892 return std::get<bool>(var_result);
1898 B2FATAL(
"Wrong number of arguments for meta function daughter");
1904 if (arguments.size() == 2) {
1905 int daughterNumber = 0;
1907 daughterNumber = Belle2::convertString<int>(arguments[0]);
1908 }
catch (std::invalid_argument&) {
1909 B2FATAL(
"First argument of mcDaughter meta function must be integer!");
1912 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1913 if (particle ==
nullptr)
1915 if (particle->getMCParticle())
1917 if (daughterNumber >=
int(particle->getMCParticle()->getNDaughters())) {
1920 Particle tempParticle = Particle(particle->getMCParticle()->getDaughters().at(daughterNumber));
1921 auto var_result = var->function(&tempParticle);
1922 if (std::holds_alternative<double>(var_result)) {
1923 return std::get<double>(var_result);
1924 }
else if (std::holds_alternative<int>(var_result)) {
1925 return std::get<int>(var_result);
1926 }
else if (std::holds_alternative<bool>(var_result)) {
1927 return std::get<bool>(var_result);
1936 B2FATAL(
"Wrong number of arguments for meta function mcDaughter");
1942 if (arguments.size() == 1) {
1944 auto func = [var](
const Particle * particle) ->
double {
1945 if (particle ==
nullptr)
1947 if (particle->getMCParticle())
1949 if (particle->getMCParticle()->getMother() ==
nullptr) {
1952 Particle tempParticle = Particle(particle->getMCParticle()->getMother());
1953 auto var_result = var->function(&tempParticle);
1954 if (std::holds_alternative<double>(var_result)) {
1955 return std::get<double>(var_result);
1956 }
else if (std::holds_alternative<int>(var_result)) {
1957 return std::get<int>(var_result);
1958 }
else if (std::holds_alternative<bool>(var_result)) {
1959 return std::get<bool>(var_result);
1968 B2FATAL(
"Wrong number of arguments for meta function mcMother");
1974 if (arguments.size() == 2) {
1975 int particleNumber = 0;
1977 particleNumber = Belle2::convertString<int>(arguments[0]);
1978 }
catch (std::invalid_argument&) {
1979 B2FATAL(
"First argument of genParticle meta function must be integer!");
1983 auto func = [var, particleNumber](
const Particle*) ->
double {
1984 StoreArray<MCParticle> mcParticles(
"MCParticles");
1985 if (particleNumber >= mcParticles.getEntries())
1990 MCParticle* mcParticle = mcParticles[particleNumber];
1991 Particle part = Particle(mcParticle);
1992 auto var_result = var->function(&part);
1993 if (std::holds_alternative<double>(var_result))
1995 return std::get<double>(var_result);
1996 }
else if (std::holds_alternative<int>(var_result))
1998 return std::get<int>(var_result);
1999 }
else if (std::holds_alternative<bool>(var_result))
2001 return std::get<bool>(var_result);
2006 B2FATAL(
"Wrong number of arguments for meta function genParticle");
2012 if (arguments.size() == 1) {
2015 auto func = [var](
const Particle*) ->
double {
2016 StoreArray<MCParticle> mcParticles(
"MCParticles");
2017 if (mcParticles.getEntries() == 0)
2022 MCParticle* mcUpsilon4S = mcParticles[0];
2023 if (mcUpsilon4S->isInitial()) mcUpsilon4S = mcParticles[2];
2024 if (mcUpsilon4S->getPDG() != 300553)
2029 Particle upsilon4S = Particle(mcUpsilon4S);
2030 auto var_result = var->function(&upsilon4S);
2031 if (std::holds_alternative<double>(var_result))
2033 return std::get<double>(var_result);
2034 }
else if (std::holds_alternative<int>(var_result))
2036 return std::get<int>(var_result);
2037 }
else if (std::holds_alternative<bool>(var_result))
2039 return std::get<bool>(var_result);
2044 B2FATAL(
"Wrong number of arguments for meta function genUpsilon4S");
2050 if (arguments.size() == 4) {
2051 std::string listName = arguments[0];
2052 std::string rankedVariableName = arguments[1];
2053 std::string returnVariableName = arguments[2];
2054 std::string extraInfoName = rankedVariableName +
"_rank";
2057 rank = Belle2::convertString<int>(arguments[3]);
2058 }
catch (std::invalid_argument&) {
2059 B2ERROR(
"3rd argument of getVariableByRank meta function (Rank) must be an integer!");
2064 auto func = [var, rank, extraInfoName, listName](
const Particle*)->
double {
2065 StoreObjPtr<ParticleList> list(listName);
2067 const unsigned int numParticles = list->getListSize();
2068 for (
unsigned int i = 0; i < numParticles; i++)
2070 const Particle* p = list->getParticle(i);
2071 if (p->getExtraInfo(extraInfoName) == rank) {
2072 auto var_result = var->function(p);
2073 if (std::holds_alternative<double>(var_result)) {
2074 return std::get<double>(var_result);
2075 }
else if (std::holds_alternative<int>(var_result)) {
2076 return std::get<int>(var_result);
2077 }
else if (std::holds_alternative<bool>(var_result)) {
2078 return std::get<bool>(var_result);
2083 return std::numeric_limits<double>::signaling_NaN();
2087 B2FATAL(
"Wrong number of arguments for meta function getVariableByRank");
2093 if (arguments.size() == 1 or arguments.size() == 2) {
2095 std::string listName = arguments[0];
2096 std::string cutString =
"";
2098 if (arguments.size() == 2) {
2099 cutString = arguments[1];
2104 auto func = [listName, cut](
const Particle*) ->
int {
2106 StoreObjPtr<ParticleList> list(listName);
2108 for (
unsigned int i = 0; i < list->getListSize(); i++)
2110 const Particle* particle = list->getParticle(i);
2111 if (cut->check(particle)) {
2119 B2FATAL(
"Wrong number of arguments for meta function countInList");
2125 if (arguments.size() == 2 or arguments.size() == 3) {
2127 std::string roeListName = arguments[0];
2128 std::string cutString = arguments[1];
2130 if (arguments.size() == 2) {
2131 B2INFO(
"Use pdgCode of electron as default in meta variable veto, other arguments: " << roeListName <<
", " << cutString);
2134 pdgCode = Belle2::convertString<int>(arguments[2]);;
2135 }
catch (std::invalid_argument&) {
2136 B2FATAL(
"Third argument of veto meta function must be integer!");
2143 auto func = [roeListName, cut, pdgCode, flavourType](
const Particle * particle) ->
bool {
2144 StoreObjPtr<ParticleList> roeList(roeListName);
2145 ROOT::Math::PxPyPzEVector vec = particle->get4Vector();
2146 for (
unsigned int i = 0; i < roeList->getListSize(); i++)
2148 const Particle* roeParticle = roeList->getParticle(i);
2149 if (not particle->overlapsWith(roeParticle)) {
2150 ROOT::Math::PxPyPzEVector tempCombination = roeParticle->get4Vector() + vec;
2151 std::vector<int> indices = { particle->getArrayIndex(), roeParticle->getArrayIndex() };
2152 Particle tempParticle = Particle(tempCombination, pdgCode, flavourType, indices, particle->getArrayPointer());
2153 if (cut->check(&tempParticle)) {
2162 B2FATAL(
"Wrong number of arguments for meta function veto");
2168 if (arguments.size() == 1) {
2169 std::string cutString = arguments[0];
2171 auto func = [cut](
const Particle * particle) ->
int {
2173 for (
auto& daughter : particle->getDaughters())
2175 if (cut->check(daughter))
2182 B2FATAL(
"Wrong number of arguments for meta function countDaughters");
2188 if (arguments.size() == 1) {
2189 std::string cutString = arguments[0];
2191 auto func = [cut](
const Particle * particle) ->
int {
2193 std::vector<const Particle*> fspDaughters;
2194 particle->fillFSPDaughters(fspDaughters);
2197 for (
auto& daughter : fspDaughters)
2199 if (cut->check(daughter))
2206 B2FATAL(
"Wrong number of arguments for meta function countFSPDaughters");
2212 if (arguments.size() == 1) {
2213 std::string cutString = arguments[0];
2215 auto func = [cut](
const Particle * particle) ->
int {
2217 std::vector<const Particle*> allDaughters;
2218 particle->fillAllDaughters(allDaughters);
2221 for (
auto& daughter : allDaughters)
2223 if (cut->check(daughter))
2230 B2FATAL(
"Wrong number of arguments for meta function countDescendants");
2234 Manager::FunctionPtr numberOfNonOverlappingParticles(
const std::vector<std::string>& arguments)
2237 auto func = [arguments](
const Particle * particle) ->
int {
2239 int _numberOfNonOverlappingParticles = 0;
2240 for (
const auto& listName : arguments)
2242 StoreObjPtr<ParticleList> list(listName);
2243 if (not list.isValid()) {
2244 B2FATAL(
"Invalid list named " << listName <<
" encountered in numberOfNonOverlappingParticles.");
2246 for (
unsigned int i = 0; i < list->getListSize(); i++) {
2247 const Particle* p = list->getParticle(i);
2248 if (not particle->overlapsWith(p)) {
2249 _numberOfNonOverlappingParticles++;
2253 return _numberOfNonOverlappingParticles;
2260 void appendDaughtersRecursive(Particle* mother)
2263 auto* mcmother = mother->getRelated<MCParticle>();
2268 std::vector<MCParticle*> mcdaughters = mcmother->
getDaughters();
2269 StoreArray<Particle> particles;
2271 for (
auto& mcdaughter : mcdaughters) {
2273 Particle tmp_daughter(mcdaughter);
2274 Particle* new_daughter = particles.appendNew(tmp_daughter);
2275 new_daughter->addRelationTo(mcdaughter);
2276 mother->appendDaughter(new_daughter,
false);
2278 if (mcdaughter->getNDaughters() > 0)
2279 appendDaughtersRecursive(new_daughter);
2286 if (arguments.size() == 1) {
2288 auto func = [var](
const Particle * particle) ->
double {
2294 Particle tmpPart(mcp);
2295 StoreArray<Particle> particles;
2296 Particle* newPart = particles.appendNew(tmpPart);
2297 newPart->addRelationTo(mcp);
2299 appendDaughtersRecursive(newPart);
2301 auto var_result = var->function(newPart);
2302 if (std::holds_alternative<double>(var_result))
2304 return std::get<double>(var_result);
2305 }
else if (std::holds_alternative<int>(var_result))
2307 return std::get<int>(var_result);
2308 }
else if (std::holds_alternative<bool>(var_result))
2310 return std::get<bool>(var_result);
2315 B2FATAL(
"Wrong number of arguments for meta function matchedMC");
2321 if (arguments.size() == 1) {
2324 auto func = [var](
const Particle * particle) ->
double {
2326 const ECLCluster* cluster = particle->getECLCluster();
2329 auto mcps = cluster->getRelationsTo<MCParticle>();
2332 std::vector<std::pair<double, int>> weightsAndIndices;
2333 for (
unsigned int i = 0; i < mcps.size(); ++i)
2334 weightsAndIndices.emplace_back(mcps.weight(i), i);
2337 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
2338 ValueIndexPairSorting::higherPair<
decltype(weightsAndIndices)::value_type>);
2341 const MCParticle* mcp = mcps.object(weightsAndIndices[0].second);
2343 Particle tmpPart(mcp);
2344 StoreArray<Particle> particles;
2345 Particle* newPart = particles.appendNew(tmpPart);
2346 newPart->addRelationTo(mcp);
2348 appendDaughtersRecursive(newPart);
2350 auto var_result = var->function(newPart);
2351 if (std::holds_alternative<double>(var_result))
2353 return std::get<double>(var_result);
2354 }
else if (std::holds_alternative<int>(var_result))
2356 return std::get<int>(var_result);
2357 }
else if (std::holds_alternative<bool>(var_result))
2359 return std::get<bool>(var_result);
2368 B2FATAL(
"Wrong number of arguments for meta function clusterBestMatchedMCParticle");
2374 if (arguments.size() == 1) {
2377 auto func = [var](
const Particle * particle) ->
double {
2379 const ECLCluster* cluster = particle->getECLCluster();
2382 auto mcps = cluster->getRelationsTo<MCParticle>();
2385 std::map<int, double> mapMCParticleIndxAndWeight;
2386 getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
2389 if (mapMCParticleIndxAndWeight.size() == 0)
2393 auto maxMap = std::max_element(mapMCParticleIndxAndWeight.begin(), mapMCParticleIndxAndWeight.end(),
2394 [](
const auto & x,
const auto & y) { return x.second < y.second; }
2397 StoreArray<MCParticle> mcparticles;
2398 const MCParticle* mcKlong = mcparticles[maxMap->first];
2400 Particle tmpPart(mcKlong);
2401 auto var_result = var->function(&tmpPart);
2402 if (std::holds_alternative<double>(var_result))
2404 return std::get<double>(var_result);
2405 }
else if (std::holds_alternative<int>(var_result))
2407 return std::get<int>(var_result);
2408 }
else if (std::holds_alternative<bool>(var_result))
2410 return std::get<bool>(var_result);
2419 B2FATAL(
"Wrong number of arguments for meta function clusterBestMatchedMCKlong");
2423 double matchedMCHasPDG(
const Particle* particle,
const std::vector<double>& pdgCode)
2425 if (pdgCode.size() != 1) {
2426 B2FATAL(
"Too many arguments provided to matchedMCHasPDG!");
2428 int inputPDG = std::lround(pdgCode[0]);
2434 return std::abs(mcp->getPDG()) == inputPDG;
2439 if (arguments.size() == 1) {
2440 std::string listName = arguments[0];
2441 auto func = [listName](
const Particle * particle) ->
double {
2444 StoreObjPtr<ParticleList> listOfParticles(listName);
2446 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2447 double totalEnergy = 0;
2448 int nParticles = listOfParticles->getListSize();
2449 for (
int i = 0; i < nParticles; i++)
2451 const Particle* part = listOfParticles->getParticle(i);
2453 totalEnergy += frame.getMomentum(part).E();
2460 B2FATAL(
"Wrong number of arguments for meta function totalEnergyOfParticlesInList");
2466 if (arguments.size() == 1) {
2467 std::string listName = arguments[0];
2468 auto func = [listName](
const Particle*) ->
double {
2469 StoreObjPtr<ParticleList> listOfParticles(listName);
2471 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPxOfParticlesInList");
2473 int nParticles = listOfParticles->getListSize();
2475 for (
int i = 0; i < nParticles; i++)
2477 const Particle* part = listOfParticles->getParticle(i);
2478 totalPx += frame.getMomentum(part).Px();
2484 B2FATAL(
"Wrong number of arguments for meta function totalPxOfParticlesInList");
2490 if (arguments.size() == 1) {
2491 std::string listName = arguments[0];
2492 auto func = [listName](
const Particle*) ->
double {
2493 StoreObjPtr<ParticleList> listOfParticles(listName);
2495 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPyOfParticlesInList");
2497 int nParticles = listOfParticles->getListSize();
2499 for (
int i = 0; i < nParticles; i++)
2501 const Particle* part = listOfParticles->getParticle(i);
2502 totalPy += frame.getMomentum(part).Py();
2508 B2FATAL(
"Wrong number of arguments for meta function totalPyOfParticlesInList");
2514 if (arguments.size() == 1) {
2515 std::string listName = arguments[0];
2516 auto func = [listName](
const Particle*) ->
double {
2517 StoreObjPtr<ParticleList> listOfParticles(listName);
2519 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPzOfParticlesInList");
2521 int nParticles = listOfParticles->getListSize();
2523 for (
int i = 0; i < nParticles; i++)
2525 const Particle* part = listOfParticles->getParticle(i);
2526 totalPz += frame.getMomentum(part).Pz();
2532 B2FATAL(
"Wrong number of arguments for meta function totalPzOfParticlesInList");
2538 if (arguments.size() > 0) {
2540 auto func = [arguments](
const Particle * particle) ->
double {
2542 ROOT::Math::PxPyPzEVector total4Vector;
2544 std::vector<Particle*> particlePool;
2547 for (
const auto& argument : arguments)
2549 StoreObjPtr <ParticleList> listOfParticles(argument);
2551 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << argument <<
" given to invMassInLists");
2552 int nParticles = listOfParticles->getListSize();
2553 for (
int i = 0; i < nParticles; i++) {
2554 bool overlaps =
false;
2555 Particle* part = listOfParticles->getParticle(i);
2556 for (
auto poolPart : particlePool) {
2557 if (part->overlapsWith(poolPart)) {
2563 total4Vector += part->get4Vector();
2564 particlePool.push_back(part);
2568 double invariantMass = total4Vector.M();
2569 return invariantMass;
2574 B2FATAL(
"Wrong number of arguments for meta function invMassInLists");
2578 Manager::FunctionPtr totalECLEnergyOfParticlesInList(
const std::vector<std::string>& arguments)
2580 if (arguments.size() == 1) {
2581 std::string listName = arguments[0];
2582 auto func = [listName](
const Particle * particle) ->
double {
2585 StoreObjPtr<ParticleList> listOfParticles(listName);
2587 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2588 double totalEnergy = 0;
2589 int nParticles = listOfParticles->getListSize();
2590 for (
int i = 0; i < nParticles; i++)
2592 const Particle* part = listOfParticles->getParticle(i);
2593 const ECLCluster* cluster = part->getECLCluster();
2595 if (cluster !=
nullptr) {
2596 totalEnergy += cluster->getEnergy(clusterHypothesis);
2604 B2FATAL(
"Wrong number of arguments for meta function totalECLEnergyOfParticlesInList");
2610 if (arguments.size() == 1) {
2611 std::string listName = arguments[0];
2612 auto func = [listName](
const Particle*) ->
double {
2613 StoreObjPtr<ParticleList> listOfParticles(listName);
2615 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxPtInList");
2616 int nParticles = listOfParticles->getListSize();
2619 for (
int i = 0; i < nParticles; i++)
2621 const Particle* part = listOfParticles->getParticle(i);
2622 const double Pt = frame.getMomentum(part).Pt();
2623 if (Pt > maxPt) maxPt = Pt;
2629 B2FATAL(
"Wrong number of arguments for meta function maxPtInList");
2633 Manager::FunctionPtr eclClusterTrackMatchedWithCondition(
const std::vector<std::string>& arguments)
2635 if (arguments.size() <= 1) {
2637 std::string cutString;
2638 if (arguments.size() == 1)
2639 cutString = arguments[0];
2641 auto func = [cut](
const Particle * particle) ->
double {
2643 if (particle ==
nullptr)
2646 const ECLCluster* cluster = particle->getECLCluster();
2650 auto tracks = cluster->getRelationsFrom<Track>();
2652 for (
const auto& track : tracks) {
2655 if (cut->check(&trackParticle))
2664 B2FATAL(
"Wrong number of arguments for meta function eclClusterSpecialTrackMatched");
2670 if (arguments.size() == 2) {
2671 std::string listName = arguments[0];
2674 auto func = [listName, var](
const Particle*) ->
double {
2675 StoreObjPtr<ParticleList> listOfParticles(listName);
2677 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to averageValueInList");
2678 int nParticles = listOfParticles->getListSize();
2679 if (nParticles == 0)
2684 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2686 for (
int i = 0; i < nParticles; i++) {
2687 average += std::get<double>(var->function(listOfParticles->getParticle(i))) / nParticles;
2689 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2691 for (
int i = 0; i < nParticles; i++) {
2692 average += std::get<int>(var->function(listOfParticles->getParticle(i))) / nParticles;
2699 B2FATAL(
"Wrong number of arguments for meta function averageValueInList");
2705 if (arguments.size() == 2) {
2706 std::string listName = arguments[0];
2709 auto func = [listName, var](
const Particle*) ->
double {
2710 StoreObjPtr<ParticleList> listOfParticles(listName);
2712 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to medianValueInList");
2713 int nParticles = listOfParticles->getListSize();
2714 if (nParticles == 0)
2718 std::vector<double> valuesInList;
2719 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2721 for (
int i = 0; i < nParticles; i++) {
2722 valuesInList.push_back(std::get<double>(var->function(listOfParticles->getParticle(i))));
2724 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2726 for (
int i = 0; i < nParticles; i++) {
2727 valuesInList.push_back(std::get<int>(var->function(listOfParticles->getParticle(i))));
2730 std::sort(valuesInList.begin(), valuesInList.end());
2731 if (nParticles % 2 != 0)
2733 return valuesInList[nParticles / 2];
2736 return 0.5 * (valuesInList[nParticles / 2] + valuesInList[nParticles / 2 - 1]);
2741 B2FATAL(
"Wrong number of arguments for meta function medianValueInList");
2747 if (arguments.size() == 2) {
2748 std::string listName = arguments[0];
2751 auto func = [listName, var](
const Particle*) ->
double {
2752 StoreObjPtr<ParticleList> listOfParticles(listName);
2754 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to sumValueInList");
2755 int nParticles = listOfParticles->getListSize();
2756 if (nParticles == 0)
2761 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2763 for (
int i = 0; i < nParticles; i++) {
2764 sum += std::get<double>(var->function(listOfParticles->getParticle(i)));
2766 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2768 for (
int i = 0; i < nParticles; i++) {
2769 sum += std::get<int>(var->function(listOfParticles->getParticle(i)));
2776 B2FATAL(
"Wrong number of arguments for meta function sumValueInList");
2782 if (arguments.size() == 2) {
2783 std::string listName = arguments[0];
2786 auto func = [listName, var](
const Particle*) ->
double {
2787 StoreObjPtr<ParticleList> listOfParticles(listName);
2789 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to productValueInList");
2790 int nParticles = listOfParticles->getListSize();
2791 if (nParticles == 0)
2796 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2798 for (
int i = 0; i < nParticles; i++) {
2799 product *= std::get<double>(var->function(listOfParticles->getParticle(i)));
2801 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2803 for (
int i = 0; i < nParticles; i++) {
2804 product *= std::get<int>(var->function(listOfParticles->getParticle(i)));
2811 B2FATAL(
"Wrong number of arguments for meta function productValueInList");
2818 if (arguments.size() != 1)
2819 B2FATAL(
"Wrong number of arguments for meta function angleToClosestInList");
2821 std::string listname = arguments[0];
2823 auto func = [listname](
const Particle * particle) ->
double {
2825 StoreObjPtr<ParticleList> list(listname);
2826 if (not list.isValid())
2827 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToClosestInList");
2830 if (list->getListSize() == 0)
2835 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2838 double minAngle = 2 * M_PI;
2839 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2841 const Particle* compareme = list->getParticle(i);
2842 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2843 double angle = p_compare.Angle(p_this);
2844 if (minAngle > angle) minAngle = angle;
2854 if (arguments.size() != 2)
2855 B2FATAL(
"Wrong number of arguments for meta function closestInList");
2857 std::string listname = arguments[0];
2862 auto func = [listname, var](
const Particle * particle) ->
double {
2864 StoreObjPtr<ParticleList> list(listname);
2865 if (not list.isValid())
2866 B2FATAL(
"Invalid particle list name " << listname <<
" given to closestInList");
2870 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2873 double minAngle = 2 * M_PI;
2875 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2877 const Particle* compareme = list->getParticle(i);
2878 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2879 double angle = p_compare.Angle(p_this);
2880 if (minAngle > angle) {
2888 auto var_result = var->function(list->getParticle(iClosest));
2889 if (std::holds_alternative<double>(var_result))
2891 return std::get<double>(var_result);
2892 }
else if (std::holds_alternative<int>(var_result))
2894 return std::get<int>(var_result);
2895 }
else if (std::holds_alternative<bool>(var_result))
2897 return std::get<bool>(var_result);
2906 if (arguments.size() != 1)
2907 B2FATAL(
"Wrong number of arguments for meta function angleToMostB2BInList");
2909 std::string listname = arguments[0];
2911 auto func = [listname](
const Particle * particle) ->
double {
2913 StoreObjPtr<ParticleList> list(listname);
2914 if (not list.isValid())
2915 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToMostB2BInList");
2918 if (list->getListSize() == 0)
2923 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2927 double maxAngle = 0;
2928 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2930 const Particle* compareme = list->getParticle(i);
2931 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2932 double angle = p_compare.Angle(p_this);
2933 if (maxAngle < angle) maxAngle = angle;
2943 if (arguments.size() != 1)
2944 B2FATAL(
"Wrong number of arguments for meta function deltaPhiToMostB2BPhiInList");
2946 std::string listname = arguments[0];
2948 auto func = [listname](
const Particle * particle) ->
double {
2950 StoreObjPtr<ParticleList> list(listname);
2951 if (not list.isValid())
2952 B2FATAL(
"Invalid particle list name " << listname <<
" given to deltaPhiToMostB2BPhiInList");
2955 if (list->getListSize() == 0)
2960 const auto phi_this = frame.getMomentum(particle).Phi();
2963 double maxAngle = 0;
2964 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2966 const Particle* compareme = list->getParticle(i);
2967 const auto phi_compare = frame.getMomentum(compareme).Phi();
2968 double angle = std::abs(phi_compare - phi_this);
2969 if (angle > M_PI) {angle = 2 * M_PI - angle;}
2970 if (maxAngle < angle) maxAngle = angle;
2980 if (arguments.size() != 2)
2981 B2FATAL(
"Wrong number of arguments for meta function mostB2BInList");
2983 std::string listname = arguments[0];
2988 auto func = [listname, var](
const Particle * particle) ->
double {
2990 StoreObjPtr<ParticleList> list(listname);
2991 if (not list.isValid())
2992 B2FATAL(
"Invalid particle list name " << listname <<
" given to mostB2BInList");
2996 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
3000 double maxAngle = -1.0;
3002 for (
unsigned int i = 0; i < list->getListSize(); ++i)
3004 const Particle* compareme = list->getParticle(i);
3005 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
3006 double angle = p_compare.Angle(p_this);
3007 if (maxAngle < angle) {
3015 auto var_result = var->function(list->getParticle(iMostB2B));
3016 if (std::holds_alternative<double>(var_result))
3018 return std::get<double>(var_result);
3019 }
else if (std::holds_alternative<int>(var_result))
3021 return std::get<int>(var_result);
3022 }
else if (std::holds_alternative<bool>(var_result))
3024 return std::get<bool>(var_result);
3032 if (arguments.size() == 1) {
3033 std::string listName = arguments[0];
3034 auto func = [listName](
const Particle*) ->
double {
3035 StoreObjPtr<ParticleList> listOfParticles(listName);
3037 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxOpeningAngleInList");
3038 int nParticles = listOfParticles->getListSize();
3043 double maxOpeningAngle = -1;
3044 for (
int i = 0; i < nParticles; i++)
3046 B2Vector3D v1 = frame.getMomentum(listOfParticles->getParticle(i)).Vect();
3047 for (
int j = i + 1; j < nParticles; j++) {
3048 B2Vector3D v2 = frame.getMomentum(listOfParticles->getParticle(j)).Vect();
3049 const double angle = v1.
Angle(v2);
3050 if (angle > maxOpeningAngle) maxOpeningAngle = angle;
3053 return maxOpeningAngle;
3057 B2FATAL(
"Wrong number of arguments for meta function maxOpeningAngleInList");
3064 if (arguments.size() >= 2) {
3069 auto func = [var, arguments](
const Particle * particle) ->
double {
3070 if (particle ==
nullptr)
3072 B2WARNING(
"Trying to access a daughter that does not exist. Skipping");
3078 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
3082 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++)
3084 auto generalizedIndex = arguments[iCoord];
3085 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
3087 pSum += frame.getMomentum(dauPart);
3089 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
3095 Particle sumOfDaughters(pSum, 100);
3097 auto var_result = var->function(&sumOfDaughters);
3099 if (std::holds_alternative<double>(var_result))
3101 return std::get<double>(var_result);
3102 }
else if (std::holds_alternative<int>(var_result))
3104 return std::get<int>(var_result);
3105 }
else if (std::holds_alternative<bool>(var_result))
3107 return std::get<bool>(var_result);
3112 B2FATAL(
"Wrong number of arguments for meta function daughterCombination");
3115 Manager::FunctionPtr useAlternativeDaughterHypothesis(
const std::vector<std::string>& arguments)
3128 if (arguments.size() >= 2) {
3139 std::unordered_map<unsigned int, int> mapOfReplacedDaughters;
3142 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++) {
3143 auto replacedDauString = arguments[iCoord];
3145 std::vector<std::string> indexAndMass;
3146 boost::split(indexAndMass, replacedDauString, boost::is_any_of(
":"));
3149 if (indexAndMass.size() > 2) {
3150 B2WARNING(
"The string indicating which daughter's mass should be replaced contains more than two elements separated by a colon. Perhaps you tried to pass a generalized index, which is not supported yet for this variable. The offending string is "
3151 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
3155 if (indexAndMass.size() < 2) {
3156 B2WARNING(
"The string indicating which daughter's mass should be replaced contains only one colon-separated element instead of two. The offending string is "
3157 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
3164 dauIndex = Belle2::convertString<int>(indexAndMass[0]);
3165 }
catch (std::invalid_argument&) {
3166 B2FATAL(
"Found the string " << indexAndMass[0] <<
"instead of a daughter index.");
3170 TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(indexAndMass[1].c_str());
3172 B2WARNING(
"Particle not in evt.pdl file! " << indexAndMass[1]);
3177 int pdgCode = particlePDG->PdgCode();
3178 mapOfReplacedDaughters[dauIndex] = pdgCode;
3182 if (mapOfReplacedDaughters.size() != arguments.size() - 1)
3183 B2FATAL(
"Overlapped daughter's index is detected in the meta-variable useAlternativeDaughterHypothesis");
3191 auto func = [var, mapOfReplacedDaughters](
const Particle * particle) ->
double {
3192 if (particle ==
nullptr)
3194 B2WARNING(
"Trying to access a particle that does not exist. Skipping");
3204 ROOT::Math::PxPyPzMVector pSum(0, 0, 0, 0);
3206 for (
unsigned int iDau = 0; iDau < particle->getNDaughters(); iDau++)
3208 const Particle* dauPart = particle->getDaughter(iDau);
3210 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << iDau);
3214 ROOT::Math::PxPyPzMVector dauMom = ROOT::Math::PxPyPzMVector(frame.getMomentum(dauPart));
3218 pdgCode = mapOfReplacedDaughters.at(iDau);
3219 }
catch (std::out_of_range&) {
3226 double p_x = dauMom.Px();
3227 double p_y = dauMom.Py();
3228 double p_z = dauMom.Pz();
3229 dauMom.SetCoordinates(p_x, p_y, p_z, TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass());
3230 const_cast<Particle*
>(dummy->getDaughter(iDau))->set4VectorDividingByMomentumScaling(ROOT::Math::PxPyPzEVector(dauMom));
3233 const int charge = dummy->getDaughter(iDau)->getCharge();
3234 if (TDatabasePDG::Instance()->GetParticle(pdgCode)->Charge() / 3.0 ==
charge)
3235 const_cast<Particle*
>(dummy->getDaughter(iDau))->setPDGCode(pdgCode);
3237 const_cast<Particle*
>(dummy->getDaughter(iDau))->setPDGCode(-1 * pdgCode);
3243 dummy->set4Vector(ROOT::Math::PxPyPzEVector(pSum));
3245 auto var_result = var->function(dummy);
3248 if (std::holds_alternative<double>(var_result))
3250 return std::get<double>(var_result);
3251 }
else if (std::holds_alternative<int>(var_result))
3253 return std::get<int>(var_result);
3254 }
else if (std::holds_alternative<bool>(var_result))
3256 return std::get<bool>(var_result);
3262 B2FATAL(
"Wrong number of arguments for meta function useAlternativeDaughterHypothesis");
3267 if (arguments.size() == 2) {
3269 std::string arg = arguments[0];
3271 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
3273 if (part !=
nullptr) {
3274 pdg_code = std::abs(part->PdgCode());
3277 pdg_code = Belle2::convertString<int>(arg);
3278 }
catch (std::exception& e) {}
3281 if (pdg_code == -1) {
3282 B2FATAL(
"Ancestor " + arg +
" is not recognised. Please provide valid PDG code or particle name.");
3285 auto func = [pdg_code, var](
const Particle * particle) ->
double {
3286 const Particle* p = particle;
3288 int ancestor_level = std::get<double>(
Manager::Instance().getVariable(
"hasAncestor(" + std::to_string(pdg_code) +
", 0)")->function(p));
3289 if ((ancestor_level <= 0) or (std::isnan(ancestor_level)))
3294 const MCParticle* i_p = p->getMCParticle();
3296 for (
int a = 0; a < ancestor_level ; a = a + 1)
3298 i_p = i_p->getMother();
3302 StoreArray<Particle> particles;
3303 Particle* newPart = particles.appendNew(m_p);
3304 newPart->addRelationTo(i_p);
3306 appendDaughtersRecursive(newPart);
3308 auto var_result = var->function(newPart);
3309 if (std::holds_alternative<double>(var_result))
3311 return std::get<double>(var_result);
3312 }
else if (std::holds_alternative<int>(var_result))
3314 return std::get<int>(var_result);
3315 }
else if (std::holds_alternative<bool>(var_result))
3317 return std::get<bool>(var_result);
3322 B2FATAL(
"Wrong number of arguments for meta function varForFirstMCAncestorOfType (expected 2: type and variable of interest)");
3328 if (arguments.size() != 1) {
3329 B2FATAL(
"Number of arguments for nTrackFitResults must be 1, particleType or PDGcode");
3332 std::string arg = arguments[0];
3333 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
3335 if (part !=
nullptr) {
3336 absPdg = std::abs(part->PdgCode());
3339 absPdg = Belle2::convertString<int>(arg);
3340 }
catch (std::exception& e) {}
3343 auto func = [absPdg](
const Particle*) ->
int {
3345 Const::ChargedStable type(absPdg);
3346 StoreArray<Track> tracks;
3348 int nTrackFitResults = 0;
3350 for (
int i = 0; i < tracks.getEntries(); i++)
3352 const Track* track = tracks[i];
3353 const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(type);
3355 if (!trackFit)
continue;
3356 if (trackFit->getChargeSign() == 0)
continue;
3361 return nTrackFitResults;
3367 VARIABLE_GROUP(
"MetaFunctions");
3368 REGISTER_METAVARIABLE(
"nCleanedECLClusters(cut)", nCleanedECLClusters,
3369 "[Eventbased] Returns the number of clean Clusters in the event\n"
3370 "Clean clusters are defined by the clusters which pass the given cut assuming a photon hypothesis.",
3371 Manager::VariableDataType::c_int);
3372 REGISTER_METAVARIABLE(
"nCleanedTracks(cut)", nCleanedTracks,
3373 "[Eventbased] Returns the number of clean Tracks in the event\n"
3374 "Clean tracks are defined by the tracks which pass the given cut assuming a pion hypothesis.", Manager::VariableDataType::c_int);
3375 REGISTER_METAVARIABLE(
"formula(v1 + v2 * [v3 - v4] / v5^v6)", formula, R
"DOCSTRING(
3376Returns the result of the given formula, where v1 to vN are variables or floating
3377point numbers. Currently the only supported operations are addition (``+``),
3378subtraction (``-``), multiplication (``*``), division (``/``) and power (``^``
3379or ``**``). Parenthesis can be in the form of square brackets ``[v1 * v2]``
3380or normal brackets ``(v1 * v2)``. It will work also with variables taking
3381arguments. Operator precedence is taken into account. For example ::
3383 (daughter(0, E) + daughter(1, E))**2 - p**2 + 0.138
3385.. versionchanged:: release-03-00-00
3386 now both, ``[]`` and ``()`` can be used for grouping operations, ``**`` can
3387 be used for exponent and float literals are possible directly in the
3389)DOCSTRING", Manager::VariableDataType::c_double);
3390 REGISTER_METAVARIABLE("useRestFrame(variable)", useRestFrame,
3391 "Returns the value of the variable using the rest frame of the given particle as current reference frame.\n"
3392 "E.g. ``useRestFrame(daughter(0, p))`` returns the total momentum of the first daughter in its mother's rest-frame", Manager::VariableDataType::c_double);
3393 REGISTER_METAVARIABLE(
"useCMSFrame(variable)", useCMSFrame,
3394 "Returns the value of the variable using the CMS frame as current reference frame.\n"
3395 "E.g. ``useCMSFrame(E)`` returns the energy of a particle in the CMS frame.", Manager::VariableDataType::c_double);
3396 REGISTER_METAVARIABLE(
"useLabFrame(variable)", useLabFrame, R
"DOC(
3397Returns the value of ``variable`` in the *lab* frame.
3400 The lab frame is the default reference frame, usually you don't need to use this meta-variable.
3401 E.g. ``useLabFrame(E)`` returns the energy of a particle in the Lab frame, same as just ``E``.
3403Specifying the lab frame is useful in some corner-cases. For example:
3404``useRestFrame(daughter(0, formula(E - useLabFrame(E))))`` which is the difference of the first daughter's energy in the rest frame of the mother (current particle) with the same daughter's lab-frame energy.
3405)DOC", Manager::VariableDataType::c_double);
3406 REGISTER_METAVARIABLE("useTagSideRecoilRestFrame(variable, daughterIndexTagB)", useTagSideRecoilRestFrame,
3407 "Returns the value of the variable in the rest frame of the recoiling particle to the tag side B meson.\n"
3408 "The variable should only be applied to an Upsilon(4S) list.\n"
3409 "E.g. ``useTagSideRecoilRestFrame(daughter(1, daughter(1, p)), 0)`` applied on a Upsilon(4S) list (``Upsilon(4S)->B+:tag B-:sig``) returns the momentum of the second daughter of the signal B meson in the signal B meson rest frame.", Manager::VariableDataType::c_double);
3410 REGISTER_METAVARIABLE(
"useParticleRestFrame(variable, particleList)", useParticleRestFrame,
3411 "Returns the value of the variable in the rest frame of the first Particle contained in the given ParticleList.\n"
3412 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
3413 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
3414 "computing the rest frame and a warning is thrown. If the given ParticleList is empty in an event, it returns NaN.", Manager::VariableDataType::c_double);
3415 REGISTER_METAVARIABLE(
"useRecoilParticleRestFrame(variable, particleList)", useRecoilParticleRestFrame,
3416 "Returns the value of the variable in the rest frame of recoil system against the first Particle contained in the given ParticleList.\n"
3417 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
3418 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
3419 "computing the rest frame and a warning is thrown. If the given ParticleList is empty in an event, it returns NaN.", Manager::VariableDataType::c_double);
3420 REGISTER_METAVARIABLE(
"useDaughterRestFrame(variable, daughterIndex_1, [daughterIndex_2, ... daughterIndex_3])", useDaughterRestFrame,
3421 "Returns the value of the variable in the rest frame of the selected daughter particle.\n"
3422 "The daughter is identified via generalized daughter index, e.g. ``0:1`` identifies the second daughter (1) "
3423 "of the first daughter (0). If the daughter index is invalid, it returns NaN.\n"
3424 "If two or more indices are given, the rest frame of the sum of the daughters is used.",
3425 Manager::VariableDataType::c_double);
3426 REGISTER_METAVARIABLE(
"passesCut(cut)", passesCut,
3427 "Returns 1 if particle passes the cut otherwise 0.\n"
3428 "Useful if you want to write out if a particle would have passed a cut or not.", Manager::VariableDataType::c_bool);
3429 REGISTER_METAVARIABLE(
"passesEventCut(cut)", passesEventCut,
3430 "[Eventbased] Returns 1 if event passes the cut otherwise 0.\n"
3431 "Useful if you want to select events passing a cut without looping into particles, such as for skimming.\n", Manager::VariableDataType::c_bool);
3432 REGISTER_METAVARIABLE(
"countDaughters(cut)", countDaughters,
3433 "Returns number of direct daughters which satisfy the cut.\n"
3434 "Used by the skimming package (for what exactly?)", Manager::VariableDataType::c_int);
3435 REGISTER_METAVARIABLE(
"countFSPDaughters(cut)", countDescendants,
3436 "Returns number of final-state daughters which satisfy the cut.",
3437 Manager::VariableDataType::c_int);
3438 REGISTER_METAVARIABLE(
"countDescendants(cut)", countDescendants,
3439 "Returns number of descendants for all generations which satisfy the cut.",
3440 Manager::VariableDataType::c_int);
3441 REGISTER_METAVARIABLE(
"varFor(pdgCode, variable)", varFor,
3442 "Returns the value of the variable for the given particle if its abs(pdgCode) agrees with the given one.\n"
3443 "E.g. ``varFor(11, p)`` returns the momentum if the particle is an electron or a positron.", Manager::VariableDataType::c_double);
3444 REGISTER_METAVARIABLE(
"varForMCGen(variable)", varForMCGen,
3445 "Returns the value of the variable for the given particle if the MC particle related to it is primary, not virtual, and not initial.\n"
3446 "If no MC particle is related to the given particle, or the MC particle is not primary, virtual, or initial, NaN will be returned.\n"
3447 "E.g. ``varForMCGen(PDG)`` returns the PDG code of the MC particle related to the given particle if it is primary, not virtual, and not initial.", Manager::VariableDataType::c_double);
3448 REGISTER_METAVARIABLE(
"nParticlesInList(particleListName)", nParticlesInList,
3449 "[Eventbased] Returns number of particles in the given particle List.", Manager::VariableDataType::c_int);
3450 REGISTER_METAVARIABLE(
"isInList(particleListName)", isInList,
3451 "Returns 1 if the particle is in the list provided, 0 if not. Note that this only checks the particle given. For daughters of composite particles, please see :b2:var:`isDaughterOfList`.", Manager::VariableDataType::c_bool);
3452 REGISTER_METAVARIABLE(
"isDaughterOfList(particleListNames)", isDaughterOfList,
3453 "Returns 1 if the given particle is a daughter of at least one of the particles in the given particle Lists.", Manager::VariableDataType::c_bool);
3454 REGISTER_METAVARIABLE(
"isDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isDescendantOfList, R
"DOC(
3455 Returns 1 if the given particle appears in the decay chain of the particles in the given ParticleLists.
3457 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
3459 * ``isDescendantOfList(<particle_list>,1)`` returns 1 if particle is a daughter of the list,
3460 * ``isDescendantOfList(<particle_list>,2)`` returns 1 if particle is a granddaughter of the list,
3461 * ``isDescendantOfList(<particle_list>,3)`` returns 1 if particle is a great-granddaughter of the list, etc.
3462 * Default value is ``-1`` that is inclusive for all generations.
3463 )DOC", Manager::VariableDataType::c_bool);
3464 REGISTER_METAVARIABLE("isMCDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isMCDescendantOfList, R
"DOC(
3465 Returns 1 if the given particle is linked to the same MC particle as any reconstructed daughter of the decay lists.
3467 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
3469 * ``isMCDescendantOfList(<particle_list>,1)`` returns 1 if particle is matched to the same particle as any daughter of the list,
3470 * ``isMCDescendantOfList(<particle_list>,2)`` returns 1 if particle is matched to the same particle as any granddaughter of the list,
3471 * ``isMCDescendantOfList(<particle_list>,3)`` returns 1 if particle is matched to the same particle as any great-granddaughter of the list, etc.
3472 * Default value is ``-1`` that is inclusive for all generations.
3474 It makes only sense for lists created with `fillParticleListFromMC` function with ``addDaughters=True`` argument.
3475 )DOC", Manager::VariableDataType::c_bool);
3477 REGISTER_METAVARIABLE("sourceObjectIsInList(particleListName)", sourceObjectIsInList, R
"DOC(
3478Returns 1 if the underlying mdst object (e.g. track, or cluster) was used to create a particle in ``particleListName``, 0 if not.
3481 This only makes sense for particles that are not composite. Returns -1 for composite particles.
3482)DOC", Manager::VariableDataType::c_int);
3484 REGISTER_METAVARIABLE("mcParticleIsInMCList(particleListName)", mcParticleIsInMCList, R
"DOC(
3485Returns 1 if the particle's matched MC particle is also matched to a particle in ``particleListName``
3486(or if either of the lists were filled from generator level `modularAnalysis.fillParticleListFromMC`.)
3488.. seealso:: :b2:var:`isMCDescendantOfList` to check daughters.
3489)DOC", Manager::VariableDataType::c_bool);
3491 REGISTER_METAVARIABLE("isGrandDaughterOfList(particleListNames)", isGrandDaughterOfList,
3492 "Returns 1 if the given particle is a grand daughter of at least one of the particles in the given particle Lists.", Manager::VariableDataType::c_bool);
3493 REGISTER_METAVARIABLE(
"originalParticle(variable)", originalParticle, R
"DOC(
3494 Returns value of variable for the original particle from which the given particle is copied.
3496 The copy of particle is created, for example, when the vertex fit updates the daughters and `modularAnalysis.copyParticles` is called.
3497 Returns NaN if the given particle is not copied and so there is no original particle.
3498 )DOC", Manager::VariableDataType::c_double);
3499 REGISTER_METAVARIABLE("daughter(i, variable)", daughter, R
"DOC(
3500 Returns value of variable for the i-th daughter. E.g.
3502 * ``daughter(0, p)`` returns the total momentum of the first daughter.
3503 * ``daughter(0, daughter(1, p)`` returns the total momentum of the second daughter of the first daughter.
3505 Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters).
3506 )DOC", Manager::VariableDataType::c_double);
3507 REGISTER_METAVARIABLE("originalDaughter(i, variable)", originalDaughter, R
"DOC(
3508 Returns value of variable for the original particle from which the i-th daughter is copied.
3510 The copy of particle is created, for example, when the vertex fit updates the daughters and `modularAnalysis.copyParticles` is called.
3511 Returns NaN if the daughter is not copied and so there is no original daughter.
3513 Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters).
3514 )DOC", Manager::VariableDataType::c_double);
3515 REGISTER_METAVARIABLE("mcDaughter(i, variable)", mcDaughter, R
"DOC(
3516 Returns the value of the requested variable for the i-th Monte Carlo daughter of the particle.
3518 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
3519 or if the i-th MC daughter does not exist.
3521 E.g. ``mcDaughter(0, PDG)`` will return the PDG code of the first MC daughter of the matched MC
3522 particle of the reconstructed particle the function is applied to.
3524 The meta variable can also be nested: ``mcDaughter(0, mcDaughter(1, PDG))``.
3525 )DOC", Manager::VariableDataType::c_double);
3526 REGISTER_METAVARIABLE("mcMother(variable)", mcMother, R
"DOC(
3527 Returns the value of the requested variable for the Monte Carlo mother of the particle.
3529 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
3530 or if the MC mother does not exist.
3532 E.g. ``mcMother(PDG)`` will return the PDG code of the MC mother of the matched MC
3533 particle of the reconstructed particle the function is applied to.
3535 The meta variable can also be nested: ``mcMother(mcMother(PDG))``.
3536 )DOC", Manager::VariableDataType::c_double);
3537 REGISTER_METAVARIABLE("genParticle(index, variable)", genParticle, R
"DOC(
3538[Eventbased] Returns the ``variable`` for the ith generator particle.
3539The arguments of the function must be the ``index`` of the particle in the MCParticle Array,
3540and ``variable``, the name of the function or variable for that generator particle.
3541If ``index`` goes beyond the length of the MCParticles array, NaN will be returned.
3543E.g. ``genParticle(0, p)`` returns the total momentum of the first MCParticle, which in a generic decay up to MC15 is
3544the Upsilon(4S) and for MC16 and beyond the initial electron.
3545)DOC", Manager::VariableDataType::c_double);
3546 REGISTER_METAVARIABLE("genUpsilon4S(variable)", genUpsilon4S, R
"DOC(
3547[Eventbased] Returns the ``variable`` evaluated for the generator-level :math:`\Upsilon(4S)`.
3548If no generator level :math:`\Upsilon(4S)` exists for the event, NaN will be returned.
3550E.g. ``genUpsilon4S(p)`` returns the total momentum of the :math:`\Upsilon(4S)` in a generic decay.
3551``genUpsilon4S(mcDaughter(1, p))`` returns the total momentum of the second daughter of the
3552generator-level :math:`\Upsilon(4S)` (i.e. the momentum of the second B meson in a generic decay).
3553)DOC", Manager::VariableDataType::c_double);
3554 REGISTER_METAVARIABLE("daughterProductOf(variable)", daughterProductOf,
3555 "Returns product of a variable over all daughters.\n"
3556 "E.g. ``daughterProductOf(extraInfo(SignalProbability))`` returns the product of the SignalProbabilitys of all daughters.", Manager::VariableDataType::c_double);
3557 REGISTER_METAVARIABLE(
"daughterSumOf(variable)", daughterSumOf,
3558 "Returns sum of a variable over all daughters.\n"
3559 "E.g. ``daughterSumOf(nDaughters)`` returns the number of grand-daughters.", Manager::VariableDataType::c_double);
3560 REGISTER_METAVARIABLE(
"daughterLowest(variable)", daughterLowest,
3561 "Returns the lowest value of the given variable among all daughters.\n"
3562 "E.g. ``useCMSFrame(daughterLowest(p))`` returns the lowest momentum in CMS frame.", Manager::VariableDataType::c_double);
3563 REGISTER_METAVARIABLE(
"daughterHighest(variable)", daughterHighest,
3564 "Returns the highest value of the given variable among all daughters.\n"
3565 "E.g. ``useCMSFrame(daughterHighest(p))`` returns the highest momentum in CMS frame.", Manager::VariableDataType::c_double);
3566 REGISTER_METAVARIABLE(
"daughterDiffOf(daughterIndex_i, daughterIndex_j, variable)", daughterDiffOf, R
"DOC(
3567 Returns the difference of a variable between the two given daughters.
3568 E.g. ``useRestFrame(daughterDiffOf(0, 1, p))`` returns the momentum difference between first and second daughter in the rest frame of the given particle.
3569 (That means that it returns :math:`p_j - p_i`)
3571 The daughters can be provided as generalized daughter indexes, which are simply colon-separated
3572 lists of daughter indexes, ordered starting from the root particle. For example, ``0:1``
3573 identifies the second daughter (1) of the first daughter (0) of the mother particle.
3575 )DOC", Manager::VariableDataType::c_double);
3576 REGISTER_METAVARIABLE("mcDaughterDiffOf(i, j, variable)", mcDaughterDiffOf,
3577 "MC matched version of the `daughterDiffOf` function.", Manager::VariableDataType::c_double);
3578 REGISTER_METAVARIABLE(
"grandDaughterDiffOf(i, j, variable)", grandDaughterDiffOf,
3579 "Returns the difference of a variable between the first daughters of the two given daughters.\n"
3580 "E.g. ``useRestFrame(grandDaughterDiffOf(0, 1, p))`` returns the momentum difference between the first daughters of the first and second daughter in the rest frame of the given particle.\n"
3581 "(That means that it returns :math:`p_j - p_i`)", Manager::VariableDataType::c_double);
3582 MAKE_DEPRECATED(
"grandDaughterDiffOf",
false,
"light-2402-ocicat", R
"DOC(
3583 The difference between any combination of (grand-)daughters can be calculated with the more general variable :b2:var:`daughterDiffOf`
3584 by using generalized daughter indexes.)DOC");
3585 REGISTER_METAVARIABLE("daughterDiffOfPhi(i, j)", daughterDiffOfPhi,
3586 "Returns the difference in :math:`\\phi` between the two given daughters. The unit of the angle is ``rad``.\n"
3587 "The difference is signed and takes account of the ordering of the given daughters.\n"
3588 "The function returns :math:`\\phi_j - \\phi_i`.", Manager::VariableDataType::c_double);
3589 MAKE_DEPRECATED(
"daughterDiffOfPhi",
false,
"release-06-00-00", R
"DOC(
3590 The difference of the azimuthal angle :math:`\\phi` of two daughters can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3591 REGISTER_METAVARIABLE("mcDaughterDiffOfPhi(i, j)", mcDaughterDiffOfPhi,
3592 "MC matched version of the `daughterDiffOfPhi` function. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
3593 MAKE_DEPRECATED(
"mcDaughterDiffOfPhi",
false,
"release-06-00-00", R
"DOC(
3594 The difference of the azimuthal angle :math:`\\phi` of the MC partners of two daughters can be calculated with the generic variable :b2:var:`mcDaughterDiffOf`.)DOC");
3595 REGISTER_METAVARIABLE("grandDaughterDiffOfPhi(i, j)", grandDaughterDiffOfPhi,
3596 "Returns the difference in :math:`\\phi` between the first daughters of the two given daughters. The unit of the angle is ``rad``.\n"
3597 "The difference is signed and takes account of the ordering of the given daughters.\n"
3598 "The function returns :math:`\\phi_j - \\phi_i`.\n", Manager::VariableDataType::c_double);
3599 MAKE_DEPRECATED(
"grandDaughterDiffOfPhi",
false,
"release-06-00-00", R
"DOC(
3600 The difference of the azimuthal angle :math:`\\phi` of two granddaughters can be calculated with the generic variable :b2:var:`grandDaughterDiffOf`.)DOC");
3601 REGISTER_METAVARIABLE("daughterDiffOfClusterPhi(i, j)", daughterDiffOfClusterPhi,
3602 "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters. The unit of the angle is ``rad``.\n"
3603 "The difference is signed and takes account of the ordering of the given daughters.\n"
3604 "The function returns :math:`\\phi_j - \\phi_i`.\n"
3605 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.", Manager::VariableDataType::c_double);
3606 MAKE_DEPRECATED(
"daughterDiffOfClusterPhi",
false,
"release-06-00-00", R
"DOC(
3607 The difference of the azimuthal angle :math:`\\phi` of the related ECL clusters of two daughters can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3608 REGISTER_METAVARIABLE("grandDaughterDiffOfClusterPhi(i, j)", grandDaughterDiffOfClusterPhi,
3609 "Returns the difference in :math:`\\phi` between the ECLClusters of the daughters of the two given daughters. The unit of the angle is ``rad``.\n"
3610 "The difference is signed and takes account of the ordering of the given daughters.\n"
3611 "The function returns :math:`\\phi_j - \\phi_i`.\n"
3612 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.\n", Manager::VariableDataType::c_double);
3613 MAKE_DEPRECATED(
"grandDaughterDiffOfClusterPhi",
false,
"release-06-00-00", R
"DOC(
3614 The difference of the azimuthal angle :math:`\\phi` of the related ECL clusters of two granddaughters can be calculated with the generic variable :b2:var:`grandDaughterDiffOf`.)DOC");
3615 REGISTER_METAVARIABLE("daughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
3616 "Returns the difference in :math:`\\phi` between the two given daughters in the CMS frame. The unit of the angle is ``rad``.\n"
3617 "The difference is signed and takes account of the ordering of the given daughters.\n"
3618 "The function returns :math:`\\phi_j - \\phi_i`.", Manager::VariableDataType::c_double);
3619 MAKE_DEPRECATED(
"daughterDiffOfPhiCMS",
false,
"release-06-00-00", R
"DOC(
3620 The difference of the azimuthal angle :math:`\\phi` of two daughters in the CMS frame can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3621 REGISTER_METAVARIABLE("mcDaughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
3622 "MC matched version of the `daughterDiffOfPhiCMS` function. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
3623 MAKE_DEPRECATED(
"mcDaughterDiffOfPhiCMS",
false,
"release-06-00-00", R
"DOC(
3624 The difference of the azimuthal angle :math:`\\phi` of the MC partners of two daughters in the CMS frame can be calculated with the generic variable :b2:var:`mcDaughterDiffOf`.)DOC");
3625 REGISTER_METAVARIABLE("daughterDiffOfClusterPhiCMS(i, j)", daughterDiffOfClusterPhiCMS,
3626 "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters in the CMS frame. The unit of the angle is ``rad``.\n"
3627 "The difference is signed and takes account of the ordering of the given daughters.\n"
3628 "The function returns :math:`\\phi_j - \\phi_i``.\n"
3629 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.", Manager::VariableDataType::c_double);
3630 MAKE_DEPRECATED(
"daughterDiffOfClusterPhiCMS",
false,
"release-06-00-00", R
"DOC(
3631 The difference of the azimuthal angle :math:`\\phi` of the related ECL clusters of two daughters in the CMS frame can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3632 REGISTER_METAVARIABLE("daughterNormDiffOf(i, j, variable)", daughterNormDiffOf,
3633 "Returns the normalized difference of a variable between the two given daughters.\n"
3634 "E.g. ``daughterNormDiffOf(0, 1, p)`` returns the normalized momentum difference between first and second daughter in the lab frame.", Manager::VariableDataType::c_double);
3635 REGISTER_METAVARIABLE(
"daughterMotherDiffOf(i, variable)", daughterMotherDiffOf,
3636 "Returns the difference of a variable between the given daughter and the mother particle itself.\n"
3637 "E.g. ``useRestFrame(daughterMotherDiffOf(0, p))`` returns the momentum difference between the given particle and its first daughter in the rest frame of the mother.", Manager::VariableDataType::c_double);
3638 REGISTER_METAVARIABLE(
"daughterMotherNormDiffOf(i, variable)", daughterMotherNormDiffOf,
3639 "Returns the normalized difference of a variable between the given daughter and the mother particle itself.\n"
3640 "E.g. ``daughterMotherNormDiffOf(1, p)`` returns the normalized momentum difference between the given particle and its second daughter in the lab frame.", Manager::VariableDataType::c_double);
3641 REGISTER_METAVARIABLE(
"daughterAngle(daughterIndex_1, daughterIndex_2[, daughterIndex_3])", daughterAngle, R
"DOC(
3642 Returns the angle in between any pair of particles belonging to the same decay tree.
3643 The unit of the angle is ``rad``.
3645 The particles are identified via generalized daughter indexes, which are simply colon-separated lists of
3646 daughter indexes, ordered starting from the root particle. For example, ``0:1:3`` identifies the fourth
3647 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply
3648 identifies the second daughter of the root particle.
3650 Both two and three generalized indexes can be given to ``daughterAngle``. If two indices are given, the
3651 variable returns the angle between the momenta of the two given particles. If three indices are given, the
3652 variable returns the angle between the momentum of the third particle and a vector which is the sum of the
3653 first two daughter momenta.
3656 ``daughterAngle(0, 3)`` will return the angle between the first and fourth daughter.
3657 ``daughterAngle(0, 1, 3)`` will return the angle between the fourth daughter and the sum of the first and
3659 ``daughterAngle(0:0, 3:0)`` will return the angle between the first daughter of the first daughter, and
3660 the first daughter of the fourth daughter.
3662 )DOC", Manager::VariableDataType::c_double);
3663 REGISTER_METAVARIABLE("mcDaughterAngle(daughterIndex_1, daughterIndex_2, [daughterIndex_3])", mcDaughterAngle,
3664 "MC matched version of the `daughterAngle` function. Also works if applied directly to MC particles. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
3665 REGISTER_VARIABLE(
"grandDaughterDecayAngle(i, j)", grandDaughterDecayAngle,
3666 "Returns the decay angle of the granddaughter in the daughter particle's rest frame.\n"
3667 "It is calculated with respect to the reverted momentum vector of the particle.\n"
3668 "Two arguments representing the daughter and granddaughter indices have to be provided as arguments.\n\n",
"rad");
3669 REGISTER_VARIABLE(
"daughterClusterAngleInBetween(i, j)", daughterClusterAngleInBetween,
3670 "Returns the angle between clusters associated to the two daughters."
3671 "If two indices given: returns the angle between the momenta of the clusters associated to the two given daughters."
3672 "If three indices given: returns the angle between the momentum of the third particle's cluster and a vector "
3673 "which is the sum of the first two daughter's cluster momenta."
3674 "Returns nan if any of the daughters specified don't have an associated cluster."
3675 "The arguments in the argument vector must be integers corresponding to the ith and jth (and kth) daughters.\n\n",
"rad");
3676 REGISTER_METAVARIABLE(
"daughterInvM(i[, j, ...])", daughterInvM, R
"DOC(
3677 Returns the invariant mass adding the Lorentz vectors of the given daughters. The unit of the invariant mass is GeV/:math:`\text{c}^2`
3678 E.g. ``daughterInvM(0, 1, 2)`` returns the invariant Mass :math:`m = \sqrt{(p_0 + p_1 + p_2)^2}` of the first, second and third daughter.
3680 Daughters from different generations of the decay tree can be combined using generalized daughter indexes,
3681 which are simply colon-separated daughter indexes for each generation, starting from the root particle. For
3682 example, ``0:1:3`` identifies the fourth daughter (3) of the second daughter (1) of the first daughter(0) of
3683 the mother particle.
3685 Returns NaN if the given daughter-index is out of bound (>= number of daughters))DOC", Manager::VariableDataType::c_double);
3686 REGISTER_METAVARIABLE("extraInfo(name)", extraInfo,
3687 "Returns extra info stored under the given name.\n"
3688 "The extraInfo has to be set by a module first.\n"
3689 "E.g. ``extraInfo(SignalProbability)`` returns the SignalProbability calculated by the ``MVAExpert`` module.\n"
3690 "If nothing is set under the given name or if the particle is a nullptr, NaN is returned.\n"
3691 "In the latter case please use `eventExtraInfo` if you want to access an EventExtraInfo variable.", Manager::VariableDataType::c_double);
3692 REGISTER_METAVARIABLE(
"eventExtraInfo(name)", eventExtraInfo,
3693 "[Eventbased] Returns extra info stored under the given name in the event extra info.\n"
3694 "The extraInfo has to be set first by another module like MVAExpert in event mode.\n"
3695 "If nothing is set under this name, NaN is returned.", Manager::VariableDataType::c_double);
3696 REGISTER_METAVARIABLE(
"eventCached(variable)", eventCached,
3697 "[Eventbased] Returns value of event-based variable and caches this value in the EventExtraInfo.\n"
3698 "The result of second call to this variable in the same event will be provided from the cache.\n"
3699 "It is recommended to use this variable in order to declare custom aliases as event-based. This is "
3700 "necessary if using the eventwise mode of variablesToNtuple).", Manager::VariableDataType::c_double);
3701 REGISTER_METAVARIABLE(
"particleCached(variable)", particleCached,
3702 "Returns value of given variable and caches this value in the ParticleExtraInfo of the provided particle.\n"
3703 "The result of second call to this variable on the same particle will be provided from the cache.", Manager::VariableDataType::c_double);
3704 REGISTER_METAVARIABLE(
"modulo(variable, n)", modulo,
3705 "Returns rest of division of variable by n.", Manager::VariableDataType::c_int);
3706 REGISTER_METAVARIABLE(
"abs(variable)", abs,
3707 "Returns absolute value of the given variable.\n"
3708 "E.g. abs(mcPDG) returns the absolute value of the mcPDG, which is often useful for cuts.", Manager::VariableDataType::c_double);
3709 REGISTER_METAVARIABLE(
"max(var1,var2)", max,
"Returns max value of two variables.\n", Manager::VariableDataType::c_double);
3710 REGISTER_METAVARIABLE(
"min(var1,var2)", min,
"Returns min value of two variables.\n", Manager::VariableDataType::c_double);
3711 REGISTER_METAVARIABLE(
"sin(variable)", sin,
"Returns sine value of the given variable.", Manager::VariableDataType::c_double);
3712 REGISTER_METAVARIABLE(
"asin(variable)", asin,
"Returns arcsine of the given variable. The unit of the asin() is ``rad``", Manager::VariableDataType::c_double);
3713 REGISTER_METAVARIABLE(
"cos(variable)", cos,
"Returns cosine value of the given variable.", Manager::VariableDataType::c_double);
3714 REGISTER_METAVARIABLE(
"acos(variable)", acos,
"Returns arccosine value of the given variable. The unit of the acos() is ``rad``", Manager::VariableDataType::c_double);
3715 REGISTER_METAVARIABLE(
"tan(variable)", tan,
"Returns tangent value of the given variable.", Manager::VariableDataType::c_double);
3716 REGISTER_METAVARIABLE(
"atan(variable)", atan,
"Returns arctangent value of the given variable. The unit of the atan() is ``rad``", Manager::VariableDataType::c_double);
3717 REGISTER_METAVARIABLE(
"exp(variable)", exp,
"Returns exponential evaluated for the given variable.", Manager::VariableDataType::c_double);
3718 REGISTER_METAVARIABLE(
"log(variable)", log,
"Returns natural logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
3719 REGISTER_METAVARIABLE(
"log10(variable)", log10,
"Returns base-10 logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
3720 REGISTER_METAVARIABLE(
"isNAN(variable)", isNAN,
3721 "Returns true if variable value evaluates to nan (determined via std::isnan(double)).\n"
3722 "Useful for debugging.", Manager::VariableDataType::c_bool);
3723 REGISTER_METAVARIABLE(
"ifNANgiveX(variable, x)", ifNANgiveX,
3724 "Returns x (has to be a number) if variable value is nan (determined via std::isnan(double)).\n"
3725 "Useful for technical purposes while training MVAs.", Manager::VariableDataType::c_double);
3726 REGISTER_METAVARIABLE(
"isInfinity(variable)", isInfinity,
3727 "Returns true if variable value evaluates to infinity (determined via std::isinf(double)).\n"
3728 "Useful for debugging.", Manager::VariableDataType::c_bool);
3729 REGISTER_METAVARIABLE(
"unmask(variable, flag1, flag2, ...)", unmask,
3730 "unmask(variable, flag1, flag2, ...) or unmask(variable, mask) sets certain bits in the variable to zero.\n"
3731 "For example, if you want to set the second, fourth and fifth bits to zero, you could call \n"
3732 "``unmask(variable, 2, 8, 16)`` or ``unmask(variable, 26)``.\n"
3733 "", Manager::VariableDataType::c_double);
3734 REGISTER_METAVARIABLE(
"conditionalVariableSelector(cut, variableIfTrue, variableIfFalse)", conditionalVariableSelector,
3735 "Returns one of the two supplied variables, depending on whether the particle passes the supplied cut.\n"
3736 "The first variable is returned if the particle passes the cut, and the second variable is returned otherwise.", Manager::VariableDataType::c_double);
3737 REGISTER_METAVARIABLE(
"pValueCombination(p1, p2, ...)", pValueCombination,
3738 "Returns the combined p-value of the provided p-values according to the formula given in `Nucl. Instr. and Meth. A 411 (1998) 449 <https://doi.org/10.1016/S0168-9002(98)00293-9>`_ .\n"
3739 "If any of the p-values is invalid, i.e. smaller than zero, -1 is returned.", Manager::VariableDataType::c_double);
3740 REGISTER_METAVARIABLE(
"veto(particleList, cut, pdgCode = 11)", veto,
3741 "Combines current particle with particles from the given particle list and returns 1 if the combination passes the provided cut. \n"
3742 "For instance one can apply this function on a signal Photon and provide a list of all photons in the rest of event and a cut \n"
3743 "around the neutral Pion mass (e.g. ``0.130 < M < 0.140``). \n"
3744 "If a combination of the signal Photon with a ROE photon fits this criteria, hence looks like a neutral pion, the veto-Metavariable will return 1", Manager::VariableDataType::c_bool);
3745 REGISTER_METAVARIABLE(
"matchedMC(variable)", matchedMC,
3746 "Returns variable output for the matched MCParticle by constructing a temporary Particle from it.\n"
3747 "This may not work too well if your variable requires accessing daughters of the particle.\n"
3748 "E.g. ``matchedMC(p)`` returns the total momentum of the related MCParticle.\n"
3749 "Returns NaN if no matched MCParticle exists.", Manager::VariableDataType::c_double);
3750 REGISTER_METAVARIABLE(
"clusterBestMatchedMCParticle(variable)", clusterBestMatchedMCParticle,
3751 "Returns variable output for the MCParticle that is best-matched with the ECLCluster of the given Particle.\n"
3752 "E.g. To get the energy of the MCParticle that matches best with an ECLCluster, one could use ``clusterBestMatchedMCParticle(E)``\n"
3753 "When the variable is called for ``gamma`` and if the ``gamma`` is matched with MCParticle, it works same as `matchedMC`.\n"
3754 "If the variable is called for ``gamma`` that fails to match with an MCParticle, it provides the mdst-level MCMatching information abouth the ECLCluster.\n"
3755 "Returns NaN if the particle is not matched to an ECLCluster, or if the ECLCluster has no matching MCParticles", Manager::VariableDataType::c_double);
3756 REGISTER_METAVARIABLE(
"varForBestMatchedMCKlong(variable)", clusterBestMatchedMCKlong,
3757 "Returns variable output for the Klong MCParticle which has the best match with the ECLCluster of the given Particle.\n"
3758 "Returns NaN if the particle is not matched to an ECLCluster, or if the ECLCluster has no matching Klong MCParticle", Manager::VariableDataType::c_double);
3760 REGISTER_METAVARIABLE(
"countInList(particleList, cut='')", countInList,
"[Eventbased] "
3761 "Returns number of particle which pass given in cut in the specified particle list.\n"
3762 "Useful for creating statistics about the number of particles in a list.\n"
3763 "E.g. ``countInList(e+, isSignal == 1)`` returns the number of correctly reconstructed electrons in the event.\n"
3764 "The variable is event-based and does not need a valid particle pointer as input.", Manager::VariableDataType::c_int);
3765 REGISTER_METAVARIABLE(
"getVariableByRank(particleList, rankedVariableName, variableName, rank)", getVariableByRank, R
"DOC(
3766 [Eventbased] Returns the value of ``variableName`` for the candidate in the ``particleList`` with the requested ``rank``.
3769 The `BestCandidateSelection` module available via `rankByHighest` / `rankByLowest` has to be used before.
3772 The first candidate matching the given rank is used.
3773 Thus, it is not recommended to use this variable in conjunction with ``allowMultiRank`` in the `BestCandidateSelection` module.
3775 The suffix ``_rank`` is automatically added to the argument ``rankedVariableName``,
3776 which either has to be the name of the variable used to order the candidates or the selected outputVariable name without the ending ``_rank``.
3777 This means that your selected name for the rank variable has to end with ``_rank``.
3779 An example of this variable's usage is given in the tutorial `B2A602-BestCandidateSelection <https://gitlab.desy.de/belle2/software/basf2/-/tree/main/analysis/examples/tutorials/B2A602-BestCandidateSelection.py>`_
3780 )DOC", Manager::VariableDataType::c_double);
3781 REGISTER_VARIABLE("matchedMCHasPDG(PDGCode)", matchedMCHasPDG,
3782 "Returns if the absolute value of the PDGCode of the MCParticle related to the Particle matches a given PDGCode."
3783 "Returns 0/NAN/1 if PDGCode does not match/is not available/ matches");
3784 REGISTER_METAVARIABLE(
"numberOfNonOverlappingParticles(pList1, pList2, ...)", numberOfNonOverlappingParticles,
3785 "Returns the number of non-overlapping particles in the given particle lists"
3786 "Useful to check if there is additional physics going on in the detector if one reconstructed the Y4S", Manager::VariableDataType::c_int);
3787 REGISTER_METAVARIABLE(
"totalEnergyOfParticlesInList(particleListName)", totalEnergyOfParticlesInList,
3788 "[Eventbased] Returns the total energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
3789 REGISTER_METAVARIABLE(
"totalPxOfParticlesInList(particleListName)", totalPxOfParticlesInList,
3790 "[Eventbased] Returns the total momentum Px of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3791 REGISTER_METAVARIABLE(
"totalPyOfParticlesInList(particleListName)", totalPyOfParticlesInList,
3792 "[Eventbased] Returns the total momentum Py of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3793 REGISTER_METAVARIABLE(
"totalPzOfParticlesInList(particleListName)", totalPzOfParticlesInList,
3794 "[Eventbased] Returns the total momentum Pz of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3795 REGISTER_METAVARIABLE(
"invMassInLists(pList1, pList2, ...)", invMassInLists,
3796 "[Eventbased] Returns the invariant mass of the combination of particles in the given particle lists. The unit of the invariant mass is GeV/:math:`\\text{c}^2` ", Manager::VariableDataType::c_double);
3797 REGISTER_METAVARIABLE(
"totalECLEnergyOfParticlesInList(particleListName)", totalECLEnergyOfParticlesInList,
3798 "[Eventbased] Returns the total ECL energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
3799 REGISTER_METAVARIABLE(
"maxPtInList(particleListName)", maxPtInList,
3800 "[Eventbased] Returns maximum transverse momentum Pt in the given particle List. The unit of the transverse momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3801 REGISTER_METAVARIABLE(
"eclClusterSpecialTrackMatched(cut)", eclClusterTrackMatchedWithCondition,
3802 "Returns if at least one Track that satisfies the given condition is related to the ECLCluster of the Particle.", Manager::VariableDataType::c_double);
3803 REGISTER_METAVARIABLE(
"averageValueInList(particleListName, variable)", averageValueInList,
3804 "[Eventbased] Returns the arithmetic mean of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3805 REGISTER_METAVARIABLE(
"medianValueInList(particleListName, variable)", medianValueInList,
3806 "[Eventbased] Returns the median value of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3807 REGISTER_METAVARIABLE(
"sumValueInList(particleListName, variable)", sumValueInList,
3808 "[Eventbased] Returns the sum of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3809 REGISTER_METAVARIABLE(
"productValueInList(particleListName, variable)", productValueInList,
3810 "[Eventbased] Returns the product of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3811 REGISTER_METAVARIABLE(
"angleToClosestInList(particleListName)", angleToClosestInList,
3812 "Returns the angle between this particle and the closest particle (smallest opening angle) in the list provided. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3813 REGISTER_METAVARIABLE(
"closestInList(particleListName, variable)", closestInList,
3814 "Returns `variable` for the closest particle (smallest opening angle) in the list provided.", Manager::VariableDataType::c_double);
3815 REGISTER_METAVARIABLE(
"angleToMostB2BInList(particleListName)", angleToMostB2BInList,
3816 "Returns the angle between this particle and the most back-to-back particle (closest opening angle to 180) in the list provided. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3817 REGISTER_METAVARIABLE(
"deltaPhiToMostB2BPhiInList(particleListName)", deltaPhiToMostB2BPhiInList,
3818 "Returns the abs(delta phi) between this particle and the most back-to-back particle in phi (closest opening angle to 180) in the list provided. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3819 REGISTER_METAVARIABLE(
"mostB2BInList(particleListName, variable)", mostB2BInList,
3820 "Returns `variable` for the most back-to-back particle (closest opening angle to 180) in the list provided.", Manager::VariableDataType::c_double);
3821 REGISTER_METAVARIABLE(
"maxOpeningAngleInList(particleListName)", maxOpeningAngleInList,
3822 "[Eventbased] Returns maximum opening angle in the given particle List. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3823 REGISTER_METAVARIABLE(
"daughterCombination(variable, daughterIndex_1, daughterIndex_2 ... daughterIndex_n)", daughterCombination,R
"DOC(
3824Returns a ``variable`` function only of the 4-momentum calculated on an arbitrary set of (grand)daughters.
3827 ``variable`` can only be a function of the daughters' 4-momenta.
3829Daughters from different generations of the decay tree can be combined using generalized daughter indexes, which are simply colon-separated
3830the list of daughter indexes, starting from the root particle: for example, ``0:1:3`` identifies the fourth
3831daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle.
3834 ``daughterCombination(M, 0, 3, 4)`` will return the invariant mass of the system made of the first, fourth and fifth daughter of particle.
3835 ``daughterCombination(M, 0:0, 3:0)`` will return the invariant mass of the system made of the first daughter of the first daughter and the first daughter of the fourth daughter.
3837)DOC", Manager::VariableDataType::c_double);
3838 REGISTER_METAVARIABLE("useAlternativeDaughterHypothesis(variable, daughterIndex_1:newMassHyp_1, ..., daughterIndex_n:newMassHyp_n)", useAlternativeDaughterHypothesis,R
"DOC(
3839Returns a ``variable`` calculated using new mass hypotheses for (some of) the particle's daughters.
3842 ``variable`` can only be a function of the particle 4-momentum, which is re-calculated as the sum of the daughters' 4-momenta, and the daughters' 4-momentum.
3843 This means that if you made a kinematic fit without updating the daughters' momenta, the result of this variable will not reflect the effect of the kinematic fit.
3844 Also, the track fit is not performed again: the variable only re-calculates the 4-vectors using different mass assumptions.
3845 In the variable, a copy of the given particle is created with daughters' alternative mass assumption (i.e. the original particle and daughters are not changed).
3848 Generalized daughter indexes are not supported (yet!): this variable can be used only on first-generation daughters.
3851 ``useAlternativeDaughterHypothesis(M, 0:K+, 2:pi-)`` will return the invariant mass of the particle assuming that the first daughter is a kaon and the third is a pion, instead of whatever was used in reconstructing the decay.
3852 ``useAlternativeDaughterHypothesis(mRecoil, 1:p+)`` will return the recoil mass of the particle assuming that the second daughter is a proton instead of whatever was used in reconstructing the decay.
3854)DOC", Manager::VariableDataType::c_double);
3855 REGISTER_METAVARIABLE("varForFirstMCAncestorOfType(type, variable)",varForFirstMCAncestorOfType,R
"DOC(Returns requested variable of the first ancestor of the given type.
3856Ancestor type can be set up by PDG code or by particle name (check evt.pdl for valid particle names))DOC", Manager::VariableDataType::c_double);
3858 REGISTER_METAVARIABLE("nTrackFitResults(particleType)", nTrackFitResults,
3859 "[Eventbased] Returns the total number of TrackFitResults for a given particleType. The argument can be the name of particle (e.g. pi+) or PDG code (e.g. 211).",
3860 Manager::VariableDataType::c_int);
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
int getPDGCode() const
PDG code.
static const ChargedStable pion
charged pion particle
static const double doubleNaN
quiet_NaN
static const ChargedStable electron
electron particle
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
@ c_nPhotons
CR is split into n photons (N1)
static std::unique_ptr< GeneralCut > compile(const std::string &cut)
Creates an instance of a cut and returns a unique_ptr to it, if you need a copy-able object instead y...
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
static std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
EParticleSourceObject
particle source enumerators
const Particle * getParticleFromGeneralizedIndexString(const std::string &generalizedIndex) const
Explores the decay tree of the particle and returns the (grand^n)daughter identified by a generalized...
std::vector< Belle2::Particle * > getDaughters() const
Returns a vector of pointers to daughter particles.
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
static const ReferenceFrame & GetCurrent()
Get current rest frame.
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.
Class to store variables with their name which were sent to the logging service.
#define MAKE_DEPRECATED(name, make_fatal, version, description)
Registers a variable as deprecated.
B2Vector3< double > B2Vector3D
typedef for common usage with double
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
bool hasAntiParticle(int pdgCode)
Checks if the particle with given pdg code has an anti-particle or not.
Particle * copyParticle(const Particle *original)
Function takes argument Particle and creates a copy of it and copies of all its (grand-)^n-daughters.
Abstract base class for different kinds of events.