10 #include <analysis/variables/MetaVariables.h> 
   12 #include <analysis/VariableManager/Utility.h> 
   13 #include <analysis/dataobjects/Particle.h> 
   14 #include <analysis/dataobjects/ParticleList.h> 
   15 #include <analysis/dataobjects/RestOfEvent.h> 
   16 #include <analysis/utility/PCmsLabTransform.h> 
   17 #include <analysis/utility/ReferenceFrame.h> 
   18 #include <analysis/utility/EvtPDLUtil.h> 
   19 #include <analysis/utility/ParticleCopy.h> 
   20 #include <analysis/utility/ValueIndexPairSorting.h> 
   21 #include <analysis/ClusterUtility/ClusterUtils.h> 
   22 #include <analysis/variables/VariableFormulaConstructor.h> 
   24 #include <framework/logging/Logger.h> 
   25 #include <framework/datastore/StoreArray.h> 
   26 #include <framework/datastore/StoreObjPtr.h> 
   27 #include <framework/dataobjects/EventExtraInfo.h> 
   28 #include <framework/utilities/Conversion.h> 
   29 #include <framework/utilities/MakeROOTCompatible.h> 
   30 #include <framework/gearbox/Const.h> 
   32 #include <mdst/dataobjects/Track.h> 
   33 #include <mdst/dataobjects/MCParticle.h> 
   34 #include <mdst/dataobjects/ECLCluster.h> 
   35 #include <mdst/dataobjects/TrackFitResult.h> 
   37 #include <boost/algorithm/string.hpp> 
   45 #include <TDatabasePDG.h> 
   46 #include <Math/Vector4D.h> 
   57       if (arguments.size() == 1) {
 
   59         auto func = [var](
const Particle * particle) -> 
double {
 
   60           UseReferenceFrame<RestFrame> frame(particle);
 
   61           double result = std::get<double>(var->function(particle));
 
   66         B2FATAL(
"Wrong number of arguments for meta function useRestFrame");
 
   72       if (arguments.size() == 1) {
 
   74         auto func = [var](
const Particle * particle) -> 
double {
 
   75           UseReferenceFrame<CMSFrame> frame;
 
   76           double result = std::get<double>(var->function(particle));
 
   81         B2FATAL(
"Wrong number of arguments for meta function useCMSFrame");
 
   87       if (arguments.size() == 1) {
 
   89         auto func = [var](
const Particle * particle) -> 
double {
 
   90           UseReferenceFrame<LabFrame> frame;
 
   91           double result = std::get<double>(var->function(particle));
 
   96         B2FATAL(
"Wrong number of arguments for meta function useLabFrame");
 
  102       if (arguments.size() == 2) {
 
  105         int daughterIndexTagB = 0;
 
  107           daughterIndexTagB = Belle2::convertString<int>(arguments[1]);
 
  108         } 
catch (std::invalid_argument&) {
 
  109           B2FATAL(
"Second argument of useTagSideRecoilRestFrame meta function must be integer!");
 
  112         auto func = [var, daughterIndexTagB](
const Particle * particle) -> 
double {
 
  113           if (particle->getPDGCode() != 300553)
 
  115             B2ERROR(
"Variable should only be used on a Upsilon(4S) Particle List!");
 
  116             return std::numeric_limits<float>::quiet_NaN();
 
  120           ROOT::Math::PxPyPzEVector pSigB = T.getBeamFourMomentum() - particle->getDaughter(daughterIndexTagB)->get4Vector();
 
  121           Particle tmp(pSigB, -particle->getDaughter(daughterIndexTagB)->getPDGCode());
 
  123           UseReferenceFrame<RestFrame> frame(&tmp);
 
  124           double result = std::get<double>(var->function(particle));
 
  130         B2FATAL(
"Wrong number of arguments for meta function useTagSideRecoilRestFrame");
 
  136       if (arguments.size() == 2) {
 
  138         std::string listName = arguments[1];
 
  139         auto func = [var, listName](
const Particle * particle) -> 
double {
 
  140           StoreObjPtr<ParticleList> list(listName);
 
  141           unsigned listSize = list->getListSize();
 
  143             return std::numeric_limits<float>::quiet_NaN();
 
  145             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." 
  146                       << 
LogVar(
"ParticleList", listName)
 
  147                       << 
LogVar(
"Number of candidates in the list", listSize));
 
  148           const Particle* p = list->getParticle(0);
 
  149           UseReferenceFrame<RestFrame> frame(p);
 
  150           double result = std::get<double>(var->function(particle));
 
  155         B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
 
  161       if (arguments.size() == 2) {
 
  163         std::string listName = arguments[1];
 
  164         auto func = [var, listName](
const Particle * particle) -> 
double {
 
  165           StoreObjPtr<ParticleList> list(listName);
 
  166           unsigned listSize = list->getListSize();
 
  168             return std::numeric_limits<float>::quiet_NaN();
 
  170             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." 
  171                       << 
LogVar(
"ParticleList", listName)
 
  172                       << 
LogVar(
"Number of candidates in the list", listSize));
 
  173           const Particle* p = list->getParticle(0);
 
  175           ROOT::Math::PxPyPzEVector recoil = T.getBeamFourMomentum() - p->get4Vector();
 
  177           Particle pRecoil(recoil, 0);
 
  178           pRecoil.setVertex(particle->getVertex());
 
  179           UseReferenceFrame<RestFrame> frame(&pRecoil);
 
  180           double result = std::get<double>(var->function(particle));
 
  185         B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
 
  191       if (arguments.size() >= 2) {
 
  193         auto func = [var, arguments](
const Particle * particle) -> 
double {
 
  196           ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
 
  198           for (
unsigned int i = 1; i < arguments.size(); i++)
 
  200             auto generalizedIndex = arguments[i];
 
  201             const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
 
  203               pSum +=  dauPart->get4Vector();
 
  205               return std::numeric_limits<float>::quiet_NaN();
 
  207           Particle tmp(pSum, 0);
 
  208           UseReferenceFrame<RestFrame> frame(&tmp);
 
  209           double result = std::get<double>(var->function(particle));
 
  214         B2FATAL(
"Wrong number of arguments for meta function useDaughterRestFrame.");
 
  220       if (arguments.size() == 1) {
 
  221         auto extraInfoName = arguments[0];
 
  222         auto func = [extraInfoName](
const Particle * particle) -> 
double {
 
  223           if (particle == 
nullptr)
 
  225             B2WARNING(
"Returns NaN because the particle is nullptr! If you want EventExtraInfo variables, please use eventExtraInfo() instead");
 
  226             return std::numeric_limits<float>::quiet_NaN();
 
  228           if (particle->hasExtraInfo(extraInfoName))
 
  230             return particle->getExtraInfo(extraInfoName);
 
  233             return std::numeric_limits<float>::quiet_NaN();
 
  238         B2FATAL(
"Wrong number of arguments for meta function extraInfo");
 
  244       if (arguments.size() == 1) {
 
  245         auto extraInfoName = arguments[0];
 
  246         auto func = [extraInfoName](
const Particle*) -> 
double {
 
  247           StoreObjPtr<EventExtraInfo> eventExtraInfo;
 
  248           if (not eventExtraInfo.isValid())
 
  249             return std::numeric_limits<float>::quiet_NaN();
 
  250           if (eventExtraInfo->hasExtraInfo(extraInfoName))
 
  252             return eventExtraInfo->getExtraInfo(extraInfoName);
 
  255             return std::numeric_limits<float>::quiet_NaN();
 
  260         B2FATAL(
"Wrong number of arguments for meta function extraInfo");
 
  266       if (arguments.size() == 1) {
 
  269         auto func = [var, key](
const Particle*) -> 
double {
 
  271           StoreObjPtr<EventExtraInfo> eventExtraInfo;
 
  272           if (not eventExtraInfo.isValid())
 
  273             eventExtraInfo.create();
 
  274           if (eventExtraInfo->hasExtraInfo(key))
 
  276             return eventExtraInfo->getExtraInfo(key);
 
  279             double value = std::numeric_limits<double>::quiet_NaN();
 
  280             auto var_result = var->function(
nullptr);
 
  281             if (std::holds_alternative<double>(var_result)) {
 
  282               value = std::get<double>(var_result);
 
  283             } 
else if (std::holds_alternative<int>(var_result)) {
 
  284               return std::get<int>(var_result);
 
  285             } 
else if (std::holds_alternative<bool>(var_result)) {
 
  286               return std::get<bool>(var_result);
 
  288             eventExtraInfo->addExtraInfo(key, value);
 
  294         B2FATAL(
"Wrong number of arguments for meta function eventCached");
 
  300       if (arguments.size() == 1) {
 
  303         auto func = [var, key](
const Particle * particle) -> 
double {
 
  305           if (particle->hasExtraInfo(key))
 
  307             return particle->getExtraInfo(key);
 
  310             double value = std::get<double>(var->function(particle));
 
  318             const_cast<Particle*
>(particle)->addExtraInfo(key, value);
 
  324         B2FATAL(
"Wrong number of arguments for meta function particleCached");
 
  333       if (arguments.size() != 1) B2FATAL(
"Wrong number of arguments for meta function formula");
 
  334       FormulaParser<VariableFormulaConstructor> parser;
 
  336         return parser.parse(arguments[0]);
 
  337       } 
catch (std::runtime_error& e) {
 
  344       if (arguments.size() <= 1) {
 
  346         std::string cutString;
 
  347         if (arguments.size() == 1)
 
  348           cutString = arguments[0];
 
  350         auto func = [cut](
const Particle*) -> 
int {
 
  352           int number_of_tracks = 0;
 
  353           StoreArray<Track> tracks;
 
  354           for (
const auto& track : tracks)
 
  356             const TrackFitResult* trackFit = track.getTrackFitResultWithClosestMass(
Const::pion);
 
  357             if (trackFit->getChargeSign() == 0) {
 
  361               if (cut->check(&particle))
 
  366           return number_of_tracks;
 
  371         B2FATAL(
"Wrong number of arguments for meta function nCleanedTracks");
 
  377       if (arguments.size() <= 1) {
 
  379         std::string cutString;
 
  380         if (arguments.size() == 1)
 
  381           cutString = arguments[0];
 
  383         auto func = [cut](
const Particle*) -> 
int {
 
  385           int number_of_clusters = 0;
 
  386           StoreArray<ECLCluster> clusters;
 
  387           for (
const auto& cluster : clusters)
 
  393             Particle particle(&cluster);
 
  394             if (cut->check(&particle))
 
  395               number_of_clusters++;
 
  398           return number_of_clusters;
 
  403         B2FATAL(
"Wrong number of arguments for meta function nCleanedECLClusters");
 
  409       if (arguments.size() == 1) {
 
  410         std::string cutString = arguments[0];
 
  412         auto func = [cut](
const Particle * particle) -> 
bool {
 
  413           if (cut->check(particle))
 
  420         B2FATAL(
"Wrong number of arguments for meta function passesCut");
 
  426       if (arguments.size() == 1) {
 
  427         std::string cutString = arguments[0];
 
  429         auto func = [cut](
const Particle*) -> 
bool {
 
  430           if (cut->check(
nullptr))
 
  437         B2FATAL(
"Wrong number of arguments for meta function passesEventCut");
 
  443       if (arguments.size() == 2) {
 
  446           pdgCode = Belle2::convertString<int>(arguments[0]);
 
  447         } 
catch (std::invalid_argument&) {
 
  448           B2FATAL(
"The first argument of varFor meta function must be a positive integer!");
 
  451         auto func = [pdgCode, var](
const Particle * particle) -> 
double {
 
  452           if (std::abs(particle->getPDGCode()) == std::abs(pdgCode))
 
  454             auto var_result = var->function(particle);
 
  455             if (std::holds_alternative<double>(var_result)) {
 
  456               return std::get<double>(var_result);
 
  457             } 
else if (std::holds_alternative<int>(var_result)) {
 
  458               return std::get<int>(var_result);
 
  459             } 
else if (std::holds_alternative<bool>(var_result)) {
 
  460               return std::get<bool>(var_result);
 
  461             } 
else return std::numeric_limits<double>::quiet_NaN();
 
  462           } 
else return std::numeric_limits<double>::quiet_NaN();
 
  466         B2FATAL(
"Wrong number of arguments for meta function varFor");
 
  472       if (arguments.size() == 1) {
 
  474         auto func = [var](
const Particle * particle) -> 
double {
 
  475           if (particle->getMCParticle())
 
  480               auto var_result = var->function(particle);
 
  481               if (std::holds_alternative<double>(var_result)) {
 
  482                 return std::get<double>(var_result);
 
  483               } 
else if (std::holds_alternative<int>(var_result)) {
 
  484                 return std::get<int>(var_result);
 
  485               } 
else if (std::holds_alternative<bool>(var_result)) {
 
  486                 return std::get<bool>(var_result);
 
  487               } 
else return std::numeric_limits<double>::quiet_NaN();
 
  488             } 
else return std::numeric_limits<double>::quiet_NaN();
 
  489           } 
else return std::numeric_limits<double>::quiet_NaN();
 
  493         B2FATAL(
"Wrong number of arguments for meta function varForMCGen");
 
  499       if (arguments.size() == 1) {
 
  500         std::string listName = arguments[0];
 
  501         auto func = [listName](
const Particle * particle) -> 
int {
 
  504           StoreObjPtr<ParticleList> listOfParticles(listName);
 
  506           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to nParticlesInList");
 
  508           return listOfParticles->getListSize();
 
  513         B2FATAL(
"Wrong number of arguments for meta function nParticlesInList");
 
  520       if (arguments.size() != 1) {
 
  521         B2FATAL(
"Wrong number of arguments for isInList");
 
  523       auto listName = arguments[0];
 
  525       auto func = [listName](
const Particle * particle) -> 
bool {
 
  528         StoreObjPtr<ParticleList> list(listName);
 
  529         if (!(list.isValid()))
 
  531           B2FATAL(
"Invalid Listname " << listName << 
" given to isInList");
 
  535         return list->contains(particle);
 
  544       if (arguments.size() != 1) {
 
  545         B2FATAL(
"Wrong number of arguments for sourceObjectIsInList");
 
  547       auto listName = arguments[0];
 
  549       auto func = [listName](
const Particle * particle) -> 
int {
 
  552         StoreObjPtr<ParticleList> list(listName);
 
  553         if (!(list.isValid()))
 
  555           B2FATAL(
"Invalid Listname " << listName << 
" given to sourceObjectIsInList");
 
  561         if (particlesource == Particle::EParticleSourceObject::c_Composite
 
  562             or particlesource == Particle::EParticleSourceObject::c_Undefined)
 
  568         for (
unsigned i = 0; i < list->getListSize(); ++i)
 
  570           Particle* iparticle = list->getParticle(i);
 
  571           if (particlesource == iparticle->getParticleSource())
 
  572             if (particle->getMdstArrayIndex() == iparticle->getMdstArrayIndex())
 
  584       if (arguments.size() != 1) {
 
  585         B2FATAL(
"Wrong number of arguments for mcParticleIsInMCList");
 
  587       auto listName = arguments[0];
 
  589       auto func = [listName](
const Particle * particle) -> 
bool {
 
  592         StoreObjPtr<ParticleList> list(listName);
 
  593         if (!(list.isValid()))
 
  594           B2FATAL(
"Invalid Listname " << listName << 
" given to mcParticleIsInMCList");
 
  598         if (mcp == 
nullptr) 
return false;
 
  601         for (
unsigned i = 0; i < list->getListSize(); ++i)
 
  603           const MCParticle* imcp = list->getParticle(i)->
getMCParticle();
 
  604           if ((imcp != 
nullptr) and (mcp->getArrayIndex() == imcp->getArrayIndex()))
 
  614       B2WARNING(
"isDaughterOfList is outdated and replaced by isDescendantOfList.");
 
  615       std::vector<std::string> new_arguments = arguments;
 
  616       new_arguments.push_back(std::string(
"1"));
 
  617       return isDescendantOfList(new_arguments);
 
  622       B2WARNING(
"isGrandDaughterOfList is outdated and replaced by isDescendantOfList.");
 
  623       std::vector<std::string> new_arguments = arguments;
 
  624       new_arguments.push_back(std::string(
"2"));
 
  625       return isDescendantOfList(new_arguments);
 
  630       if (arguments.size() > 0) {
 
  631         auto listNames = arguments;
 
  632         auto func = [listNames](
const Particle * particle) -> 
bool {
 
  634           int generation_flag = -1;
 
  637             generation_flag = Belle2::convertString<int>(listNames.back());
 
  638           } 
catch (std::exception& e) {}
 
  640           for (
auto& iListName : listNames)
 
  643               Belle2::convertString<int>(iListName);
 
  645             } 
catch (std::exception& e) {}
 
  648             auto list_comparison  = [](
auto&& 
self, 
const Particle * m, 
const Particle * p, 
int flag)-> 
bool {
 
  650               for (
unsigned i = 0; i < m->getNDaughters(); ++i)
 
  652                 const Particle* daughter = m->getDaughter(i);
 
  653                 if ((flag == 1.) or (flag < 0)) {
 
  654                   if (p->isCopyOf(daughter)) {
 
  660                   if (daughter->getNDaughters() > 0) {
 
  661                     result = 
self(
self, daughter, p, flag - 1);
 
  671             StoreObjPtr<ParticleList> listOfParticles(iListName);
 
  673             if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName << 
" given to isDescendantOfList");
 
  675             for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
 
  676               Particle* iParticle = listOfParticles->getParticle(i);
 
  677               output = list_comparison(list_comparison, iParticle, particle, generation_flag);
 
  687         B2FATAL(
"Wrong number of arguments for meta function isDescendantOfList");
 
  693       if (arguments.size() > 0) {
 
  694         auto listNames = arguments;
 
  695         auto func = [listNames](
const Particle * particle) -> 
bool {
 
  697           int generation_flag = -1;
 
  700             generation_flag = Belle2::convertString<int>(listNames.back());
 
  701           } 
catch (std::exception& e) {}
 
  703           if (particle->getMCParticle() == 
nullptr)
 
  708           for (
auto& iListName : listNames)
 
  711               std::stod(iListName);
 
  713             } 
catch (std::exception& e) {}
 
  715             auto list_comparison  = [](
auto&& 
self, 
const Particle * m, 
const Particle * p, 
int flag)-> 
bool {
 
  717               for (
unsigned i = 0; i < m->getNDaughters(); ++i)
 
  719                 const Particle* daughter = m->getDaughter(i);
 
  720                 if ((flag == 1.) or (flag < 0)) {
 
  721                   if (daughter->getMCParticle() != 
nullptr) {
 
  722                     if (p->getMCParticle()->getArrayIndex() == daughter->getMCParticle()->getArrayIndex()) {
 
  728                   if (daughter->getNDaughters() > 0) {
 
  729                     result = 
self(
self, daughter, p, flag - 1);
 
  739             StoreObjPtr<ParticleList> listOfParticles(iListName);
 
  741             if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName << 
" given to isMCDescendantOfList");
 
  743             for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
 
  744               Particle* iParticle = listOfParticles->getParticle(i);
 
  745               output = list_comparison(list_comparison, iParticle, particle, generation_flag);
 
  755         B2FATAL(
"Wrong number of arguments for meta function isMCDescendantOfList");
 
  761       if (arguments.size() == 1) {
 
  763         auto func = [var](
const Particle * particle) -> 
double {
 
  764           double product = 1.0;
 
  765           if (particle->getNDaughters() == 0)
 
  767             return std::numeric_limits<double>::quiet_NaN();
 
  769           if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
 
  771             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  772               product *= std::get<double>(var->function(particle->getDaughter(j)));
 
  774           } 
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
 
  776             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  777               product *= std::get<int>(var->function(particle->getDaughter(j)));
 
  779           } 
else return std::numeric_limits<double>::quiet_NaN();
 
  784         B2FATAL(
"Wrong number of arguments for meta function daughterProductOf");
 
  790       if (arguments.size() == 1) {
 
  792         auto func = [var](
const Particle * particle) -> 
double {
 
  794           if (particle->getNDaughters() == 0)
 
  796             return std::numeric_limits<double>::quiet_NaN();
 
  798           if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
 
  800             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  801               sum += std::get<double>(var->function(particle->getDaughter(j)));
 
  803           } 
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
 
  805             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  806               sum += std::get<int>(var->function(particle->getDaughter(j)));
 
  808           } 
else return std::numeric_limits<double>::quiet_NaN();
 
  813         B2FATAL(
"Wrong number of arguments for meta function daughterSumOf");
 
  819       if (arguments.size() == 1) {
 
  821         auto func = [var](
const Particle * particle) -> 
double {
 
  822           double min = std::numeric_limits<double>::quiet_NaN();
 
  823           if (particle->getNDaughters() == 0)
 
  825             return std::numeric_limits<double>::quiet_NaN();
 
  827           if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
 
  829             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  830               double iValue = std::get<double>(var->function(particle->getDaughter(j)));
 
  831               if (std::isnan(iValue)) 
continue;
 
  832               if (std::isnan(min)) min = iValue;
 
  833               if (iValue < min) min = iValue;
 
  835           } 
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
 
  837             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  838               int iValue = std::get<int>(var->function(particle->getDaughter(j)));
 
  839               if (std::isnan(min)) min = iValue;
 
  840               if (iValue < min) min = iValue;
 
  847         B2FATAL(
"Wrong number of arguments for meta function daughterLowest");
 
  853       if (arguments.size() == 1) {
 
  855         auto func = [var](
const Particle * particle) -> 
double {
 
  856           double max = std::numeric_limits<double>::quiet_NaN();
 
  857           if (particle->getNDaughters() == 0)
 
  859             return std::numeric_limits<double>::quiet_NaN();
 
  861           if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
 
  863             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  864               double iValue = std::get<double>(var->function(particle->getDaughter(j)));
 
  865               if (std::isnan(iValue)) 
continue;
 
  866               if (std::isnan(max)) max = iValue;
 
  867               if (iValue > max) max = iValue;
 
  869           } 
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
 
  871             for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
 
  872               int iValue = std::get<int>(var->function(particle->getDaughter(j)));
 
  873               if (std::isnan(max)) max = iValue;
 
  874               if (iValue > max) max = iValue;
 
  881         B2FATAL(
"Wrong number of arguments for meta function daughterHighest");
 
  887       if (arguments.size() == 3) {
 
  888         int iDaughterNumber = 0;
 
  889         int jDaughterNumber = 0;
 
  891           iDaughterNumber = Belle2::convertString<int>(arguments[0]);
 
  892           jDaughterNumber = Belle2::convertString<int>(arguments[1]);
 
  893         } 
catch (std::invalid_argument&) {
 
  894           B2FATAL(
"First two arguments of daughterDiffOf meta function must be integers!");
 
  896         auto variablename = arguments[2];
 
  897         auto func = [variablename, iDaughterNumber, jDaughterNumber](
const Particle * particle) -> 
double {
 
  898           if (particle == 
nullptr)
 
  899             return std::numeric_limits<double>::quiet_NaN();
 
  900           if (iDaughterNumber >= 
int(particle->getNDaughters()) || jDaughterNumber >= 
int(particle->getNDaughters()))
 
  901             return std::numeric_limits<double>::quiet_NaN();
 
  905             auto result_j = var->function(particle->getDaughter(jDaughterNumber));
 
  906             auto result_i = var->function(particle->getDaughter(iDaughterNumber));
 
  907             double diff = std::numeric_limits<double>::quiet_NaN();
 
  908             if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i)) {
 
  909               diff = std::get<double>(result_j) - std::get<double>(result_i);
 
  910             } 
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i)) {
 
  911               diff = std::get<int>(result_j) - std::get<int>(result_i);
 
  913               throw std::runtime_error(
"Bad variant access");
 
  915             if (variablename == 
"phi" or variablename == 
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))
 
  916                 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;
 
  930         B2FATAL(
"Wrong number of arguments for meta function daughterDiffOf");
 
  936       if (arguments.size() == 3) {
 
  937         int iDaughterNumber = 0;
 
  938         int jDaughterNumber = 0;
 
  940           iDaughterNumber = Belle2::convertString<int>(arguments[0]);
 
  941           jDaughterNumber = Belle2::convertString<int>(arguments[1]);
 
  942         } 
catch (std::invalid_argument&) {
 
  943           B2FATAL(
"First two arguments of mcDaughterDiffOf meta function must be integers!");
 
  945         auto variablename = arguments[2];
 
  946         auto func = [variablename, iDaughterNumber, jDaughterNumber](
const Particle * particle) -> 
double {
 
  947           if (particle == 
nullptr)
 
  948             return std::numeric_limits<double>::quiet_NaN();
 
  949           if (iDaughterNumber >= 
int(particle->getNDaughters()) || jDaughterNumber >= 
int(particle->getNDaughters()))
 
  950             return std::numeric_limits<double>::quiet_NaN();
 
  951           if (particle->getDaughter(jDaughterNumber)->getMCParticle() == 
nullptr || particle->getDaughter(iDaughterNumber)->getMCParticle() == 
nullptr)
 
  952             return std::numeric_limits<double>::quiet_NaN();
 
  957             Particle iTmpPart(iMcDaughter);
 
  958             Particle jTmpPart(jMcDaughter);
 
  960             auto result_j = var->function(&jTmpPart);
 
  961             auto result_i = var->function(&iTmpPart);
 
  962             double diff = std::numeric_limits<double>::quiet_NaN();
 
  963             if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i)) {
 
  964               diff = std::get<double>(result_j) - std::get<double>(result_i);
 
  965             } 
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i)) {
 
  966               diff = std::get<int>(result_j) - std::get<int>(result_i);
 
  968               throw std::runtime_error(
"Bad variant access");
 
  970             if (variablename == 
"phi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))) {
 
  971               if (fabs(diff) > M_PI) {
 
  973                   diff = diff - 2 * M_PI;
 
  975                   diff = 2 * M_PI + diff;
 
  984         B2FATAL(
"Wrong number of arguments for meta function mcDaughterDiffOf");
 
  990       if (arguments.size() == 5) {
 
  991         int iDaughterNumber = 0, jDaughterNumber = 0, agrandDaughterNumber = 0, bgrandDaughterNumber = 0;
 
  993           iDaughterNumber = Belle2::convertString<int>(arguments[0]);
 
  994           jDaughterNumber = Belle2::convertString<int>(arguments[1]);
 
  995           agrandDaughterNumber = Belle2::convertString<int>(arguments[2]);
 
  996           bgrandDaughterNumber = Belle2::convertString<int>(arguments[3]);
 
  997         } 
catch (std::invalid_argument&) {
 
  998           B2FATAL(
"First four arguments of grandDaughterDiffOf meta function must be integers!");
 
 1000         auto variablename = arguments[4];
 
 1001         auto func = [variablename, iDaughterNumber, jDaughterNumber, agrandDaughterNumber,
 
 1002                       bgrandDaughterNumber](
const Particle * particle) -> 
double {
 
 1003           if (particle == 
nullptr)
 
 1004             return std::numeric_limits<double>::quiet_NaN();
 
 1005           if (iDaughterNumber >= 
int(particle->getNDaughters()) || jDaughterNumber >= 
int(particle->getNDaughters()))
 
 1006             return std::numeric_limits<double>::quiet_NaN();
 
 1007           if (agrandDaughterNumber >= 
int((particle->getDaughter(iDaughterNumber))->getNDaughters()) || bgrandDaughterNumber >= 
int((particle->getDaughter(jDaughterNumber))->getNDaughters()))
 
 1008             return std::numeric_limits<double>::quiet_NaN();
 
 1012             double diff = std::get<double>(var->function((particle->getDaughter(jDaughterNumber))->getDaughter(
 
 1013                                                            bgrandDaughterNumber))) - std::get<double>(var->function((particle->getDaughter(iDaughterNumber))->getDaughter(
 
 1014                                                                  agrandDaughterNumber)));
 
 1015             if (variablename == 
"phi" or variablename == 
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))
 
 1016                 or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)"))) {
 
 1017               if (fabs(diff) > M_PI) {
 
 1019                   diff = diff - 2 * M_PI;
 
 1021                   diff = 2 * M_PI + diff;
 
 1030         B2FATAL(
"Wrong number of arguments for meta function grandDaughterDiffOf");
 
 1036       std::vector<std::string> new_arguments = arguments;
 
 1037       new_arguments.push_back(std::string(
"phi"));
 
 1038       return daughterDiffOf(new_arguments);
 
 1043       std::vector<std::string> new_arguments = arguments;
 
 1044       new_arguments.push_back(std::string(
"phi"));
 
 1045       return mcDaughterDiffOf(new_arguments);
 
 1050       std::vector<std::string> new_arguments = arguments;
 
 1051       new_arguments.push_back(std::string(
"phi"));
 
 1052       return grandDaughterDiffOf(new_arguments);
 
 1057       std::vector<std::string> new_arguments = arguments;
 
 1058       new_arguments.push_back(std::string(
"clusterPhi"));
 
 1059       return daughterDiffOf(new_arguments);
 
 1064       std::vector<std::string> new_arguments = arguments;
 
 1065       new_arguments.push_back(std::string(
"clusterPhi"));
 
 1066       return grandDaughterDiffOf(new_arguments);
 
 1071       std::vector<std::string> new_arguments = arguments;
 
 1072       new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
 
 1073       return daughterDiffOf(new_arguments);
 
 1078       std::vector<std::string> new_arguments = arguments;
 
 1079       new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
 
 1080       return mcDaughterDiffOf(new_arguments);
 
 1085       std::vector<std::string> new_arguments = arguments;
 
 1086       new_arguments.push_back(std::string(
"useCMSFrame(clusterPhi)"));
 
 1087       return daughterDiffOf(new_arguments);
 
 1092       if (arguments.size() == 3) {
 
 1093         int iDaughterNumber = 0;
 
 1094         int jDaughterNumber = 0;
 
 1096           iDaughterNumber = Belle2::convertString<int>(arguments[0]);
 
 1097           jDaughterNumber = Belle2::convertString<int>(arguments[1]);
 
 1098         } 
catch (std::invalid_argument&) {
 
 1099           B2FATAL(
"First two arguments of daughterDiffOf meta function must be integers!");
 
 1102         auto func = [var, iDaughterNumber, jDaughterNumber](
const Particle * particle) -> 
double {
 
 1103           if (particle == 
nullptr)
 
 1104             return std::numeric_limits<double>::quiet_NaN();
 
 1105           if (iDaughterNumber >= 
int(particle->getNDaughters()) || jDaughterNumber >= 
int(particle->getNDaughters()))
 
 1106             return std::numeric_limits<double>::quiet_NaN();
 
 1109             double iValue, jValue;
 
 1110             if (std::holds_alternative<double>(var->function(particle->getDaughter(jDaughterNumber)))) {
 
 1111               iValue = std::get<double>(var->function(particle->getDaughter(iDaughterNumber)));
 
 1112               jValue = std::get<double>(var->function(particle->getDaughter(jDaughterNumber)));
 
 1113             } 
else if (std::holds_alternative<int>(var->function(particle->getDaughter(jDaughterNumber)))) {
 
 1114               iValue = std::get<int>(var->function(particle->getDaughter(iDaughterNumber)));
 
 1115               jValue = std::get<int>(var->function(particle->getDaughter(jDaughterNumber)));
 
 1116             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1117             return (jValue - iValue) / (jValue + iValue);
 
 1122         B2FATAL(
"Wrong number of arguments for meta function daughterNormDiffOf");
 
 1128       if (arguments.size() == 2) {
 
 1129         int daughterNumber = 0;
 
 1131           daughterNumber = Belle2::convertString<int>(arguments[0]);
 
 1132         } 
catch (std::invalid_argument&) {
 
 1133           B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
 
 1135         auto variablename = arguments[1];
 
 1136         auto func = [variablename, daughterNumber](
const Particle * particle) -> 
double {
 
 1137           if (particle == 
nullptr)
 
 1138             return std::numeric_limits<double>::quiet_NaN();
 
 1139           if (daughterNumber >= 
int(particle->getNDaughters()))
 
 1140             return std::numeric_limits<double>::quiet_NaN();
 
 1144             auto result_mother = var->function(particle);
 
 1145             auto result_daughter = var->function(particle->getDaughter(daughterNumber));
 
 1146             double diff = std::numeric_limits<double>::quiet_NaN();
 
 1147             if (std::holds_alternative<double>(result_mother) && std::holds_alternative<double>(result_daughter)) {
 
 1148               diff = std::get<double>(result_mother) - std::get<double>(result_daughter);
 
 1149             } 
else if (std::holds_alternative<int>(result_mother) && std::holds_alternative<int>(result_daughter)) {
 
 1150               diff = std::get<int>(result_mother) - std::get<int>(result_daughter);
 
 1152               throw std::runtime_error(
"Bad variant access");
 
 1155             if (variablename == 
"phi" or variablename == 
"useCMSFrame(phi)") {
 
 1156               if (fabs(diff) > M_PI) {
 
 1158                   diff = diff - 2 * M_PI;
 
 1160                   diff = 2 * M_PI + diff;
 
 1169         B2FATAL(
"Wrong number of arguments for meta function daughterMotherDiffOf");
 
 1175       if (arguments.size() == 2) {
 
 1176         int daughterNumber = 0;
 
 1178           daughterNumber = Belle2::convertString<int>(arguments[0]);
 
 1179         } 
catch (std::invalid_argument&) {
 
 1180           B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
 
 1183         auto func = [var, daughterNumber](
const Particle * particle) -> 
double {
 
 1184           if (particle == 
nullptr)
 
 1185             return std::numeric_limits<double>::quiet_NaN();
 
 1186           if (daughterNumber >= 
int(particle->getNDaughters()))
 
 1187             return std::numeric_limits<double>::quiet_NaN();
 
 1190             double daughterValue = 0.0, motherValue = 0.0;
 
 1191             if (std::holds_alternative<double>(var->function(particle))) {
 
 1192               daughterValue = std::get<double>(var->function(particle->getDaughter(daughterNumber)));
 
 1193               motherValue = std::get<double>(var->function(particle));
 
 1194             } 
else if (std::holds_alternative<int>(var->function(particle))) {
 
 1195               daughterValue = std::get<int>(var->function(particle->getDaughter(daughterNumber)));
 
 1196               motherValue = std::get<int>(var->function(particle));
 
 1198             return (motherValue - daughterValue) / (motherValue + daughterValue);
 
 1203         B2FATAL(
"Wrong number of arguments for meta function daughterMotherNormDiffOf");
 
 1209       if (arguments.size() == 2 || arguments.size() == 3) {
 
 1211         auto func = [arguments](
const Particle * particle) -> 
double {
 
 1212           if (particle == 
nullptr)
 
 1213             return std::numeric_limits<double>::quiet_NaN();
 
 1215           std::vector<ROOT::Math::PxPyPzEVector> pDaus;
 
 1219           for (
auto& generalizedIndex : arguments)
 
 1221             const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
 
 1223               pDaus.push_back(frame.getMomentum(dauPart));
 
 1225               B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
 
 1226               return std::numeric_limits<double>::quiet_NaN();
 
 1231           if (pDaus.size() == 2)
 
 1238         B2FATAL(
"Wrong number of arguments for meta function daughterAngle");
 
 1242     double grandDaughterDecayAngle(
const Particle* particle, 
const std::vector<double>& arguments)
 
 1244       if (arguments.size() == 2) {
 
 1247           return std::numeric_limits<double>::quiet_NaN();
 
 1249         int daughterIndex = std::lround(arguments[0]);
 
 1250         if (daughterIndex >= 
int(particle->getNDaughters()))
 
 1251           return std::numeric_limits<float>::quiet_NaN();
 
 1252         const Particle* dau = particle->getDaughter(daughterIndex);
 
 1254         int grandDaughterIndex = std::lround(arguments[1]);
 
 1255         if (grandDaughterIndex >= 
int(dau->getNDaughters()))
 
 1256           return std::numeric_limits<float>::quiet_NaN();
 
 1258         B2Vector3D  boost = dau->get4Vector().BoostToCM();
 
 1260         ROOT::Math::PxPyPzEVector motherMomentum = - particle->get4Vector();
 
 1261         motherMomentum = ROOT::Math::Boost(boost) * motherMomentum;
 
 1263         ROOT::Math::PxPyPzEVector grandDaughterMomentum = dau->getDaughter(grandDaughterIndex)->get4Vector();
 
 1264         grandDaughterMomentum = ROOT::Math::Boost(boost) * grandDaughterMomentum;
 
 1269         B2FATAL(
"The variable grandDaughterDecayAngle needs exactly two integers as arguments!");
 
 1275       if (arguments.size() == 2 || arguments.size() == 3) {
 
 1277         auto func = [arguments](
const Particle * particle) -> 
double {
 
 1278           if (particle == 
nullptr)
 
 1279             return std::numeric_limits<double>::quiet_NaN();
 
 1281           std::vector<ROOT::Math::PxPyPzEVector> pDaus;
 
 1285           if (particle->getParticleSource() == Particle::EParticleSourceObject::c_MCParticle) 
 
 1287             for (
auto& generalizedIndex : arguments) {
 
 1289               if (mcPart == 
nullptr)
 
 1290                 return std::numeric_limits<double>::quiet_NaN();
 
 1292               if (dauMcPart == 
nullptr)
 
 1293                 return std::numeric_limits<double>::quiet_NaN();
 
 1295               pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
 
 1299             for (
auto& generalizedIndex : arguments) {
 
 1300               const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
 
 1301               if (dauPart == 
nullptr)
 
 1302                 return std::numeric_limits<double>::quiet_NaN();
 
 1305               if (dauMcPart == 
nullptr)
 
 1306                 return std::numeric_limits<double>::quiet_NaN();
 
 1308               pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
 
 1313           if (pDaus.size() == 2)
 
 1320         B2FATAL(
"Wrong number of arguments for meta function mcDaughterAngle");
 
 1324     double daughterClusterAngleInBetween(
const Particle* particle, 
const std::vector<double>& daughterIndices)
 
 1326       if (daughterIndices.size() == 2) {
 
 1327         int daughterIndexi = std::lround(daughterIndices[0]);
 
 1328         int daughterIndexj = std::lround(daughterIndices[1]);
 
 1329         if (std::max(daughterIndexi, daughterIndexj) >= 
int(particle->getNDaughters())) {
 
 1330           return std::numeric_limits<double>::quiet_NaN();
 
 1332           const ECLCluster* clusteri = particle->getDaughter(daughterIndexi)->getECLCluster();
 
 1333           const ECLCluster* clusterj = particle->getDaughter(daughterIndexj)->getECLCluster();
 
 1334           if (clusteri and clusterj) {
 
 1338             ClusterUtils clusutils;
 
 1339             B2Vector3D pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
 
 1340             B2Vector3D pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
 
 1341             return pi.Angle(pj);
 
 1343           return std::numeric_limits<float>::quiet_NaN();
 
 1345       } 
else if (daughterIndices.size() == 3) {
 
 1346         int daughterIndexi = std::lround(daughterIndices[0]);
 
 1347         int daughterIndexj = std::lround(daughterIndices[1]);
 
 1348         int daughterIndexk = std::lround(daughterIndices[2]);
 
 1349         if (std::max(std::max(daughterIndexi, daughterIndexj), daughterIndexk) >= 
int(particle->getNDaughters())) {
 
 1350           return std::numeric_limits<double>::quiet_NaN();
 
 1352           const ECLCluster* clusteri = (particle->getDaughter(daughterIndices[0]))->getECLCluster();
 
 1353           const ECLCluster* clusterj = (particle->getDaughter(daughterIndices[1]))->getECLCluster();
 
 1354           const ECLCluster* clusterk = (particle->getDaughter(daughterIndices[2]))->getECLCluster();
 
 1355           if (clusteri and clusterj and clusterk) {
 
 1360             ClusterUtils clusutils;
 
 1361             B2Vector3D pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
 
 1362             B2Vector3D pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
 
 1363             B2Vector3D pk = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterk, clusterkBit)).Vect();
 
 1364             return pk.
Angle(pi + pj);
 
 1366           return std::numeric_limits<float>::quiet_NaN();
 
 1369         B2FATAL(
"Wrong number of arguments for daughterClusterAngleInBetween!");
 
 1375       if (arguments.size() > 1) {
 
 1376         auto func = [arguments](
const Particle * particle) -> 
double {
 
 1378           ROOT::Math::PxPyPzEVector pSum;
 
 1380           for (
auto& generalizedIndex : arguments)
 
 1382             const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
 
 1384               pSum += frame.getMomentum(dauPart);
 
 1386               return std::numeric_limits<float>::quiet_NaN();
 
 1393         B2FATAL(
"Wrong number of arguments for meta function daughterInvM. At least two integers are needed.");
 
 1399       if (arguments.size() == 2) {
 
 1403           divideBy = Belle2::convertString<int>(arguments[1]);
 
 1404         } 
catch (std::invalid_argument&) {
 
 1405           B2FATAL(
"Second argument of modulo meta function must be integer!");
 
 1407         auto func = [var, divideBy](
const Particle * particle) -> 
int {
 
 1408           auto var_result = var->function(particle);
 
 1409           if (std::holds_alternative<double>(var_result))
 
 1411             return int(std::get<double>(var_result)) % divideBy;
 
 1412           } 
else if (std::holds_alternative<int>(var_result))
 
 1414             return std::get<int>(var_result) % divideBy;
 
 1415           } 
else if (std::holds_alternative<bool>(var_result))
 
 1417             return int(std::get<bool>(var_result)) % divideBy;
 
 1422         B2FATAL(
"Wrong number of arguments for meta function modulo");
 
 1428       if (arguments.size() == 1) {
 
 1431         auto func = [var](
const Particle * particle) -> 
bool { 
return std::isnan(std::get<double>(var->function(particle))); };
 
 1434         B2FATAL(
"Wrong number of arguments for meta function isNAN");
 
 1440       if (arguments.size() == 2) {
 
 1442         double defaultOutput;
 
 1444           defaultOutput = Belle2::convertString<double>(arguments[1]);
 
 1445         } 
catch (std::invalid_argument&) {
 
 1446           B2FATAL(
"The second argument of ifNANgiveX meta function must be a number!");
 
 1448         auto func = [var, defaultOutput](
const Particle * particle) -> 
double {
 
 1449           double output = std::get<double>(var->function(particle));
 
 1450           if (std::isnan(output)) 
return defaultOutput;
 
 1455         B2FATAL(
"Wrong number of arguments for meta function ifNANgiveX");
 
 1461       if (arguments.size() == 1) {
 
 1464         auto func = [var](
const Particle * particle) -> 
bool { 
return std::isinf(std::get<double>(var->function(particle))); };
 
 1467         B2FATAL(
"Wrong number of arguments for meta function isInfinity");
 
 1473       if (arguments.size() >= 2) {
 
 1479         for (
size_t i = 1; i < arguments.size(); ++i) {
 
 1481             finalMask |= Belle2::convertString<int>(arguments[i]);
 
 1482           } 
catch (std::invalid_argument&) {
 
 1483             B2FATAL(
"The input flags to meta function unmask() should be integer!");
 
 1489         auto func = [var, finalMask](
const Particle * particle) -> 
double {
 
 1491           auto var_result = var->function(particle);
 
 1492           if (std::holds_alternative<double>(var_result))
 
 1495             if (std::isnan(std::get<double>(var_result))) {
 
 1496               return std::numeric_limits<double>::quiet_NaN();
 
 1498             value = int(std::get<double>(var_result));
 
 1499           } 
else if (std::holds_alternative<int>(var_result))
 
 1501             value = std::get<int>(var_result);
 
 1505           value &= (~finalMask);
 
 1512         B2FATAL(
"Meta function unmask needs at least two arguments!");
 
 1518       if (arguments.size() == 3) {
 
 1520         std::string cutString = arguments[0];
 
 1526         auto func = [cut, variableIfTrue, variableIfFalse](
const Particle * particle) -> 
double {
 
 1527           if (particle == 
nullptr)
 
 1528             return std::numeric_limits<float>::quiet_NaN();
 
 1529           if (cut->check(particle))
 
 1531             auto var_result = variableIfTrue->function(particle);
 
 1532             if (std::holds_alternative<double>(var_result)) {
 
 1533               return std::get<double>(var_result);
 
 1534             } 
else if (std::holds_alternative<int>(var_result)) {
 
 1535               return std::get<int>(var_result);
 
 1536             } 
else if (std::holds_alternative<bool>(var_result)) {
 
 1537               return std::get<bool>(var_result);
 
 1538             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1541             auto var_result = variableIfFalse->function(particle);
 
 1542             if (std::holds_alternative<double>(var_result)) {
 
 1543               return std::get<double>(var_result);
 
 1544             } 
else if (std::holds_alternative<int>(var_result)) {
 
 1545               return std::get<int>(var_result);
 
 1546             } 
else if (std::holds_alternative<bool>(var_result)) {
 
 1547               return std::get<bool>(var_result);
 
 1548             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1554         B2FATAL(
"Wrong number of arguments for meta function conditionalVariableSelector");
 
 1560       if (arguments.size() > 0) {
 
 1561         std::vector<const Variable::Manager::Var*> variables;
 
 1562         for (
auto& argument : arguments)
 
 1565         auto func = [variables, arguments](
const Particle * particle) -> 
double {
 
 1566           double pValueProduct = 1.;
 
 1567           for (
auto variable : variables)
 
 1569             double pValue = std::get<double>(variable->function(particle));
 
 1573               pValueProduct *= pValue;
 
 1575           double pValueSum = 1.;
 
 1576           double factorial = 1.;
 
 1577           for (
unsigned int i = 1; i < arguments.size(); ++i)
 
 1580             pValueSum += pow(-std::log(pValueProduct), i) / factorial;
 
 1582           return pValueProduct * pValueSum;
 
 1586         B2FATAL(
"Wrong number of arguments for meta function pValueCombination");
 
 1592       if (arguments.size() == 1) {
 
 1594         auto func = [var](
const Particle * particle) -> 
double {
 
 1595           auto var_result = var->function(particle);
 
 1596           if (std::holds_alternative<double>(var_result))
 
 1598             return std::abs(std::get<double>(var_result));
 
 1599           } 
else if (std::holds_alternative<int>(var_result))
 
 1601             return std::abs(std::get<int>(var_result));
 
 1602           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1606         B2FATAL(
"Wrong number of arguments for meta function abs");
 
 1612       if (arguments.size() == 2) {
 
 1617           B2FATAL(
"One or both of the used variables doesn't exist!");
 
 1619         auto func = [var1, var2](
const Particle * particle) -> 
double {
 
 1621           auto var_result1 = var1->function(particle);
 
 1622           auto var_result2 = var2->function(particle);
 
 1623           if (std::holds_alternative<double>(var_result1))
 
 1625             val1 = std::get<double>(var_result1);
 
 1626           } 
else if (std::holds_alternative<int>(var_result1))
 
 1628             val1 = std::get<int>(var_result1);
 
 1630           if (std::holds_alternative<double>(var_result2))
 
 1632             val2 = std::get<double>(var_result2);
 
 1633           } 
else if (std::holds_alternative<int>(var_result2))
 
 1635             val2 = std::get<int>(var_result2);
 
 1637           return std::max(val1, val2);
 
 1641         B2FATAL(
"Wrong number of arguments for meta function max");
 
 1647       if (arguments.size() == 2) {
 
 1652           B2FATAL(
"One or both of the used variables doesn't exist!");
 
 1654         auto func = [var1, var2](
const Particle * particle) -> 
double {
 
 1656           auto var_result1 = var1->function(particle);
 
 1657           auto var_result2 = var2->function(particle);
 
 1658           if (std::holds_alternative<double>(var_result1))
 
 1660             val1 = std::get<double>(var_result1);
 
 1661           } 
else if (std::holds_alternative<int>(var_result1))
 
 1663             val1 = std::get<int>(var_result1);
 
 1665           if (std::holds_alternative<double>(var_result2))
 
 1667             val2 = std::get<double>(var_result2);
 
 1668           } 
else if (std::holds_alternative<int>(var_result2))
 
 1670             val2 = std::get<int>(var_result2);
 
 1672           return std::min(val1, val2);
 
 1676         B2FATAL(
"Wrong number of arguments for meta function min");
 
 1682       if (arguments.size() == 1) {
 
 1684         auto func = [var](
const Particle * particle) -> 
double {
 
 1685           auto var_result = var->function(particle);
 
 1686           if (std::holds_alternative<double>(var_result))
 
 1687             return std::sin(std::get<double>(var_result));
 
 1688           else if (std::holds_alternative<int>(var_result))
 
 1689             return std::sin(std::get<int>(var_result));
 
 1690           else return std::numeric_limits<double>::quiet_NaN();
 
 1694         B2FATAL(
"Wrong number of arguments for meta function sin");
 
 1700       if (arguments.size() == 1) {
 
 1702         auto func = [var](
const Particle * particle) -> 
double {
 
 1703           auto var_result = var->function(particle);
 
 1704           if (std::holds_alternative<double>(var_result))
 
 1705             return std::asin(std::get<double>(var_result));
 
 1706           else if (std::holds_alternative<int>(var_result))
 
 1707             return std::asin(std::get<int>(var_result));
 
 1708           else return std::numeric_limits<double>::quiet_NaN();
 
 1712         B2FATAL(
"Wrong number of arguments for meta function asin");
 
 1718       if (arguments.size() == 1) {
 
 1720         auto func = [var](
const Particle * particle) -> 
double {
 
 1721           auto var_result = var->function(particle);
 
 1722           if (std::holds_alternative<double>(var_result))
 
 1723             return std::cos(std::get<double>(var_result));
 
 1724           else if (std::holds_alternative<int>(var_result))
 
 1725             return std::cos(std::get<int>(var_result));
 
 1726           else return std::numeric_limits<double>::quiet_NaN();
 
 1730         B2FATAL(
"Wrong number of arguments for meta function cos");
 
 1736       if (arguments.size() == 1) {
 
 1738         auto func = [var](
const Particle * particle) -> 
double {
 
 1739           auto var_result = var->function(particle);
 
 1740           if (std::holds_alternative<double>(var_result))
 
 1741             return std::acos(std::get<double>(var_result));
 
 1742           else if (std::holds_alternative<int>(var_result))
 
 1743             return std::acos(std::get<int>(var_result));
 
 1744           else return std::numeric_limits<double>::quiet_NaN();
 
 1748         B2FATAL(
"Wrong number of arguments for meta function acos");
 
 1754       if (arguments.size() == 1) {
 
 1756         auto func = [var](
const Particle * particle) -> 
double { 
return std::tan(std::get<double>(var->function(particle))); };
 
 1759         B2FATAL(
"Wrong number of arguments for meta function tan");
 
 1765       if (arguments.size() == 1) {
 
 1767         auto func = [var](
const Particle * particle) -> 
double { 
return std::atan(std::get<double>(var->function(particle))); };
 
 1770         B2FATAL(
"Wrong number of arguments for meta function atan");
 
 1776       if (arguments.size() == 1) {
 
 1778         auto func = [var](
const Particle * particle) -> 
double {
 
 1779           auto var_result = var->function(particle);
 
 1780           if (std::holds_alternative<double>(var_result))
 
 1781             return std::exp(std::get<double>(var_result));
 
 1782           else if (std::holds_alternative<int>(var_result))
 
 1783             return std::exp(std::get<int>(var_result));
 
 1784           else return std::numeric_limits<double>::quiet_NaN();
 
 1788         B2FATAL(
"Wrong number of arguments for meta function exp");
 
 1794       if (arguments.size() == 1) {
 
 1796         auto func = [var](
const Particle * particle) -> 
double {
 
 1797           auto var_result = var->function(particle);
 
 1798           if (std::holds_alternative<double>(var_result))
 
 1799             return std::log(std::get<double>(var_result));
 
 1800           else if (std::holds_alternative<int>(var_result))
 
 1801             return std::log(std::get<int>(var_result));
 
 1802           else return std::numeric_limits<double>::quiet_NaN();
 
 1806         B2FATAL(
"Wrong number of arguments for meta function log");
 
 1812       if (arguments.size() == 1) {
 
 1814         auto func = [var](
const Particle * particle) -> 
double {
 
 1815           auto var_result = var->function(particle);
 
 1816           if (std::holds_alternative<double>(var_result))
 
 1817             return std::log10(std::get<double>(var_result));
 
 1818           else if (std::holds_alternative<int>(var_result))
 
 1819             return std::log10(std::get<int>(var_result));
 
 1820           else return std::numeric_limits<double>::quiet_NaN();
 
 1824         B2FATAL(
"Wrong number of arguments for meta function log10");
 
 1830       if (arguments.size() == 1) {
 
 1832         auto func = [var](
const Particle * particle) -> 
double {
 
 1833           if (particle == 
nullptr)
 
 1834             return std::numeric_limits<float>::quiet_NaN();
 
 1836           StoreArray<Particle> particles;
 
 1837           if (!particle->hasExtraInfo(
"original_index"))
 
 1838             return std::numeric_limits<float>::quiet_NaN();
 
 1840           auto originalParticle = particles[particle->getExtraInfo(
"original_index")];
 
 1841           if (!originalParticle)
 
 1842             return std::numeric_limits<float>::quiet_NaN();
 
 1843           auto var_result = var->function(originalParticle);
 
 1844           if (std::holds_alternative<double>(var_result))
 
 1846             return std::get<double>(var_result);
 
 1847           } 
else if (std::holds_alternative<int>(var_result))
 
 1849             return std::get<int>(var_result);
 
 1850           } 
else if (std::holds_alternative<bool>(var_result))
 
 1852             return std::get<bool>(var_result);
 
 1853           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1857         B2FATAL(
"Wrong number of arguments for meta function originalParticle");
 
 1863       if (arguments.size() == 2) {
 
 1864         int daughterNumber = 0;
 
 1866           daughterNumber = Belle2::convertString<int>(arguments[0]);
 
 1867         } 
catch (std::invalid_argument&) {
 
 1868           B2FATAL(
"First argument of daughter meta function must be integer!");
 
 1871         auto func = [var, daughterNumber](
const Particle * particle) -> 
double {
 
 1872           if (particle == 
nullptr)
 
 1873             return std::numeric_limits<float>::quiet_NaN();
 
 1874           if (daughterNumber >= 
int(particle->getNDaughters()))
 
 1875             return std::numeric_limits<float>::quiet_NaN();
 
 1878             auto var_result = var->function(particle->getDaughter(daughterNumber));
 
 1879             if (std::holds_alternative<double>(var_result)) {
 
 1880               return std::get<double>(var_result);
 
 1881             } 
else if (std::holds_alternative<int>(var_result)) {
 
 1882               return std::get<int>(var_result);
 
 1883             } 
else if (std::holds_alternative<bool>(var_result)) {
 
 1884               return std::get<bool>(var_result);
 
 1885             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1890         B2FATAL(
"Wrong number of arguments for meta function daughter");
 
 1896       if (arguments.size() == 2) {
 
 1897         int daughterNumber = 0;
 
 1899           daughterNumber = Belle2::convertString<int>(arguments[0]);
 
 1900         } 
catch (std::invalid_argument&) {
 
 1901           B2FATAL(
"First argument of daughter meta function must be integer!");
 
 1904         auto func = [var, daughterNumber](
const Particle * particle) -> 
double {
 
 1905           if (particle == 
nullptr)
 
 1906             return std::numeric_limits<float>::quiet_NaN();
 
 1907           if (daughterNumber >= 
int(particle->getNDaughters()))
 
 1908             return std::numeric_limits<float>::quiet_NaN();
 
 1911             StoreArray<Particle> particles;
 
 1912             if (!particle->getDaughter(daughterNumber)->hasExtraInfo(
"original_index"))
 
 1913               return std::numeric_limits<float>::quiet_NaN();
 
 1914             auto originalDaughter = particles[particle->getDaughter(daughterNumber)->getExtraInfo(
"original_index")];
 
 1915             if (!originalDaughter)
 
 1916               return std::numeric_limits<float>::quiet_NaN();
 
 1918             auto var_result = var->function(originalDaughter);
 
 1919             if (std::holds_alternative<double>(var_result)) {
 
 1920               return std::get<double>(var_result);
 
 1921             } 
else if (std::holds_alternative<int>(var_result)) {
 
 1922               return std::get<int>(var_result);
 
 1923             } 
else if (std::holds_alternative<bool>(var_result)) {
 
 1924               return std::get<bool>(var_result);
 
 1925             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1930         B2FATAL(
"Wrong number of arguments for meta function daughter");
 
 1936       if (arguments.size() == 2) {
 
 1937         int daughterNumber = 0;
 
 1939           daughterNumber = Belle2::convertString<int>(arguments[0]);
 
 1940         } 
catch (std::invalid_argument&) {
 
 1941           B2FATAL(
"First argument of mcDaughter meta function must be integer!");
 
 1944         auto func = [var, daughterNumber](
const Particle * particle) -> 
double {
 
 1945           if (particle == 
nullptr)
 
 1946             return std::numeric_limits<float>::quiet_NaN();
 
 1947           if (particle->getMCParticle()) 
 
 1949             if (daughterNumber >= 
int(particle->getMCParticle()->getNDaughters())) {
 
 1950               return std::numeric_limits<float>::quiet_NaN();
 
 1952             Particle tempParticle = Particle(particle->getMCParticle()->getDaughters().at(daughterNumber));
 
 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);
 
 1960             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1963             return std::numeric_limits<float>::quiet_NaN();
 
 1968         B2FATAL(
"Wrong number of arguments for meta function mcDaughter");
 
 1974       if (arguments.size() == 1) {
 
 1976         auto func = [var](
const Particle * particle) -> 
double {
 
 1977           if (particle == 
nullptr)
 
 1978             return std::numeric_limits<float>::quiet_NaN();
 
 1979           if (particle->getMCParticle()) 
 
 1981             if (particle->getMCParticle()->getMother() == 
nullptr) {
 
 1982               return std::numeric_limits<float>::quiet_NaN();
 
 1984             Particle tempParticle = Particle(particle->getMCParticle()->getMother());
 
 1985             auto var_result = var->function(&tempParticle);
 
 1986             if (std::holds_alternative<double>(var_result)) {
 
 1987               return std::get<double>(var_result);
 
 1988             } 
else if (std::holds_alternative<int>(var_result)) {
 
 1989               return std::get<int>(var_result);
 
 1990             } 
else if (std::holds_alternative<bool>(var_result)) {
 
 1991               return std::get<bool>(var_result);
 
 1992             } 
else return std::numeric_limits<double>::quiet_NaN();
 
 1995             return std::numeric_limits<float>::quiet_NaN();
 
 2000         B2FATAL(
"Wrong number of arguments for meta function mcMother");
 
 2006       if (arguments.size() == 2) {
 
 2007         int particleNumber = 0;
 
 2009           particleNumber = Belle2::convertString<int>(arguments[0]);
 
 2010         } 
catch (std::invalid_argument&) {
 
 2011           B2FATAL(
"First argument of genParticle meta function must be integer!");
 
 2015         auto func = [var, particleNumber](
const Particle*) -> 
double {
 
 2016           StoreArray<MCParticle> mcParticles(
"MCParticles");
 
 2017           if (particleNumber >= mcParticles.getEntries())
 
 2019             return std::numeric_limits<float>::quiet_NaN();
 
 2022           MCParticle* mcParticle = mcParticles[particleNumber];
 
 2023           Particle part = Particle(mcParticle);
 
 2024           auto var_result = var->function(&part);
 
 2025           if (std::holds_alternative<double>(var_result))
 
 2027             return std::get<double>(var_result);
 
 2028           } 
else if (std::holds_alternative<int>(var_result))
 
 2030             return std::get<int>(var_result);
 
 2031           } 
else if (std::holds_alternative<bool>(var_result))
 
 2033             return std::get<bool>(var_result);
 
 2034           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2038         B2FATAL(
"Wrong number of arguments for meta function genParticle");
 
 2044       if (arguments.size() == 1) {
 
 2047         auto func = [var](
const Particle*) -> 
double {
 
 2048           StoreArray<MCParticle> mcParticles(
"MCParticles");
 
 2049           if (mcParticles.getEntries() == 0)
 
 2051             return std::numeric_limits<float>::quiet_NaN();
 
 2054           MCParticle* mcUpsilon4S = mcParticles[0];
 
 2055           if (mcUpsilon4S->getPDG() != 300553)
 
 2057             return std::numeric_limits<float>::quiet_NaN();
 
 2060           Particle upsilon4S = Particle(mcUpsilon4S);
 
 2061           auto var_result = var->function(&upsilon4S);
 
 2062           if (std::holds_alternative<double>(var_result))
 
 2064             return std::get<double>(var_result);
 
 2065           } 
else if (std::holds_alternative<int>(var_result))
 
 2067             return std::get<int>(var_result);
 
 2068           } 
else if (std::holds_alternative<bool>(var_result))
 
 2070             return std::get<bool>(var_result);
 
 2071           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2075         B2FATAL(
"Wrong number of arguments for meta function genUpsilon4S");
 
 2081       if (arguments.size() == 4) {
 
 2082         std::string listName = arguments[0];
 
 2083         std::string rankedVariableName = arguments[1];
 
 2084         std::string returnVariableName = arguments[2];
 
 2085         std::string extraInfoName = rankedVariableName + 
"_rank";
 
 2088           rank = Belle2::convertString<int>(arguments[3]);
 
 2089         } 
catch (std::invalid_argument&)  {
 
 2090           B2ERROR(
"3rd argument of getVariableByRank meta function (Rank) must be an integer!");
 
 2095         auto func = [var, rank, extraInfoName, listName](
const Particle*)-> 
double {
 
 2096           StoreObjPtr<ParticleList> list(listName);
 
 2098           const unsigned int numParticles = list->getListSize();
 
 2099           for (
unsigned int i = 0; i < numParticles; i++)
 
 2101             const Particle* p = list->getParticle(i);
 
 2102             if (p->getExtraInfo(extraInfoName) == rank) {
 
 2103               auto var_result = var->function(p);
 
 2104               if (std::holds_alternative<double>(var_result)) {
 
 2105                 return std::get<double>(var_result);
 
 2106               } 
else if (std::holds_alternative<int>(var_result)) {
 
 2107                 return std::get<int>(var_result);
 
 2108               } 
else if (std::holds_alternative<bool>(var_result)) {
 
 2109                 return std::get<bool>(var_result);
 
 2110               } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2114           return std::numeric_limits<double>::signaling_NaN();
 
 2118         B2FATAL(
"Wrong number of arguments for meta function getVariableByRank");
 
 2124       if (arguments.size() == 1 or arguments.size() == 2) {
 
 2126         std::string listName = arguments[0];
 
 2127         std::string cutString = 
"";
 
 2129         if (arguments.size() == 2) {
 
 2130           cutString = arguments[1];
 
 2135         auto func = [listName, cut](
const Particle*) -> 
int {
 
 2137           StoreObjPtr<ParticleList> list(listName);
 
 2139           for (
unsigned int i = 0; i < list->getListSize(); i++)
 
 2141             const Particle* particle = list->getParticle(i);
 
 2142             if (cut->check(particle)) {
 
 2150         B2FATAL(
"Wrong number of arguments for meta function countInList");
 
 2156       if (arguments.size() == 2 or arguments.size() == 3) {
 
 2158         std::string roeListName = arguments[0];
 
 2159         std::string cutString = arguments[1];
 
 2161         if (arguments.size() == 2) {
 
 2162           B2INFO(
"Use pdgCode of electron as default in meta variable veto, other arguments: " << roeListName << 
", " << cutString);
 
 2165             pdgCode = Belle2::convertString<int>(arguments[2]);;
 
 2166           } 
catch (std::invalid_argument&) {
 
 2167             B2FATAL(
"Third argument of veto meta function must be integer!");
 
 2174         auto func = [roeListName, cut, pdgCode, flavourType](
const Particle * particle) -> 
bool {
 
 2175           StoreObjPtr<ParticleList> roeList(roeListName);
 
 2176           ROOT::Math::PxPyPzEVector vec = particle->get4Vector();
 
 2177           for (
unsigned int i = 0; i < roeList->getListSize(); i++)
 
 2179             const Particle* roeParticle = roeList->getParticle(i);
 
 2180             if (not particle->overlapsWith(roeParticle)) {
 
 2181               ROOT::Math::PxPyPzEVector tempCombination = roeParticle->get4Vector() + vec;
 
 2182               std::vector<int> indices = { particle->getArrayIndex(), roeParticle->getArrayIndex() };
 
 2183               Particle tempParticle = Particle(tempCombination, pdgCode, flavourType, indices, particle->getArrayPointer());
 
 2184               if (cut->check(&tempParticle)) {
 
 2193         B2FATAL(
"Wrong number of arguments for meta function veto");
 
 2199       if (arguments.size() == 1) {
 
 2200         std::string cutString = arguments[0];
 
 2202         auto func = [cut](
const Particle * particle) -> 
int {
 
 2204           for (
auto& daughter : particle->getDaughters())
 
 2206             if (cut->check(daughter))
 
 2213         B2FATAL(
"Wrong number of arguments for meta function countDaughters");
 
 2219       if (arguments.size() == 1) {
 
 2220         std::string cutString = arguments[0];
 
 2222         auto func = [cut](
const Particle * particle) -> 
int {
 
 2224           std::vector<const Particle*> fspDaughters;
 
 2225           particle->fillFSPDaughters(fspDaughters);
 
 2228           for (
auto& daughter : fspDaughters)
 
 2230             if (cut->check(daughter))
 
 2237         B2FATAL(
"Wrong number of arguments for meta function countFSPDaughters");
 
 2243       if (arguments.size() == 1) {
 
 2244         std::string cutString = arguments[0];
 
 2246         auto func = [cut](
const Particle * particle) -> 
int {
 
 2248           std::vector<const Particle*> allDaughters;
 
 2249           particle->fillAllDaughters(allDaughters);
 
 2252           for (
auto& daughter : allDaughters)
 
 2254             if (cut->check(daughter))
 
 2261         B2FATAL(
"Wrong number of arguments for meta function countDescendants");
 
 2265     Manager::FunctionPtr numberOfNonOverlappingParticles(
const std::vector<std::string>& arguments)
 
 2268       auto func = [arguments](
const Particle * particle) -> 
int {
 
 2270         int _numberOfNonOverlappingParticles = 0;
 
 2271         for (
const auto& listName : arguments)
 
 2273           StoreObjPtr<ParticleList> list(listName);
 
 2274           if (not list.isValid()) {
 
 2275             B2FATAL(
"Invalid list named " << listName << 
" encountered in numberOfNonOverlappingParticles.");
 
 2277           for (
unsigned int i = 0; i < list->getListSize(); i++) {
 
 2278             const Particle* p = list->getParticle(i);
 
 2279             if (not particle->overlapsWith(p)) {
 
 2280               _numberOfNonOverlappingParticles++;
 
 2284         return _numberOfNonOverlappingParticles;
 
 2293       if (arguments.size() == 1) {
 
 2295         auto func = [var](
const Particle * particle) -> 
double {
 
 2299             return std::numeric_limits<float>::quiet_NaN();
 
 2301           Particle tmpPart(mcp);
 
 2302           auto var_result = var->function(&tmpPart);
 
 2303           if (std::holds_alternative<double>(var_result))
 
 2305             return std::get<double>(var_result);
 
 2306           } 
else if (std::holds_alternative<int>(var_result))
 
 2308             return std::get<int>(var_result);
 
 2309           } 
else if (std::holds_alternative<bool>(var_result))
 
 2311             return std::get<bool>(var_result);
 
 2312           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2316         B2FATAL(
"Wrong number of arguments for meta function matchedMC");
 
 2322       if (arguments.size() == 1) {
 
 2325         auto func = [var](
const Particle * particle) -> 
double {
 
 2327           const ECLCluster* cluster = particle->getECLCluster();
 
 2328           if (!cluster) 
return std::numeric_limits<double>::quiet_NaN();
 
 2330           auto mcps = cluster->getRelationsTo<MCParticle>();
 
 2331           if (mcps.size() == 0) 
return std::numeric_limits<double>::quiet_NaN();
 
 2333           std::vector<std::pair<double, int>> weightsAndIndices;
 
 2334           for (
unsigned int i = 0; i < mcps.size(); ++i)
 
 2335             weightsAndIndices.emplace_back(mcps.weight(i), i);
 
 2338           std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
 
 2339                     ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
 
 2342           const MCParticle* mcp = mcps.object(weightsAndIndices[0].second);
 
 2344           Particle tmpPart(mcp);
 
 2345           auto var_result = var->function(&tmpPart);
 
 2346           if (std::holds_alternative<double>(var_result))
 
 2348             return std::get<double>(var_result);
 
 2349           } 
else if (std::holds_alternative<int>(var_result))
 
 2351             return std::get<int>(var_result);
 
 2352           } 
else if (std::holds_alternative<bool>(var_result))
 
 2354             return std::get<bool>(var_result);
 
 2357             return std::numeric_limits<double>::quiet_NaN();
 
 2363         B2FATAL(
"Wrong number of arguments for meta function clusterBestMatchedMCParticle");
 
 2367     double matchedMCHasPDG(
const Particle* particle, 
const std::vector<double>& pdgCode)
 
 2369       if (pdgCode.size() != 1) {
 
 2370         B2FATAL(
"Too many arguments provided to matchedMCHasPDG!");
 
 2372       int inputPDG = std::lround(pdgCode[0]);
 
 2376         return std::numeric_limits<double>::quiet_NaN();
 
 2378       return std::abs(mcp->getPDG()) == inputPDG;
 
 2383       if (arguments.size() == 1) {
 
 2384         std::string listName = arguments[0];
 
 2385         auto func = [listName](
const Particle * particle) -> 
double {
 
 2388           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2390           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to totalEnergyOfParticlesInList");
 
 2391           double totalEnergy = 0;
 
 2392           int nParticles = listOfParticles->getListSize();
 
 2393           for (
int i = 0; i < nParticles; i++)
 
 2395             const Particle* part = listOfParticles->getParticle(i);
 
 2397             totalEnergy += frame.getMomentum(part).E();
 
 2404         B2FATAL(
"Wrong number of arguments for meta function totalEnergyOfParticlesInList");
 
 2410       if (arguments.size() == 1) {
 
 2411         std::string listName = arguments[0];
 
 2412         auto func = [listName](
const Particle*) -> 
double {
 
 2413           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2415           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to totalPxOfParticlesInList");
 
 2417           int nParticles = listOfParticles->getListSize();
 
 2419           for (
int i = 0; i < nParticles; i++)
 
 2421             const Particle* part = listOfParticles->getParticle(i);
 
 2422             totalPx += frame.getMomentum(part).Px();
 
 2428         B2FATAL(
"Wrong number of arguments for meta function totalPxOfParticlesInList");
 
 2434       if (arguments.size() == 1) {
 
 2435         std::string listName = arguments[0];
 
 2436         auto func = [listName](
const Particle*) -> 
double {
 
 2437           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2439           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to totalPyOfParticlesInList");
 
 2441           int nParticles = listOfParticles->getListSize();
 
 2443           for (
int i = 0; i < nParticles; i++)
 
 2445             const Particle* part = listOfParticles->getParticle(i);
 
 2446             totalPy += frame.getMomentum(part).Py();
 
 2452         B2FATAL(
"Wrong number of arguments for meta function totalPyOfParticlesInList");
 
 2458       if (arguments.size() == 1) {
 
 2459         std::string listName = arguments[0];
 
 2460         auto func = [listName](
const Particle*) -> 
double {
 
 2461           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2463           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to totalPzOfParticlesInList");
 
 2465           int nParticles = listOfParticles->getListSize();
 
 2467           for (
int i = 0; i < nParticles; i++)
 
 2469             const Particle* part = listOfParticles->getParticle(i);
 
 2470             totalPz += frame.getMomentum(part).Pz();
 
 2476         B2FATAL(
"Wrong number of arguments for meta function totalPzOfParticlesInList");
 
 2482       if (arguments.size() > 0) {
 
 2484         auto func = [arguments](
const Particle * particle) -> 
double {
 
 2486           ROOT::Math::PxPyPzEVector total4Vector;
 
 2488           std::vector<Particle*> particlePool;
 
 2491           for (
const auto& argument : arguments)
 
 2493             StoreObjPtr <ParticleList> listOfParticles(argument);
 
 2495             if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << argument << 
" given to invMassInLists");
 
 2496             int nParticles = listOfParticles->getListSize();
 
 2497             for (
int i = 0; i < nParticles; i++) {
 
 2498               bool overlaps = 
false;
 
 2499               Particle* part = listOfParticles->getParticle(i);
 
 2500               for (
auto poolPart : particlePool) {
 
 2501                 if (part->overlapsWith(poolPart)) {
 
 2507                 total4Vector += part->get4Vector();
 
 2508                 particlePool.push_back(part);
 
 2512           double invariantMass = total4Vector.M();
 
 2513           return invariantMass;
 
 2518         B2FATAL(
"Wrong number of arguments for meta function invMassInLists");
 
 2522     Manager::FunctionPtr totalECLEnergyOfParticlesInList(
const std::vector<std::string>& arguments)
 
 2524       if (arguments.size() == 1) {
 
 2525         std::string listName = arguments[0];
 
 2526         auto func = [listName](
const Particle * particle) -> 
double {
 
 2529           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2531           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to totalEnergyOfParticlesInList");
 
 2532           double totalEnergy = 0;
 
 2533           int nParticles = listOfParticles->getListSize();
 
 2534           for (
int i = 0; i < nParticles; i++)
 
 2536             const Particle* part = listOfParticles->getParticle(i);
 
 2537             const ECLCluster* cluster = part->getECLCluster();
 
 2539             if (cluster != 
nullptr) {
 
 2540               totalEnergy += cluster->getEnergy(clusterHypothesis);
 
 2548         B2FATAL(
"Wrong number of arguments for meta function totalECLEnergyOfParticlesInList");
 
 2554       if (arguments.size() == 1) {
 
 2555         std::string listName = arguments[0];
 
 2556         auto func = [listName](
const Particle*) -> 
double {
 
 2557           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2559           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to maxPtInList");
 
 2560           int nParticles = listOfParticles->getListSize();
 
 2563           for (
int i = 0; i < nParticles; i++)
 
 2565             const Particle* part = listOfParticles->getParticle(i);
 
 2566             const double Pt = frame.getMomentum(part).Pt();
 
 2567             if (Pt > maxPt) maxPt = Pt;
 
 2573         B2FATAL(
"Wrong number of arguments for meta function maxPtInList");
 
 2577     Manager::FunctionPtr eclClusterTrackMatchedWithCondition(
const std::vector<std::string>& arguments)
 
 2579       if (arguments.size() <= 1) {
 
 2581         std::string cutString;
 
 2582         if (arguments.size() == 1)
 
 2583           cutString = arguments[0];
 
 2585         auto func = [cut](
const Particle * particle) -> 
double {
 
 2587           if (particle == 
nullptr)
 
 2588             return std::numeric_limits<double>::quiet_NaN();
 
 2590           const ECLCluster* cluster = particle->getECLCluster();
 
 2594             auto tracks = cluster->getRelationsFrom<Track>();
 
 2596             for (
const auto& track : tracks) {
 
 2599               if (cut->check(&trackParticle))
 
 2604           return std::numeric_limits<double>::quiet_NaN();
 
 2608         B2FATAL(
"Wrong number of arguments for meta function eclClusterSpecialTrackMatched");
 
 2614       if (arguments.size() == 2) {
 
 2615         std::string listName = arguments[0];
 
 2618         auto func = [listName, var](
const Particle*) -> 
double {
 
 2619           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2621           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName << 
" given to averageValueInList");
 
 2622           int nParticles = listOfParticles->getListSize();
 
 2623           if (nParticles == 0)
 
 2625             return std::numeric_limits<double>::quiet_NaN();
 
 2628           if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
 
 2630             for (
int i = 0; i < nParticles; i++) {
 
 2631               average += std::get<double>(var->function(listOfParticles->getParticle(i))) / nParticles;
 
 2633           } 
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
 
 2635             for (
int i = 0; i < nParticles; i++) {
 
 2636               average += std::get<int>(var->function(listOfParticles->getParticle(i))) / nParticles;
 
 2638           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2643         B2FATAL(
"Wrong number of arguments for meta function averageValueInList");
 
 2649       if (arguments.size() == 2) {
 
 2650         std::string listName = arguments[0];
 
 2653         auto func = [listName, var](
const Particle*) -> 
double {
 
 2654           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2656           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName << 
" given to medianValueInList");
 
 2657           int nParticles = listOfParticles->getListSize();
 
 2658           if (nParticles == 0)
 
 2660             return std::numeric_limits<double>::quiet_NaN();
 
 2662           std::vector<double> valuesInList;
 
 2663           if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
 
 2665             for (
int i = 0; i < nParticles; i++) {
 
 2666               valuesInList.push_back(std::get<double>(var->function(listOfParticles->getParticle(i))));
 
 2668           } 
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
 
 2670             for (
int i = 0; i < nParticles; i++) {
 
 2671               valuesInList.push_back(std::get<int>(var->function(listOfParticles->getParticle(i))));
 
 2673           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2674           std::sort(valuesInList.begin(), valuesInList.end());
 
 2675           if (nParticles % 2 != 0)
 
 2677             return valuesInList[nParticles / 2];
 
 2680             return 0.5 * (valuesInList[nParticles / 2] + valuesInList[nParticles / 2 - 1]);
 
 2685         B2FATAL(
"Wrong number of arguments for meta function medianValueInList");
 
 2692       if (arguments.size() != 1)
 
 2693         B2FATAL(
"Wrong number of arguments for meta function angleToClosestInList");
 
 2695       std::string listname = arguments[0];
 
 2697       auto func = [listname](
const Particle * particle) -> 
double {
 
 2699         StoreObjPtr<ParticleList> list(listname);
 
 2700         if (not list.isValid())
 
 2701           B2FATAL(
"Invalid particle list name " << listname << 
" given to angleToClosestInList");
 
 2704         if (list->getListSize() == 0)
 
 2705           return std::numeric_limits<double>::quiet_NaN();
 
 2709         const auto p_this = 
B2Vector3D(frame.getMomentum(particle).Vect());
 
 2712         double minAngle = 2 * M_PI;
 
 2713         for (
unsigned int i = 0; i < list->getListSize(); ++i)
 
 2715           const Particle* compareme = list->getParticle(i);
 
 2716           const auto p_compare = 
B2Vector3D(frame.getMomentum(compareme).Vect());
 
 2717           double angle = p_compare.Angle(p_this);
 
 2718           if (minAngle > angle) minAngle = angle;
 
 2728       if (arguments.size() != 2)
 
 2729         B2FATAL(
"Wrong number of arguments for meta function closestInList");
 
 2731       std::string listname = arguments[0];
 
 2736       auto func = [listname, var](
const Particle * particle) -> 
double {
 
 2738         StoreObjPtr<ParticleList> list(listname);
 
 2739         if (not list.isValid())
 
 2740           B2FATAL(
"Invalid particle list name " << listname << 
" given to closestInList");
 
 2744         const auto p_this = 
B2Vector3D(frame.getMomentum(particle).Vect());
 
 2747         double minAngle = 2 * M_PI;
 
 2749         for (
unsigned int i = 0; i < list->getListSize(); ++i)
 
 2751           const Particle* compareme = list->getParticle(i);
 
 2752           const auto p_compare = 
B2Vector3D(frame.getMomentum(compareme).Vect());
 
 2753           double angle = p_compare.Angle(p_this);
 
 2754           if (minAngle > angle) {
 
 2761         if (iClosest == -1) 
return std::numeric_limits<double>::quiet_NaN();
 
 2762         auto var_result = var->function(list->getParticle(iClosest));
 
 2763         if (std::holds_alternative<double>(var_result))
 
 2765           return std::get<double>(var_result);
 
 2766         } 
else if (std::holds_alternative<int>(var_result))
 
 2768           return std::get<int>(var_result);
 
 2769         } 
else if (std::holds_alternative<bool>(var_result))
 
 2771           return std::get<bool>(var_result);
 
 2772         } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2780       if (arguments.size() != 1)
 
 2781         B2FATAL(
"Wrong number of arguments for meta function angleToMostB2BInList");
 
 2783       std::string listname = arguments[0];
 
 2785       auto func = [listname](
const Particle * particle) -> 
double {
 
 2787         StoreObjPtr<ParticleList> list(listname);
 
 2788         if (not list.isValid())
 
 2789           B2FATAL(
"Invalid particle list name " << listname << 
" given to angleToMostB2BInList");
 
 2792         if (list->getListSize() == 0)
 
 2793           return std::numeric_limits<double>::quiet_NaN();
 
 2797         const auto p_this = 
B2Vector3D(frame.getMomentum(particle).Vect());
 
 2801         double maxAngle = 0;
 
 2802         for (
unsigned int i = 0; i < list->getListSize(); ++i)
 
 2804           const Particle* compareme = list->getParticle(i);
 
 2805           const auto p_compare = 
B2Vector3D(frame.getMomentum(compareme).Vect());
 
 2806           double angle = p_compare.Angle(p_this);
 
 2807           if (maxAngle < angle) maxAngle = angle;
 
 2817       if (arguments.size() != 2)
 
 2818         B2FATAL(
"Wrong number of arguments for meta function mostB2BInList");
 
 2820       std::string listname = arguments[0];
 
 2825       auto func = [listname, var](
const Particle * particle) -> 
double {
 
 2827         StoreObjPtr<ParticleList> list(listname);
 
 2828         if (not list.isValid())
 
 2829           B2FATAL(
"Invalid particle list name " << listname << 
" given to mostB2BInList");
 
 2833         const auto p_this = 
B2Vector3D(frame.getMomentum(particle).Vect());
 
 2837         double maxAngle = -1.0;
 
 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 (maxAngle < angle) {
 
 2851         if (iMostB2B == -1) 
return std::numeric_limits<double>::quiet_NaN();
 
 2852         auto var_result = var->function(list->getParticle(iMostB2B));
 
 2853         if (std::holds_alternative<double>(var_result))
 
 2855           return std::get<double>(var_result);
 
 2856         } 
else if (std::holds_alternative<int>(var_result))
 
 2858           return std::get<int>(var_result);
 
 2859         } 
else if (std::holds_alternative<bool>(var_result))
 
 2861           return std::get<bool>(var_result);
 
 2862         } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2869       if (arguments.size() == 1) {
 
 2870         std::string listName = arguments[0];
 
 2871         auto func = [listName](
const Particle*) -> 
double {
 
 2872           StoreObjPtr<ParticleList> listOfParticles(listName);
 
 2874           if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName << 
" given to maxOpeningAngleInList");
 
 2875           int nParticles = listOfParticles->getListSize();
 
 2877           if (nParticles < 2) 
return std::numeric_limits<double>::quiet_NaN();
 
 2880           double maxOpeningAngle = -1;
 
 2881           for (
int i = 0; i < nParticles; i++)
 
 2883             B2Vector3D v1 = frame.getMomentum(listOfParticles->getParticle(i)).Vect();
 
 2884             for (
int j = i + 1; j < nParticles; j++) {
 
 2885               B2Vector3D v2 = frame.getMomentum(listOfParticles->getParticle(j)).Vect();
 
 2886               const double angle = v1.
Angle(v2);
 
 2887               if (angle > maxOpeningAngle) maxOpeningAngle = angle;
 
 2890           return maxOpeningAngle;
 
 2894         B2FATAL(
"Wrong number of arguments for meta function maxOpeningAngleInList");
 
 2901       if (arguments.size() >= 2) {
 
 2906         auto func = [var, arguments](
const Particle * particle) -> 
double {
 
 2907           if (particle == 
nullptr)
 
 2909             B2WARNING(
"Trying to access a daughter that does not exist. Skipping");
 
 2910             return std::numeric_limits<float>::quiet_NaN();
 
 2915           ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
 
 2919           for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++)
 
 2921             auto generalizedIndex = arguments[iCoord];
 
 2922             const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
 
 2924               pSum +=  frame.getMomentum(dauPart);
 
 2926               B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
 
 2927               return std::numeric_limits<float>::quiet_NaN();
 
 2932           Particle sumOfDaughters(pSum, 100); 
 
 2934           auto var_result = var->function(&sumOfDaughters);
 
 2936           if (std::holds_alternative<double>(var_result))
 
 2938             return std::get<double>(var_result);
 
 2939           } 
else if (std::holds_alternative<int>(var_result))
 
 2941             return std::get<int>(var_result);
 
 2942           } 
else if (std::holds_alternative<bool>(var_result))
 
 2944             return std::get<bool>(var_result);
 
 2945           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 2949         B2FATAL(
"Wrong number of arguments for meta function daughterCombination");
 
 2952     Manager::FunctionPtr useAlternativeDaughterHypothesis(
const std::vector<std::string>& arguments)
 
 2965       if (arguments.size() >= 2) {
 
 2976         std::unordered_map<unsigned int, int> mapOfReplacedDaughters;
 
 2979         for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++) {
 
 2980           auto replacedDauString = arguments[iCoord];
 
 2982           std::vector<std::string> indexAndMass;
 
 2983           boost::split(indexAndMass, replacedDauString, boost::is_any_of(
":"));
 
 2986           if (indexAndMass.size() > 2) {
 
 2987             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 " 
 2988                       << replacedDauString << 
", while a correct syntax looks like 0:K+.");
 
 2992           if (indexAndMass.size() < 2) {
 
 2993             B2WARNING(
"The string indicating which daughter's mass should be replaced contains only one colon-separated element instead of two. The offending string is " 
 2994                       << replacedDauString << 
", while a correct syntax looks like 0:K+.");
 
 3001             dauIndex = Belle2::convertString<int>(indexAndMass[0]);
 
 3002           } 
catch (std::invalid_argument&) {
 
 3003             B2FATAL(
"Found the string " << indexAndMass[0] << 
"instead of a daughter index.");
 
 3007           TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(indexAndMass[1].c_str());
 
 3009             B2WARNING(
"Particle not in evt.pdl file! " << indexAndMass[1]);
 
 3014           int pdgCode = particlePDG->PdgCode();
 
 3015           mapOfReplacedDaughters[dauIndex] = pdgCode;
 
 3019         if (mapOfReplacedDaughters.size() != arguments.size() - 1)
 
 3020           B2FATAL(
"Overlapped daughter's index is detected in the meta-variable useAlternativeDaughterHypothesis");
 
 3028         auto func = [var, mapOfReplacedDaughters](
const Particle * particle) -> 
double {
 
 3029           if (particle == 
nullptr)
 
 3031             B2WARNING(
"Trying to access a particle that does not exist. Skipping");
 
 3032             return std::numeric_limits<float>::quiet_NaN();
 
 3041           ROOT::Math::PxPyPzMVector pSum(0, 0, 0, 0);
 
 3043           for (
unsigned int iDau = 0; iDau < particle->getNDaughters(); iDau++)
 
 3045             const Particle* dauPart = particle->getDaughter(iDau);
 
 3047               B2WARNING(
"Trying to access a daughter that does not exist. Index = " << iDau);
 
 3048               return std::numeric_limits<float>::quiet_NaN();
 
 3051             ROOT::Math::PxPyPzMVector dauMom = ROOT::Math::PxPyPzMVector(frame.getMomentum(dauPart));
 
 3055               pdgCode = mapOfReplacedDaughters.at(iDau);
 
 3056             } 
catch (std::out_of_range&) {
 
 3063             double p_x = dauMom.Px();
 
 3064             double p_y = dauMom.Py();
 
 3065             double p_z = dauMom.Pz();
 
 3066             dauMom.SetCoordinates(p_x, p_y, p_z, TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass());
 
 3067             const_cast<Particle*
>(dummy->getDaughter(iDau))->set4VectorDividingByMomentumScaling(ROOT::Math::PxPyPzEVector(dauMom));
 
 3070             const int charge = dummy->getDaughter(iDau)->getCharge();
 
 3071             if (TDatabasePDG::Instance()->GetParticle(pdgCode)->Charge() / 3.0 == 
charge)
 
 3072               const_cast<Particle*
>(dummy->getDaughter(iDau))->setPDGCode(pdgCode);
 
 3074               const_cast<Particle*
>(dummy->getDaughter(iDau))->setPDGCode(-1 * pdgCode);
 
 3080           dummy->set4Vector(ROOT::Math::PxPyPzEVector(pSum));
 
 3082           auto var_result = var->function(dummy);
 
 3085           if (std::holds_alternative<double>(var_result))
 
 3087             return std::get<double>(var_result);
 
 3088           } 
else if (std::holds_alternative<int>(var_result))
 
 3090             return std::get<int>(var_result);
 
 3091           } 
else if (std::holds_alternative<bool>(var_result))
 
 3093             return std::get<bool>(var_result);
 
 3094           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 3099         B2FATAL(
"Wrong number of arguments for meta function useAlternativeDaughterHypothesis");
 
 3104       if (arguments.size() == 2) {
 
 3106         std::string arg = arguments[0];
 
 3108         TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
 
 3110         if (part != 
nullptr) {
 
 3111           pdg_code = std::abs(part->PdgCode());
 
 3114             pdg_code = Belle2::convertString<int>(arg);
 
 3115           } 
catch (std::exception& e) {}
 
 3118         if (pdg_code == -1) {
 
 3119           B2FATAL(
"Ancestor " + arg + 
" is not recognised. Please provide valid PDG code or particle name.");
 
 3122         auto func = [pdg_code, var](
const Particle * particle) -> 
double {
 
 3123           const Particle* p = particle;
 
 3125           int ancestor_level = std::get<double>(
Manager::Instance().getVariable(
"hasAncestor(" + std::to_string(pdg_code) + 
", 0)")->
function(p));
 
 3126           if ((ancestor_level <= 0) or (std::isnan(ancestor_level)))
 
 3128             return std::numeric_limits<float>::quiet_NaN();
 
 3131           const MCParticle* i_p = p->getMCParticle();
 
 3133           for (
int a = 0; a < ancestor_level ; a = a + 1)
 
 3135             i_p = i_p->getMother();
 
 3138           auto var_result = var->function(&m_p);
 
 3139           if (std::holds_alternative<double>(var_result))
 
 3141             return std::get<double>(var_result);
 
 3142           } 
else if (std::holds_alternative<int>(var_result))
 
 3144             return std::get<int>(var_result);
 
 3145           } 
else if (std::holds_alternative<bool>(var_result))
 
 3147             return std::get<bool>(var_result);
 
 3148           } 
else return std::numeric_limits<double>::quiet_NaN();
 
 3152         B2FATAL(
"Wrong number of arguments for meta function varForFirstMCAncestorOfType (expected 2: type and variable of interest)");
 
 3156     VARIABLE_GROUP(
"MetaFunctions");
 
 3157     REGISTER_METAVARIABLE(
"nCleanedECLClusters(cut)", nCleanedECLClusters,
 
 3158                           "[Eventbased] Returns the number of clean Clusters in the event\n" 
 3159                           "Clean clusters are defined by the clusters which pass the given cut assuming a photon hypothesis.",
 
 3160                           Manager::VariableDataType::c_int);
 
 3161     REGISTER_METAVARIABLE(
"nCleanedTracks(cut)", nCleanedTracks,
 
 3162                           "[Eventbased] Returns the number of clean Tracks in the event\n" 
 3163                           "Clean tracks are defined by the tracks which pass the given cut assuming a pion hypothesis.", Manager::VariableDataType::c_int);
 
 3164     REGISTER_METAVARIABLE(
"formula(v1 + v2 * [v3 - v4] / v5^v6)", formula, R
"DOCSTRING( 
 3165 Returns the result of the given formula, where v1 to vN are variables or floating 
 3166 point numbers. Currently the only supported operations are addition (``+``), 
 3167 subtraction (``-``), multiplication (``*``), division (``/``) and power (``^`` 
 3168 or ``**``). Parenthesis can be in the form of square brackets ``[v1 * v2]`` 
 3169 or normal brackets ``(v1 * v2)``. It will work also with variables taking 
 3170 arguments. Operator precedence is taken into account. For example :: 
 3172     (daughter(0, E) + daughter(1, E))**2 - p**2 + 0.138 
 3174 .. versionchanged:: release-03-00-00 
 3175    now both, ``[]`` and ``()`` can be used for grouping operations, ``**`` can 
 3176    be used for exponent and float literals are possible directly in the 
 3178 )DOCSTRING", Manager::VariableDataType::c_double); 
 3179     REGISTER_METAVARIABLE("useRestFrame(variable)", useRestFrame,
 
 3180                       "Returns the value of the variable using the rest frame of the given particle as current reference frame.\n" 
 3181                       "E.g. ``useRestFrame(daughter(0, p))`` returns the total momentum of the first daughter in its mother's rest-frame", Manager::VariableDataType::c_double);
 
 3182     REGISTER_METAVARIABLE(
"useCMSFrame(variable)", useCMSFrame,
 
 3183                       "Returns the value of the variable using the CMS frame as current reference frame.\n" 
 3184                       "E.g. ``useCMSFrame(E)`` returns the energy of a particle in the CMS frame.", Manager::VariableDataType::c_double);
 
 3185     REGISTER_METAVARIABLE(
"useLabFrame(variable)", useLabFrame, R
"DOC( 
 3186 Returns the value of ``variable`` in the *lab* frame. 
 3189     The lab frame is the default reference frame, usually you don't need to use this meta-variable. 
 3190     E.g. ``useLabFrame(E)`` returns the energy of a particle in the Lab frame, same as just ``E``. 
 3192 Specifying the lab frame is useful in some corner-cases. For example: 
 3193 ``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. 
 3194 )DOC", Manager::VariableDataType::c_double); 
 3195     REGISTER_METAVARIABLE("useTagSideRecoilRestFrame(variable, daughterIndexTagB)", useTagSideRecoilRestFrame,
 
 3196                       "Returns the value of the variable in the rest frame of the recoiling particle to the tag side B meson.\n" 
 3197                       "The variable should only be applied to an Upsilon(4S) list.\n" 
 3198                       "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);
 
 3199     REGISTER_METAVARIABLE(
"useParticleRestFrame(variable, particleList)", useParticleRestFrame,
 
 3200                       "Returns the value of the variable in the rest frame of the first Particle contained in the given ParticleList.\n" 
 3201           "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. " 
 3202           "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for " 
 3203           "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);
 
 3204     REGISTER_METAVARIABLE(
"useRecoilParticleRestFrame(variable, particleList)", useRecoilParticleRestFrame,
 
 3205                       "Returns the value of the variable in the rest frame of recoil system against the first Particle contained in the given ParticleList.\n" 
 3206           "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. " 
 3207           "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for " 
 3208           "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);
 
 3209     REGISTER_METAVARIABLE(
"useDaughterRestFrame(variable, daughterIndex_1, [daughterIndex_2, ... daughterIndex_3])", useDaughterRestFrame,
 
 3210                       "Returns the value of the variable in the rest frame of the selected daughter particle.\n" 
 3211           "The daughter is identified via generalized daughter index, e.g. ``0:1`` identifies the second daughter (1) " 
 3212           "of the first daughter (0). If the daughter index is invalid, it returns NaN.\n" 
 3213           "If two or more indices are given, the rest frame of the sum of the daughters is used.",
 
 3214           Manager::VariableDataType::c_double);
 
 3215     REGISTER_METAVARIABLE(
"passesCut(cut)", passesCut,
 
 3216                       "Returns 1 if particle passes the cut otherwise 0.\n" 
 3217                       "Useful if you want to write out if a particle would have passed a cut or not.", Manager::VariableDataType::c_bool);
 
 3218     REGISTER_METAVARIABLE(
"passesEventCut(cut)", passesEventCut,
 
 3219                       "[Eventbased] Returns 1 if event passes the cut otherwise 0.\n" 
 3220                       "Useful if you want to select events passing a cut without looping into particles, such as for skimming.\n", Manager::VariableDataType::c_bool);
 
 3221     REGISTER_METAVARIABLE(
"countDaughters(cut)", countDaughters,
 
 3222                       "Returns number of direct daughters which satisfy the cut.\n" 
 3223                       "Used by the skimming package (for what exactly?)", Manager::VariableDataType::c_int);
 
 3224     REGISTER_METAVARIABLE(
"countFSPDaughters(cut)", countDescendants,
 
 3225         "Returns number of final-state daughters which satisfy the cut.",
 
 3226         Manager::VariableDataType::c_int);
 
 3227     REGISTER_METAVARIABLE(
"countDescendants(cut)", countDescendants,
 
 3228         "Returns number of descendants for all generations which satisfy the cut.",
 
 3229         Manager::VariableDataType::c_int);
 
 3230     REGISTER_METAVARIABLE(
"varFor(pdgCode, variable)", varFor,
 
 3231                       "Returns the value of the variable for the given particle if its abs(pdgCode) agrees with the given one.\n" 
 3232                       "E.g. ``varFor(11, p)`` returns the momentum if the particle is an electron or a positron.", Manager::VariableDataType::c_double);
 
 3233     REGISTER_METAVARIABLE(
"varForMCGen(variable)", varForMCGen,
 
 3234                       "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" 
 3235                       "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" 
 3236                       "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);
 
 3237     REGISTER_METAVARIABLE(
"nParticlesInList(particleListName)", nParticlesInList,
 
 3238                       "[Eventbased] Returns number of particles in the given particle List.", Manager::VariableDataType::c_int);
 
 3239     REGISTER_METAVARIABLE(
"isInList(particleListName)", isInList,
 
 3240                       "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);
 
 3241     REGISTER_METAVARIABLE(
"isDaughterOfList(particleListNames)", isDaughterOfList,
 
 3242                       "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);
 
 3243     REGISTER_METAVARIABLE(
"isDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isDescendantOfList, R
"DOC( 
 3244                       Returns 1 if the given particle appears in the decay chain of the particles in the given ParticleLists. 
 3246                       Passing an integer as the last argument, allows to check if the particle belongs to the specific generation: 
 3248                       * ``isDescendantOfList(<particle_list>,1)`` returns 1 if particle is a daughter of the list, 
 3249                       * ``isDescendantOfList(<particle_list>,2)`` returns 1 if particle is a granddaughter of the list, 
 3250                       * ``isDescendantOfList(<particle_list>,3)`` returns 1 if particle is a great-granddaughter of the list, etc. 
 3251                       * Default value is ``-1`` that is inclusive for all generations. 
 3252                       )DOC", Manager::VariableDataType::c_bool); 
 3253     REGISTER_METAVARIABLE("isMCDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isMCDescendantOfList, R
"DOC( 
 3254                       Returns 1 if the given particle is linked to the same MC particle as any reconstructed daughter of the decay lists. 
 3256                       Passing an integer as the last argument, allows to check if the particle belongs to the specific generation: 
 3258                       * ``isMCDescendantOfList(<particle_list>,1)`` returns 1 if particle is matched to the same particle as any daughter of the list, 
 3259                       * ``isMCDescendantOfList(<particle_list>,2)`` returns 1 if particle is matched to the same particle as any granddaughter of the list, 
 3260                       * ``isMCDescendantOfList(<particle_list>,3)`` returns 1 if particle is matched to the same particle as any great-granddaughter of the list, etc. 
 3261                       * Default value is ``-1`` that is inclusive for all generations. 
 3263                       It makes only sense for lists created with `fillParticleListFromMC` function with ``addDaughters=True`` argument. 
 3264                       )DOC", Manager::VariableDataType::c_bool); 
 3266     REGISTER_METAVARIABLE("sourceObjectIsInList(particleListName)", sourceObjectIsInList, R
"DOC( 
 3267 Returns 1 if the underlying mdst object (e.g. track, or cluster) was used to create a particle in ``particleListName``, 0 if not.  
 3270   This only makes sense for particles that are not composite. Returns -1 for composite particles. 
 3271 )DOC", Manager::VariableDataType::c_int); 
 3273     REGISTER_METAVARIABLE("mcParticleIsInMCList(particleListName)", mcParticleIsInMCList, R
"DOC( 
 3274 Returns 1 if the particle's matched MC particle is also matched to a particle in ``particleListName``  
 3275 (or if either of the lists were filled from generator level `modularAnalysis.fillParticleListFromMC`.) 
 3277 .. seealso:: :b2:var:`isMCDescendantOfList` to check daughters. 
 3278 )DOC", Manager::VariableDataType::c_bool); 
 3280     REGISTER_METAVARIABLE("isGrandDaughterOfList(particleListNames)", isGrandDaughterOfList,
 
 3281                       "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);
 
 3282     REGISTER_METAVARIABLE(
"originalParticle(variable)", originalParticle, R
"DOC( 
 3283                       Returns value of variable for the original particle from which the given particle is copied. 
 3285                       The copy of particle is created, for example, when the vertex fit updates the daughters and `modularAnalysis.copyParticles` is called. 
 3286                       Returns NaN if the given particle is not copied and so there is no original particle. 
 3287                       )DOC", Manager::VariableDataType::c_double); 
 3288     REGISTER_METAVARIABLE("daughter(i, variable)", daughter, R
"DOC( 
 3289                       Returns value of variable for the i-th daughter. E.g. 
 3291                       * ``daughter(0, p)`` returns the total momentum of the first daughter. 
 3292                       * ``daughter(0, daughter(1, p)`` returns the total momentum of the second daughter of the first daughter. 
 3294                       Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters). 
 3295                       )DOC", Manager::VariableDataType::c_double); 
 3296     REGISTER_METAVARIABLE("originalDaughter(i, variable)", originalDaughter, R
"DOC( 
 3297                       Returns value of variable for the original particle from which the i-th daughter is copied. 
 3299                       The copy of particle is created, for example,  when the vertex fit updates the daughters and `modularAnalysis.copyParticles` is called. 
 3300                       Returns NaN if the daughter is not copied and so there is no original daughter. 
 3302                       Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters). 
 3303                       )DOC", Manager::VariableDataType::c_double); 
 3304     REGISTER_METAVARIABLE("mcDaughter(i, variable)", mcDaughter, R
"DOC( 
 3305                       Returns the value of the requested variable for the i-th Monte Carlo daughter of the particle. 
 3307                       Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle, 
 3308                       or if the i-th MC daughter does not exist. 
 3310                       E.g. ``mcDaughter(0, PDG)`` will return the PDG code of the first MC daughter of the matched MC 
 3311                       particle of the reconstructed particle the function is applied to. 
 3313                       The meta variable can also be nested: ``mcDaughter(0, mcDaughter(1, PDG))``. 
 3314                       )DOC", Manager::VariableDataType::c_double); 
 3315     REGISTER_METAVARIABLE("mcMother(variable)", mcMother, R
"DOC( 
 3316                       Returns the value of the requested variable for the Monte Carlo mother of the particle. 
 3318                       Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle, 
 3319                       or if the MC mother does not exist. 
 3321                       E.g. ``mcMother(PDG)`` will return the PDG code of the MC mother of the matched MC 
 3322                       particle of the reconstructed particle the function is applied to. 
 3324                       The meta variable can also be nested: ``mcMother(mcMother(PDG))``. 
 3325                       )DOC", Manager::VariableDataType::c_double); 
 3326     REGISTER_METAVARIABLE("genParticle(index, variable)", genParticle,  R
"DOC( 
 3327 [Eventbased] Returns the ``variable`` for the ith generator particle. 
 3328 The arguments of the function must be the ``index`` of the particle in the MCParticle Array, 
 3329 and ``variable``, the name of the function or variable for that generator particle. 
 3330 If ``index`` goes beyond the length of the MCParticles array, NaN will be returned. 
 3332 E.g. ``genParticle(0, p)`` returns the total momentum of the first MCParticle, which is 
 3333 the Upsilon(4S) in a generic decay. 
 3334 ``genParticle(0, mcDaughter(1, p)`` returns the total momentum of the second daughter of 
 3335 the first MC Particle, which is the momentum of the second B meson in a generic decay. 
 3336 )DOC", Manager::VariableDataType::c_double); 
 3337     REGISTER_METAVARIABLE("genUpsilon4S(variable)", genUpsilon4S, R
"DOC( 
 3338 [Eventbased] Returns the ``variable`` evaluated for the generator-level :math:`\Upsilon(4S)`. 
 3339 If no generator level :math:`\Upsilon(4S)` exists for the event, NaN will be returned. 
 3341 E.g. ``genUpsilon4S(p)`` returns the total momentum of the :math:`\Upsilon(4S)` in a generic decay. 
 3342 ``genUpsilon4S(mcDaughter(1, p)`` returns the total momentum of the second daughter of the 
 3343 generator-level :math:`\Upsilon(4S)` (i.e. the momentum of the second B meson in a generic decay. 
 3344 )DOC", Manager::VariableDataType::c_double); 
 3345     REGISTER_METAVARIABLE("daughterProductOf(variable)", daughterProductOf,
 
 3346                       "Returns product of a variable over all daughters.\n" 
 3347                       "E.g. ``daughterProductOf(extraInfo(SignalProbability))`` returns the product of the SignalProbabilitys of all daughters.", Manager::VariableDataType::c_double);
 
 3348     REGISTER_METAVARIABLE(
"daughterSumOf(variable)", daughterSumOf,
 
 3349                       "Returns sum of a variable over all daughters.\n" 
 3350                       "E.g. ``daughterSumOf(nDaughters)`` returns the number of grand-daughters.", Manager::VariableDataType::c_double);
 
 3351     REGISTER_METAVARIABLE(
"daughterLowest(variable)", daughterLowest,
 
 3352                       "Returns the lowest value of the given variable among all daughters.\n" 
 3353                       "E.g. ``useCMSFrame(daughterLowest(p))`` returns the lowest momentum in CMS frame.", Manager::VariableDataType::c_double);
 
 3354     REGISTER_METAVARIABLE(
"daughterHighest(variable)", daughterHighest,
 
 3355                       "Returns the highest value of the given variable among all daughters.\n" 
 3356                       "E.g. ``useCMSFrame(daughterHighest(p))`` returns the highest momentum in CMS frame.", Manager::VariableDataType::c_double);
 
 3357     REGISTER_METAVARIABLE(
"daughterDiffOf(i, j, variable)", daughterDiffOf,
 
 3358                       "Returns the difference of a variable between the two given daughters.\n" 
 3359                       "E.g. ``useRestFrame(daughterDiffOf(0, 1, p))`` returns the momentum difference between first and second daughter in the rest frame of the given particle.\n" 
 3360                       "(That means that it returns :math:`p_j - p_i`)\n" 
 3361                       "Nota Bene: for the particular case 'variable=phi' you should use the :b2:var:`daughterDiffOfPhi` function.", Manager::VariableDataType::c_double);
 
 3362     REGISTER_METAVARIABLE(
"mcDaughterDiffOf(i, j, variable)", mcDaughterDiffOf,
 
 3363                       "MC matched version of the `daughterDiffOf` function.", Manager::VariableDataType::c_double);
 
 3364     REGISTER_METAVARIABLE(
"grandDaughterDiffOf(i, j, variable)", grandDaughterDiffOf,
 
 3365                       "Returns the difference of a variable between the first daughters of the two given daughters.\n" 
 3366                       "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" 
 3367                       "(That means that it returns :math:`p_j - p_i`)\n" 
 3368                       "Nota Bene: for the particular case 'variable=phi' you should use the :b2:var:`grandDaughterDiffOfPhi` function.", Manager::VariableDataType::c_double);
 
 3369     REGISTER_METAVARIABLE(
"daughterDiffOfPhi(i, j)", daughterDiffOfPhi,
 
 3370                       "Returns the difference in :math:`\\phi` between the two given daughters. The unit of the angle is ``rad``.\n" 
 3371                       "The difference is signed and takes account of the ordering of the given daughters.\n" 
 3372                       "The function returns :math:`\\phi_j - \\phi_i`.", Manager::VariableDataType::c_double);
 
 3373     MAKE_DEPRECATED(
"daughterDiffOfPhi", 
false, 
"release-06-00-00", R
"DOC( 
 3374                      The difference of the azimuthal angle :math:`\\phi` of two daughters can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC"); 
 3375     REGISTER_METAVARIABLE("mcDaughterDiffOfPhi(i, j)", mcDaughterDiffOfPhi,
 
 3376                       "MC matched version of the `daughterDiffOfPhi` function. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
 
 3377     MAKE_DEPRECATED(
"mcDaughterDiffOfPhi", 
false, 
"release-06-00-00", R
"DOC( 
 3378                      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"); 
 3379     REGISTER_METAVARIABLE("grandDaughterDiffOfPhi(i, j)", grandDaughterDiffOfPhi,
 
 3380                       "Returns the difference in :math:`\\phi` between the first daughters of the two given daughters. The unit of the angle is ``rad``.\n" 
 3381                       "The difference is signed and takes account of the ordering of the given daughters.\n" 
 3382                       "The function returns :math:`\\phi_j - \\phi_i`.\n", Manager::VariableDataType::c_double);
 
 3383     MAKE_DEPRECATED(
"grandDaughterDiffOfPhi", 
false, 
"release-06-00-00", R
"DOC( 
 3384                      The difference of the azimuthal angle :math:`\\phi` of two granddaughters can be calculated with the generic variable :b2:var:`grandDaughterDiffOf`.)DOC"); 
 3385     REGISTER_METAVARIABLE("daughterDiffOfClusterPhi(i, j)", daughterDiffOfClusterPhi,
 
 3386                       "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters. The unit of the angle is ``rad``.\n" 
 3387                       "The difference is signed and takes account of the ordering of the given daughters.\n" 
 3388                       "The function returns :math:`\\phi_j - \\phi_i`.\n" 
 3389                       "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);
 
 3390     MAKE_DEPRECATED(
"daughterDiffOfClusterPhi", 
false, 
"release-06-00-00", R
"DOC( 
 3391                      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"); 
 3392     REGISTER_METAVARIABLE("grandDaughterDiffOfClusterPhi(i, j)", grandDaughterDiffOfClusterPhi,
 
 3393                       "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" 
 3394                       "The difference is signed and takes account of the ordering of the given daughters.\n" 
 3395                       "The function returns :math:`\\phi_j - \\phi_i`.\n" 
 3396                       "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);
 
 3397     MAKE_DEPRECATED(
"grandDaughterDiffOfClusterPhi", 
false, 
"release-06-00-00", R
"DOC( 
 3398                      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"); 
 3399     REGISTER_METAVARIABLE("daughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
 
 3400                       "Returns the difference in :math:`\\phi` between the two given daughters in the CMS frame. The unit of the angle is ``rad``.\n" 
 3401                       "The difference is signed and takes account of the ordering of the given daughters.\n" 
 3402                       "The function returns :math:`\\phi_j - \\phi_i`.", Manager::VariableDataType::c_double);
 
 3403     MAKE_DEPRECATED(
"daughterDiffOfPhiCMS", 
false, 
"release-06-00-00", R
"DOC( 
 3404                      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"); 
 3405     REGISTER_METAVARIABLE("mcDaughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
 
 3406                       "MC matched version of the `daughterDiffOfPhiCMS` function. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
 
 3407     MAKE_DEPRECATED(
"mcDaughterDiffOfPhiCMS", 
false, 
"release-06-00-00", R
"DOC( 
 3408                      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"); 
 3409     REGISTER_METAVARIABLE("daughterDiffOfClusterPhiCMS(i, j)", daughterDiffOfClusterPhiCMS,
 
 3410                       "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" 
 3411                       "The difference is signed and takes account of the ordering of the given daughters.\n" 
 3412                       "The function returns :math:`\\phi_j - \\phi_i``.\n" 
 3413                       "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);
 
 3414     MAKE_DEPRECATED(
"daughterDiffOfClusterPhiCMS", 
false, 
"release-06-00-00", R
"DOC( 
 3415                      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"); 
 3416     REGISTER_METAVARIABLE("daughterNormDiffOf(i, j, variable)", daughterNormDiffOf,
 
 3417                       "Returns the normalized difference of a variable between the two given daughters.\n" 
 3418                       "E.g. ``daughterNormDiffOf(0, 1, p)`` returns the normalized momentum difference between first and second daughter in the lab frame.", Manager::VariableDataType::c_double);
 
 3419     REGISTER_METAVARIABLE(
"daughterMotherDiffOf(i, variable)", daughterMotherDiffOf,
 
 3420                       "Returns the difference of a variable between the given daughter and the mother particle itself.\n" 
 3421                       "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);
 
 3422     REGISTER_METAVARIABLE(
"daughterMotherNormDiffOf(i, variable)", daughterMotherNormDiffOf,
 
 3423                       "Returns the normalized difference of a variable between the given daughter and the mother particle itself.\n" 
 3424                       "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);
 
 3425     REGISTER_METAVARIABLE(
"daughterAngle(daughterIndex_1, daughterIndex_2[, daughterIndex_3])", daughterAngle, R
"DOC( 
 3426                        Returns the angle in between any pair of particles belonging to the same decay tree. 
 3427                        The unit of the angle is ``rad``. 
 3429                        The particles are identified via generalized daughter indexes, which are simply colon-separated lists of 
 3430                        daughter indexes, ordered starting from the root particle. For example, ``0:1:3``  identifies the fourth 
 3431                        daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply 
 3432                        identifies the second daughter of the root particle. 
 3434                        Both two and three generalized indexes can be given to ``daughterAngle``. If two indices are given, the 
 3435                        variable returns the angle between the momenta of the two given particles. If three indices are given, the 
 3436                        variable returns the angle between the momentum of the third particle and a vector which is the sum of the 
 3437                        first two daughter momenta. 
 3440                            ``daughterAngle(0, 3)`` will return the angle between the first and fourth daughter. 
 3441                            ``daughterAngle(0, 1, 3)`` will return the angle between the fourth daughter and the sum of the first and 
 3443                            ``daughterAngle(0:0, 3:0)`` will return the angle between the first daughter of the first daughter, and 
 3444                            the first daughter of the fourth daughter. 
 3446                       )DOC", Manager::VariableDataType::c_double); 
 3447     REGISTER_METAVARIABLE("mcDaughterAngle(daughterIndex_1, daughterIndex_2, [daughterIndex_3])", mcDaughterAngle,
 
 3448                       "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);
 
 3449     REGISTER_VARIABLE(
"grandDaughterDecayAngle(i, j)", grandDaughterDecayAngle,
 
 3450                       "Returns the decay angle of the granddaughter in the daughter particle's rest frame.\n" 
 3451                       "It is calculated with respect to the reverted momentum vector of the particle.\n" 
 3452                       "Two arguments representing the daughter and granddaughter indices have to be provided as arguments.\n\n", 
"rad");
 
 3453     REGISTER_VARIABLE(
"daughterClusterAngleInBetween(i, j)", daughterClusterAngleInBetween,
 
 3454                       "Returns the angle between clusters associated to the two daughters." 
 3455                       "If two indices given: returns the angle between the momenta of the clusters associated to the two given daughters." 
 3456                       "If three indices given: returns the angle between the momentum of the third particle's cluster and a vector " 
 3457                       "which is the sum of the first two daughter's cluster momenta." 
 3458                       "Returns nan if any of the daughters specified don't have an associated cluster." 
 3459                       "The arguments in the argument vector must be integers corresponding to the ith and jth (and kth) daughters.\n\n", 
"rad");
 
 3460     REGISTER_METAVARIABLE(
"daughterInvM(i[, j, ...])", daughterInvM, R
"DOC( 
 3461                        Returns the invariant mass adding the Lorentz vectors of the given daughters. The unit of the invariant mass is GeV/:math:`\text{c}^2` 
 3462                        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. 
 3464                        Daughters from different generations of the decay tree can be combined using generalized daughter indexes, 
 3465                        which are simply colon-separated daughter indexes for each generation, starting from the root particle. For 
 3466                        example, ``0:1:3`` identifies the fourth daughter (3) of the second daughter (1) of the first daughter(0) of 
 3467                        the mother particle. 
 3469                        Returns NaN if the given daughter-index is out of bound (>= number of daughters))DOC", Manager::VariableDataType::c_double); 
 3470     REGISTER_METAVARIABLE("extraInfo(name)", extraInfo,
 
 3471                       "Returns extra info stored under the given name.\n" 
 3472                       "The extraInfo has to be set by a module first.\n" 
 3473                       "E.g. ``extraInfo(SignalProbability)`` returns the SignalProbability calculated by the ``MVAExpert`` module.\n" 
 3474                       "If nothing is set under the given name or if the particle is a nullptr, NaN is returned.\n" 
 3475                       "In the latter case please use `eventExtraInfo` if you want to access an EventExtraInfo variable.", Manager::VariableDataType::c_double);
 
 3476     REGISTER_METAVARIABLE(
"eventExtraInfo(name)", eventExtraInfo,
 
 3477                       "[Eventbased] Returns extra info stored under the given name in the event extra info.\n" 
 3478                       "The extraInfo has to be set first by another module like MVAExpert in event mode.\n" 
 3479                       "If nothing is set under this name, NaN is returned.", Manager::VariableDataType::c_double);
 
 3480     REGISTER_METAVARIABLE(
"eventCached(variable)", eventCached,
 
 3481                       "[Eventbased] Returns value of event-based variable and caches this value in the EventExtraInfo.\n" 
 3482                       "The result of second call to this variable in the same event will be provided from the cache.\n" 
 3483                       "It is recommended to use this variable in order to declare custom aliases as event-based. This is " 
 3484                       "necessary if using the eventwise mode of variablesToNtuple).", Manager::VariableDataType::c_double);
 
 3485     REGISTER_METAVARIABLE(
"particleCached(variable)", particleCached,
 
 3486                       "Returns value of given variable and caches this value in the ParticleExtraInfo of the provided particle.\n" 
 3487                       "The result of second call to this variable on the same particle will be provided from the cache.", Manager::VariableDataType::c_double);
 
 3488     REGISTER_METAVARIABLE(
"modulo(variable, n)", modulo,
 
 3489                       "Returns rest of division of variable by n.", Manager::VariableDataType::c_int);
 
 3490     REGISTER_METAVARIABLE(
"abs(variable)", abs,
 
 3491                       "Returns absolute value of the given variable.\n" 
 3492                       "E.g. abs(mcPDG) returns the absolute value of the mcPDG, which is often useful for cuts.", Manager::VariableDataType::c_double);
 
 3493     REGISTER_METAVARIABLE(
"max(var1,var2)", max, 
"Returns max value of two variables.\n", Manager::VariableDataType::c_double);
 
 3494     REGISTER_METAVARIABLE(
"min(var1,var2)", min, 
"Returns min value of two variables.\n", Manager::VariableDataType::c_double);
 
 3495     REGISTER_METAVARIABLE(
"sin(variable)", sin, 
"Returns sine value of the given variable.", Manager::VariableDataType::c_double);
 
 3496     REGISTER_METAVARIABLE(
"asin(variable)", asin, 
"Returns arcsine of the given variable. The unit of the asin() is ``rad``", Manager::VariableDataType::c_double);
 
 3497     REGISTER_METAVARIABLE(
"cos(variable)", cos, 
"Returns cosine value of the given variable.", Manager::VariableDataType::c_double);
 
 3498     REGISTER_METAVARIABLE(
"acos(variable)", acos, 
"Returns arccosine value of the given variable. The unit of the acos() is ``rad``", Manager::VariableDataType::c_double);
 
 3499     REGISTER_METAVARIABLE(
"tan(variable)", tan, 
"Returns tangent value of the given variable.", Manager::VariableDataType::c_double);
 
 3500     REGISTER_METAVARIABLE(
"atan(variable)", atan, 
"Returns arctangent value of the given variable. The unit of the atan() is ``rad``", Manager::VariableDataType::c_double);
 
 3501     REGISTER_METAVARIABLE(
"exp(variable)", exp, 
"Returns exponential evaluated for the given variable.", Manager::VariableDataType::c_double);
 
 3502     REGISTER_METAVARIABLE(
"log(variable)", log, 
"Returns natural logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
 
 3503     REGISTER_METAVARIABLE(
"log10(variable)", log10, 
"Returns base-10 logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
 
 3504     REGISTER_METAVARIABLE(
"isNAN(variable)", isNAN,
 
 3505                       "Returns true if variable value evaluates to nan (determined via std::isnan(double)).\n" 
 3506                       "Useful for debugging.", Manager::VariableDataType::c_bool);
 
 3507     REGISTER_METAVARIABLE(
"ifNANgiveX(variable, x)", ifNANgiveX,
 
 3508                       "Returns x (has to be a number) if variable value is nan (determined via std::isnan(double)).\n" 
 3509                       "Useful for technical purposes while training MVAs.", Manager::VariableDataType::c_double);
 
 3510     REGISTER_METAVARIABLE(
"isInfinity(variable)", isInfinity,
 
 3511                       "Returns true if variable value evaluates to infinity (determined via std::isinf(double)).\n" 
 3512                       "Useful for debugging.", Manager::VariableDataType::c_bool);
 
 3513     REGISTER_METAVARIABLE(
"unmask(variable, flag1, flag2, ...)", unmask,
 
 3514                       "unmask(variable, flag1, flag2, ...) or unmask(variable, mask) sets certain bits in the variable to zero.\n" 
 3515                       "For example, if you want to set the second, fourth and fifth bits to zero, you could call \n" 
 3516                       "``unmask(variable, 2, 8, 16)`` or ``unmask(variable, 26)``.\n" 
 3517                       "", Manager::VariableDataType::c_double);
 
 3518     REGISTER_METAVARIABLE(
"conditionalVariableSelector(cut, variableIfTrue, variableIfFalse)", conditionalVariableSelector,
 
 3519                       "Returns one of the two supplied variables, depending on whether the particle passes the supplied cut.\n" 
 3520                       "The first variable is returned if the particle passes the cut, and the second variable is returned otherwise.", Manager::VariableDataType::c_double);
 
 3521     REGISTER_METAVARIABLE(
"pValueCombination(p1, p2, ...)", pValueCombination,
 
 3522                       "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" 
 3523                       "If any of the p-values is invalid, i.e. smaller than zero, -1 is returned.", Manager::VariableDataType::c_double);
 
 3524     REGISTER_METAVARIABLE(
"veto(particleList, cut, pdgCode = 11)", veto,
 
 3525                       "Combines current particle with particles from the given particle list and returns 1 if the combination passes the provided cut. \n" 
 3526                       "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" 
 3527                       "around the neutral Pion mass (e.g. ``0.130 < M < 0.140``). \n" 
 3528                       "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);
 
 3529     REGISTER_METAVARIABLE(
"matchedMC(variable)", matchedMC,
 
 3530                       "Returns variable output for the matched MCParticle by constructing a temporary Particle from it.\n" 
 3531                       "This may not work too well if your variable requires accessing daughters of the particle.\n" 
 3532                       "E.g. ``matchedMC(p)`` returns the total momentum of the related MCParticle.\n" 
 3533                       "Returns NaN if no matched MCParticle exists.", Manager::VariableDataType::c_double);
 
 3534     REGISTER_METAVARIABLE(
"clusterBestMatchedMCParticle(variable)", clusterBestMatchedMCParticle,
 
 3535                       "Returns variable output for the MCParticle that is best-matched with the ECLCluster of the given Particle.\n" 
 3536                       "E.g. To get the energy of the MCParticle that matches best with an ECLCluster, one could use ``clusterBestMatchedMCParticle(E)``\n" 
 3537                       "When the variable is called for ``gamma`` and if the ``gamma`` is matched with MCParticle, it works same as `matchedMC`.\n" 
 3538                       "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" 
 3539                       "Returns NaN if the particle is not matched to an ECLCluster, or if the ECLCluster has no matching MCParticles", Manager::VariableDataType::c_double);
 
 3540     REGISTER_METAVARIABLE(
"countInList(particleList, cut='')", countInList, 
"[Eventbased] " 
 3541                       "Returns number of particle which pass given in cut in the specified particle list.\n" 
 3542                       "Useful for creating statistics about the number of particles in a list.\n" 
 3543                       "E.g. ``countInList(e+, isSignal == 1)`` returns the number of correctly reconstructed electrons in the event.\n" 
 3544                       "The variable is event-based and does not need a valid particle pointer as input.", Manager::VariableDataType::c_int);
 
 3545     REGISTER_METAVARIABLE(
"getVariableByRank(particleList, rankedVariableName, variableName, rank)", getVariableByRank, R
"DOC( 
 3546                       [Eventbased] Returns the value of ``variableName`` for the candidate in the ``particleList`` with the requested ``rank``. 
 3549                         The `BestCandidateSelection` module available via `rankByHighest` / `rankByLowest` has to be used before. 
 3552                         The first candidate matching the given rank is used. 
 3553                         Thus, it is not recommended to use this variable in conjunction with ``allowMultiRank`` in the `BestCandidateSelection` module. 
 3555                       The suffix ``_rank`` is automatically added to the argument ``rankedVariableName``, 
 3556                       which either has to be the name of the variable used to order the candidates or the selected outputVariable name without the ending ``_rank``. 
 3557                       This means that your selected name for the rank variable has to end with ``_rank``. 
 3559                       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>`_ 
 3560                       )DOC", Manager::VariableDataType::c_double); 
 3561     REGISTER_VARIABLE("matchedMCHasPDG(PDGCode)", matchedMCHasPDG,
 
 3562                       "Returns if the absolute value of the PDGCode of the MCParticle related to the Particle matches a given PDGCode." 
 3563                       "Returns 0/NAN/1 if PDGCode does not match/is not available/ matches");
 
 3564     REGISTER_METAVARIABLE(
"numberOfNonOverlappingParticles(pList1, pList2, ...)", numberOfNonOverlappingParticles,
 
 3565                       "Returns the number of non-overlapping particles in the given particle lists" 
 3566                       "Useful to check if there is additional physics going on in the detector if one reconstructed the Y4S", Manager::VariableDataType::c_int);
 
 3567     REGISTER_METAVARIABLE(
"totalEnergyOfParticlesInList(particleListName)", totalEnergyOfParticlesInList,
 
 3568                       "Returns the total energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
 
 3569     REGISTER_METAVARIABLE(
"totalPxOfParticlesInList(particleListName)", totalPxOfParticlesInList,
 
 3570                       "Returns the total momentum Px of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
 
 3571     REGISTER_METAVARIABLE(
"totalPyOfParticlesInList(particleListName)", totalPyOfParticlesInList,
 
 3572                       "Returns the total momentum Py of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
 
 3573     REGISTER_METAVARIABLE(
"totalPzOfParticlesInList(particleListName)", totalPzOfParticlesInList,
 
 3574                       "Returns the total momentum Pz of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
 
 3575     REGISTER_METAVARIABLE(
"invMassInLists(pList1, pList2, ...)", invMassInLists,
 
 3576                       "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);
 
 3577     REGISTER_METAVARIABLE(
"totalECLEnergyOfParticlesInList(particleListName)", totalECLEnergyOfParticlesInList,
 
 3578                       "Returns the total ECL energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
 
 3579     REGISTER_METAVARIABLE(
"maxPtInList(particleListName)", maxPtInList,
 
 3580                       "Returns maximum transverse momentum Pt in the given particle List. The unit of the transverse momentum is ``GeV/c``", Manager::VariableDataType::c_double);
 
 3581     REGISTER_METAVARIABLE(
"eclClusterSpecialTrackMatched(cut)", eclClusterTrackMatchedWithCondition,
 
 3582                       "Returns if at least one Track that satisfies the given condition is related to the ECLCluster of the Particle.", Manager::VariableDataType::c_double);
 
 3583     REGISTER_METAVARIABLE(
"averageValueInList(particleListName, variable)", averageValueInList,
 
 3584                       "Returns the arithmetic mean of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
 
 3585     REGISTER_METAVARIABLE(
"medianValueInList(particleListName, variable)", medianValueInList,
 
 3586                       "Returns the median value of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
 
 3587     REGISTER_METAVARIABLE(
"angleToClosestInList(particleListName)", angleToClosestInList,
 
 3588                       "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);
 
 3589     REGISTER_METAVARIABLE(
"closestInList(particleListName, variable)", closestInList,
 
 3590                       "Returns `variable` for the closest particle (smallest opening angle) in the list provided.", Manager::VariableDataType::c_double);
 
 3591     REGISTER_METAVARIABLE(
"angleToMostB2BInList(particleListName)", angleToMostB2BInList,
 
 3592                       "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);
 
 3593     REGISTER_METAVARIABLE(
"mostB2BInList(particleListName, variable)", mostB2BInList,
 
 3594                       "Returns `variable` for the most back-to-back particle (closest opening angle to 180) in the list provided.", Manager::VariableDataType::c_double);
 
 3595     REGISTER_METAVARIABLE(
"maxOpeningAngleInList(particleListName)", maxOpeningAngleInList,
 
 3596                       "Returns maximum opening angle in the given particle List. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
 
 3597     REGISTER_METAVARIABLE(
"daughterCombination(variable, daughterIndex_1, daughterIndex_2 ... daughterIndex_n)", daughterCombination,R
"DOC( 
 3598 Returns a ``variable`` function only of the 4-momentum calculated on an arbitrary set of (grand)daughters. 
 3601     ``variable`` can only be a function of the daughters' 4-momenta. 
 3603 Daughters from different generations of the decay tree can be combined using generalized daughter indexes, which are simply colon-separated 
 3604 the list of daughter indexes, starting from the root particle: for example, ``0:1:3``  identifies the fourth 
 3605 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. 
 3608     ``daughterCombination(M, 0, 3, 4)`` will return the invariant mass of the system made of the first, fourth and fifth daughter of particle. 
 3609     ``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. 
 3611 )DOC", Manager::VariableDataType::c_double); 
 3612     REGISTER_METAVARIABLE("useAlternativeDaughterHypothesis(variable, daughterIndex_1:newMassHyp_1, ..., daughterIndex_n:newMassHyp_n)", useAlternativeDaughterHypothesis,R
"DOC( 
 3613 Returns a ``variable`` calculated using new mass hypotheses for (some of) the particle's daughters. 
 3616     ``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. 
 3617     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. 
 3618     Also, the track fit is not performed again: the variable only re-calculates the 4-vectors using different mass assumptions. 
 3619     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). 
 3622     Generalized daughter indexes are not supported (yet!): this variable can be used only on first-generation daughters. 
 3625     ``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. 
 3626     ``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. 
 3628 )DOC", Manager::VariableDataType::c_double); 
 3629     REGISTER_METAVARIABLE("varForFirstMCAncestorOfType(type, variable)",varForFirstMCAncestorOfType,R
"DOC(Returns requested variable of the first ancestor of the given type. 
 3630 Ancestor type can be set up by PDG code or by particle name (check evt.pdl for valid particle names))DOC", Manager::VariableDataType::c_double) 
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 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...
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
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.