10#include <analysis/variables/MetaVariables.h>
11#include <analysis/variables/MCTruthVariables.h>
13#include <analysis/VariableManager/Utility.h>
14#include <analysis/dataobjects/Particle.h>
15#include <analysis/dataobjects/ParticleList.h>
16#include <analysis/dataobjects/EventKinematics.h>
17#include <analysis/utility/PCmsLabTransform.h>
18#include <analysis/utility/ReferenceFrame.h>
19#include <analysis/utility/EvtPDLUtil.h>
20#include <analysis/utility/ParticleCopy.h>
21#include <analysis/utility/ValueIndexPairSorting.h>
22#include <analysis/ClusterUtility/ClusterUtils.h>
23#include <analysis/variables/VariableFormulaConstructor.h>
25#include <framework/logging/Logger.h>
26#include <framework/datastore/StoreArray.h>
27#include <framework/datastore/StoreObjPtr.h>
28#include <framework/dataobjects/EventExtraInfo.h>
29#include <framework/utilities/Conversion.h>
30#include <framework/utilities/MakeROOTCompatible.h>
31#include <framework/gearbox/Const.h>
33#include <mdst/dataobjects/Track.h>
34#include <mdst/dataobjects/MCParticle.h>
35#include <mdst/dataobjects/ECLCluster.h>
36#include <mdst/dataobjects/TrackFitResult.h>
38#include <boost/algorithm/string.hpp>
45#include <TDatabasePDG.h>
46#include <Math/Vector4D.h>
47#include <Math/VectorUtil.h>
58 if (arguments.size() == 1) {
60 auto func = [var](
const Particle * particle) ->
double {
61 UseReferenceFrame<RestFrame> frame(particle);
62 double result = std::get<double>(var->function(particle));
67 B2FATAL(
"Wrong number of arguments for meta function useRestFrame");
73 if (arguments.size() == 1) {
75 auto func = [var](
const Particle * particle) ->
double {
76 UseReferenceFrame<CMSFrame> frame;
77 double result = std::get<double>(var->function(particle));
82 B2FATAL(
"Wrong number of arguments for meta function useCMSFrame");
88 if (arguments.size() == 1) {
90 auto func = [var](
const Particle * particle) ->
double {
91 UseReferenceFrame<LabFrame> frame;
92 double result = std::get<double>(var->function(particle));
97 B2FATAL(
"Wrong number of arguments for meta function useLabFrame");
103 if (arguments.size() == 2) {
105 auto daughterFunction = convertToDaughterIndex({arguments[1]});
106 auto func = [var, daughterFunction](
const Particle * particle) ->
double {
107 int daughterIndexTagB = std::get<int>(daughterFunction(particle));
108 if (daughterIndexTagB < 0)
111 if (particle->getPDGCode() != 300553)
113 B2ERROR(
"Variable should only be used on a Upsilon(4S) Particle List!");
118 ROOT::Math::PxPyPzEVector pSigB = T.getBeamFourMomentum() - particle->getDaughter(daughterIndexTagB)->get4Vector();
119 Particle tmp(pSigB, -particle->getDaughter(daughterIndexTagB)->getPDGCode());
121 UseReferenceFrame<RestFrame> frame(&tmp);
122 double result = std::get<double>(var->function(particle));
128 B2FATAL(
"Wrong number of arguments for meta function useTagSideRecoilRestFrame");
134 if (arguments.size() == 2) {
136 std::string listName = arguments[1];
137 auto func = [var, listName](
const Particle * particle) ->
double {
138 StoreObjPtr<ParticleList> list(listName);
139 unsigned listSize = list->getListSize();
143 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."
144 << LogVar(
"ParticleList", listName)
145 << LogVar(
"Number of candidates in the list", listSize));
146 const Particle* p = list->getParticle(0);
147 UseReferenceFrame<RestFrame> frame(p);
148 double result = std::get<double>(var->function(particle));
153 B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
159 if (arguments.size() == 2) {
161 std::string listName = arguments[1];
162 auto func = [var, listName](
const Particle * particle) ->
double {
163 StoreObjPtr<ParticleList> list(listName);
164 unsigned listSize = list->getListSize();
168 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."
169 << LogVar(
"ParticleList", listName)
170 << LogVar(
"Number of candidates in the list", listSize));
171 const Particle* p = list->getParticle(0);
173 ROOT::Math::PxPyPzEVector recoil = T.getBeamFourMomentum() - p->get4Vector();
175 Particle pRecoil(recoil, 0);
176 pRecoil.setVertex(particle->getVertex());
177 UseReferenceFrame<RestFrame> frame(&pRecoil);
178 double result = std::get<double>(var->function(particle));
183 B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
189 if (arguments.size() >= 2) {
191 auto func = [var, arguments](
const Particle * particle) ->
double {
194 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
196 for (
unsigned int i = 1; i < arguments.size(); i++)
198 auto generalizedIndex = arguments[i];
199 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
201 pSum += dauPart->get4Vector();
205 Particle tmp(pSum, 0);
206 UseReferenceFrame<RestFrame> frame(&tmp);
207 double result = std::get<double>(var->function(particle));
212 B2FATAL(
"Wrong number of arguments for meta function useDaughterRestFrame.");
218 if (arguments.size() >= 2) {
220 auto func = [var, arguments](
const Particle * particle) ->
double {
223 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
225 for (
unsigned int i = 1; i < arguments.size(); i++)
227 auto generalizedIndex = arguments[i];
228 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
230 pSum += dauPart->get4Vector();
235 ROOT::Math::PxPyPzEVector recoil = T.getBeamFourMomentum() - pSum;
237 Particle pRecoil(recoil, 0);
238 UseReferenceFrame<RestFrame> frame(&pRecoil);
239 double result = std::get<double>(var->function(particle));
244 B2FATAL(
"Wrong number of arguments for meta function useDaughterRecoilRestFrame.");
250 if (arguments.size() == 1) {
252 auto func = [var](
const Particle * particle) ->
double {
253 int index = ancestorBIndex(particle);
255 StoreArray<MCParticle> mcparticles;
256 Particle temp(mcparticles[index]);
257 UseReferenceFrame<RestFrame> frame(&temp);
258 double result = std::get<double>(var->function(particle));
263 B2FATAL(
"Wrong number of arguments for meta function useMCancestorBRestFrame.");
269 if (arguments.size() == 1) {
270 auto extraInfoName = arguments[0];
271 auto func = [extraInfoName](
const Particle * particle) ->
double {
272 if (particle ==
nullptr)
274 B2WARNING(
"Returns NaN because the particle is nullptr! If you want EventExtraInfo variables, please use eventExtraInfo() instead");
277 if (particle->hasExtraInfo(extraInfoName))
279 return particle->getExtraInfo(extraInfoName);
287 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
293 if (arguments.size() == 1) {
294 auto extraInfoName = arguments[0];
295 auto func = [extraInfoName](
const Particle*) ->
double {
296 StoreObjPtr<EventExtraInfo> eventExtraInfo;
297 if (not eventExtraInfo.isValid())
299 if (eventExtraInfo->hasExtraInfo(extraInfoName))
301 return eventExtraInfo->getExtraInfo(extraInfoName);
309 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
315 if (arguments.size() == 1) {
318 auto func = [var, key](
const Particle*) ->
double {
320 StoreObjPtr<EventExtraInfo> eventExtraInfo;
321 if (not eventExtraInfo.isValid())
322 eventExtraInfo.create();
323 if (eventExtraInfo->hasExtraInfo(key))
325 return eventExtraInfo->getExtraInfo(key);
329 auto var_result = var->function(
nullptr);
330 if (std::holds_alternative<double>(var_result)) {
331 value = std::get<double>(var_result);
332 }
else if (std::holds_alternative<int>(var_result)) {
333 return std::get<int>(var_result);
334 }
else if (std::holds_alternative<bool>(var_result)) {
335 return std::get<bool>(var_result);
337 eventExtraInfo->addExtraInfo(key, value);
343 B2FATAL(
"Wrong number of arguments for meta function eventCached");
349 if (arguments.size() == 1) {
352 auto func = [var, key](
const Particle * particle) ->
double {
354 if (particle->hasExtraInfo(key))
356 return particle->getExtraInfo(key);
359 double value = std::get<double>(var->function(particle));
367 const_cast<Particle*
>(particle)->addExtraInfo(key, value);
373 B2FATAL(
"Wrong number of arguments for meta function particleCached");
382 if (arguments.size() != 1) B2FATAL(
"Wrong number of arguments for meta function formula");
383 FormulaParser<VariableFormulaConstructor> parser;
385 return parser.parse(arguments[0]);
386 }
catch (std::runtime_error& e) {
393 if (arguments.size() <= 1) {
395 std::string cutString;
396 if (arguments.size() == 1)
397 cutString = arguments[0];
399 auto func = [cut](
const Particle*) ->
int {
401 int number_of_tracks = 0;
402 StoreArray<Track> tracks;
403 for (
const auto& track : tracks)
405 const TrackFitResult* trackFit = track.getTrackFitResultWithClosestMass(
Const::pion);
406 if (!trackFit)
continue;
407 if (trackFit->getChargeSign() == 0) {
411 if (cut->check(&particle))
416 return number_of_tracks;
421 B2FATAL(
"Wrong number of arguments for meta function nCleanedTracks");
427 if (arguments.size() <= 1) {
429 std::string cutString;
430 if (arguments.size() == 1)
431 cutString = arguments[0];
433 auto func = [cut](
const Particle*) ->
int {
435 int number_of_clusters = 0;
436 StoreArray<ECLCluster> clusters;
437 for (
const auto& cluster : clusters)
443 Particle particle(&cluster);
444 if (cut->check(&particle))
445 number_of_clusters++;
448 return number_of_clusters;
453 B2FATAL(
"Wrong number of arguments for meta function nCleanedECLClusters");
459 if (arguments.size() == 1) {
460 std::string cutString = arguments[0];
462 auto func = [cut](
const Particle * particle) ->
bool {
463 if (cut->check(particle))
470 B2FATAL(
"Wrong number of arguments for meta function passesCut");
476 if (arguments.size() == 1) {
477 std::string cutString = arguments[0];
479 auto func = [cut](
const Particle*) ->
bool {
480 if (cut->check(
nullptr))
487 B2FATAL(
"Wrong number of arguments for meta function passesEventCut");
493 if (arguments.size() == 2) {
497 }
catch (std::invalid_argument&) {
498 B2FATAL(
"The first argument of varFor meta function must be a positive integer!");
501 auto func = [pdgCode, var](
const Particle * particle) ->
double {
502 if (std::abs(particle->getPDGCode()) == std::abs(pdgCode))
504 auto var_result = var->function(particle);
505 if (std::holds_alternative<double>(var_result)) {
506 return std::get<double>(var_result);
507 }
else if (std::holds_alternative<int>(var_result)) {
508 return std::get<int>(var_result);
509 }
else if (std::holds_alternative<bool>(var_result)) {
510 return std::get<bool>(var_result);
516 B2FATAL(
"Wrong number of arguments for meta function varFor");
522 if (arguments.size() == 1) {
524 auto func = [var](
const Particle * particle) ->
double {
525 if (particle->getMCParticle())
530 auto var_result = var->function(particle);
531 if (std::holds_alternative<double>(var_result)) {
532 return std::get<double>(var_result);
533 }
else if (std::holds_alternative<int>(var_result)) {
534 return std::get<int>(var_result);
535 }
else if (std::holds_alternative<bool>(var_result)) {
536 return std::get<bool>(var_result);
543 B2FATAL(
"Wrong number of arguments for meta function varForMCGen");
549 if (arguments.size() == 1) {
550 std::string listName = arguments[0];
551 auto func = [listName](
const Particle * particle) ->
int {
554 StoreObjPtr<ParticleList> listOfParticles(listName);
556 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to nParticlesInList");
558 return listOfParticles->getListSize();
563 B2FATAL(
"Wrong number of arguments for meta function nParticlesInList");
570 if (arguments.size() != 1) {
571 B2FATAL(
"Wrong number of arguments for isInList");
573 auto listName = arguments[0];
575 auto func = [listName](
const Particle * particle) ->
bool {
578 StoreObjPtr<ParticleList> list(listName);
579 if (!(list.isValid()))
581 B2FATAL(
"Invalid Listname " << listName <<
" given to isInList");
585 return list->contains(particle);
594 if (arguments.size() != 1) {
595 B2FATAL(
"Wrong number of arguments for sourceObjectIsInList");
597 auto listName = arguments[0];
599 auto func = [listName](
const Particle * particle) ->
int {
602 StoreObjPtr<ParticleList> list(listName);
603 if (!(list.isValid()))
605 B2FATAL(
"Invalid Listname " << listName <<
" given to sourceObjectIsInList");
611 if (particlesource == Particle::EParticleSourceObject::c_Composite
612 or particlesource == Particle::EParticleSourceObject::c_Undefined)
618 for (
unsigned i = 0; i < list->getListSize(); ++i)
620 Particle* iparticle = list->getParticle(i);
621 if (particle->getMdstSource() == iparticle->getMdstSource())
633 if (arguments.size() != 1) {
634 B2FATAL(
"Wrong number of arguments for mcParticleIsInMCList");
636 auto listName = arguments[0];
638 auto func = [listName](
const Particle * particle) ->
bool {
641 StoreObjPtr<ParticleList> list(listName);
642 if (!(list.isValid()))
643 B2FATAL(
"Invalid Listname " << listName <<
" given to mcParticleIsInMCList");
646 const MCParticle* mcp = particle->getMCParticle();
647 if (mcp ==
nullptr)
return false;
650 for (
unsigned i = 0; i < list->getListSize(); ++i)
652 const MCParticle* imcp = list->getParticle(i)->getMCParticle();
653 if ((imcp !=
nullptr) and (mcp->getArrayIndex() == imcp->getArrayIndex()))
663 B2WARNING(
"isDaughterOfList is outdated and replaced by isDescendantOfList.");
664 std::vector<std::string> new_arguments = arguments;
665 new_arguments.push_back(std::string(
"1"));
666 return isDescendantOfList(new_arguments);
671 B2WARNING(
"isGrandDaughterOfList is outdated and replaced by isDescendantOfList.");
672 std::vector<std::string> new_arguments = arguments;
673 new_arguments.push_back(std::string(
"2"));
674 return isDescendantOfList(new_arguments);
679 if (arguments.size() > 0) {
680 auto listNames = arguments;
681 auto func = [listNames](
const Particle * particle) ->
bool {
683 int generation_flag = -1;
687 }
catch (std::exception& e) {}
689 for (
auto& iListName : listNames)
694 }
catch (std::exception& e) {}
697 auto list_comparison = [](
auto&& self,
const Particle * m,
const Particle * p,
int flag)->
bool {
699 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
701 const Particle* daughter = m->getDaughter(i);
702 if ((flag == 1.) or (flag < 0)) {
703 if (p->isCopyOf(daughter)) {
709 if (daughter->getNDaughters() > 0) {
710 result = self(self, daughter, p, flag - 1);
720 StoreObjPtr<ParticleList> listOfParticles(iListName);
722 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isDescendantOfList");
724 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
725 Particle* iParticle = listOfParticles->getParticle(i);
726 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
736 B2FATAL(
"Wrong number of arguments for meta function isDescendantOfList");
742 if (arguments.size() > 0) {
743 auto listNames = arguments;
744 auto func = [listNames](
const Particle * particle) ->
bool {
746 int generation_flag = -1;
750 }
catch (std::exception& e) {}
752 if (particle->getMCParticle() ==
nullptr)
757 for (
auto& iListName : listNames)
760 std::stod(iListName);
762 }
catch (std::exception& e) {}
764 auto list_comparison = [](
auto&& self,
const Particle * m,
const Particle * p,
int flag)->
bool {
766 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
768 const Particle* daughter = m->getDaughter(i);
769 if ((flag == 1.) or (flag < 0)) {
770 if (daughter->getMCParticle() !=
nullptr) {
771 if (p->getMCParticle()->getArrayIndex() == daughter->getMCParticle()->getArrayIndex()) {
777 if (daughter->getNDaughters() > 0) {
778 result = self(self, daughter, p, flag - 1);
788 StoreObjPtr<ParticleList> listOfParticles(iListName);
790 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isMCDescendantOfList");
792 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
793 Particle* iParticle = listOfParticles->getParticle(i);
794 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
804 B2FATAL(
"Wrong number of arguments for meta function isMCDescendantOfList");
810 if (arguments.size() == 1) {
812 auto func = [var](
const Particle * particle) ->
double {
813 double product = 1.0;
814 if (particle->getNDaughters() == 0)
818 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
820 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
821 product *= std::get<double>(var->function(particle->getDaughter(j)));
823 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
825 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
826 product *= std::get<int>(var->function(particle->getDaughter(j)));
833 B2FATAL(
"Wrong number of arguments for meta function daughterProductOf");
839 if (arguments.size() == 1) {
841 auto func = [var](
const Particle * particle) ->
double {
843 if (particle->getNDaughters() == 0)
847 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
849 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
850 sum += std::get<double>(var->function(particle->getDaughter(j)));
852 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
854 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
855 sum += std::get<int>(var->function(particle->getDaughter(j)));
862 B2FATAL(
"Wrong number of arguments for meta function daughterSumOf");
868 if (arguments.size() == 1) {
870 auto func = [var](
const Particle * particle) ->
double {
872 if (particle->getNDaughters() == 0)
876 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
878 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
879 double iValue = std::get<double>(var->function(particle->getDaughter(j)));
880 if (std::isnan(iValue))
continue;
881 if (std::isnan(min)) min = iValue;
882 if (iValue < min) min = iValue;
884 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
886 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
887 int iValue = std::get<int>(var->function(particle->getDaughter(j)));
888 if (std::isnan(min)) min = iValue;
889 if (iValue < min) min = iValue;
896 B2FATAL(
"Wrong number of arguments for meta function daughterLowest");
902 if (arguments.size() == 1) {
904 auto func = [var](
const Particle * particle) ->
double {
906 if (particle->getNDaughters() == 0)
910 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
912 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
913 double iValue = std::get<double>(var->function(particle->getDaughter(j)));
914 if (std::isnan(iValue))
continue;
915 if (std::isnan(max)) max = iValue;
916 if (iValue > max) max = iValue;
918 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
920 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
921 int iValue = std::get<int>(var->function(particle->getDaughter(j)));
922 if (std::isnan(max)) max = iValue;
923 if (iValue > max) max = iValue;
930 B2FATAL(
"Wrong number of arguments for meta function daughterHighest");
936 if (arguments.size() == 3) {
937 auto func = [arguments](
const Particle * particle) ->
double {
938 if (particle ==
nullptr)
940 const Particle* dau_i = particle->getParticleFromGeneralizedIndexString(arguments[0]);
941 const Particle* dau_j = particle->getParticleFromGeneralizedIndexString(arguments[1]);
942 auto variablename = arguments[2];
943 if (dau_i ==
nullptr || dau_j ==
nullptr)
945 B2ERROR(
"One of the first two arguments doesn't specify a valid (grand-)daughter!");
949 auto result_j = var->function(dau_j);
950 auto result_i = var->function(dau_i);
952 if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i))
954 diff = std::get<double>(result_j) - std::get<double>(result_i);
955 }
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i))
957 diff = std::get<int>(result_j) - std::get<int>(result_i);
960 throw std::runtime_error(
"Bad variant access");
962 if (variablename ==
"phi" or variablename ==
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))
963 or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)")))
965 if (fabs(diff) > M_PI) {
967 diff = diff - 2 * M_PI;
969 diff = 2 * M_PI + diff;
977 B2FATAL(
"Wrong number of arguments for meta function daughterDiffOf");
983 if (arguments.size() == 3) {
984 auto func = [arguments](
const Particle * particle) ->
double {
985 if (particle ==
nullptr)
987 const Particle* dau_i = particle->getParticleFromGeneralizedIndexString(arguments[0]);
988 const Particle* dau_j = particle->getParticleFromGeneralizedIndexString(arguments[1]);
989 auto variablename = arguments[2];
990 if (dau_i ==
nullptr || dau_j ==
nullptr)
992 B2ERROR(
"One of the first two arguments doesn't specify a valid (grand-)daughter!");
995 const MCParticle* iMcDaughter = dau_i->getMCParticle();
996 const MCParticle* jMcDaughter = dau_j->getMCParticle();
997 if (iMcDaughter ==
nullptr || jMcDaughter ==
nullptr)
999 Particle iTmpPart(iMcDaughter);
1000 Particle jTmpPart(jMcDaughter);
1002 auto result_j = var->function(&jTmpPart);
1003 auto result_i = var->function(&iTmpPart);
1005 if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i))
1007 diff = std::get<double>(result_j) - std::get<double>(result_i);
1008 }
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i))
1010 diff = std::get<int>(result_j) - std::get<int>(result_i);
1013 throw std::runtime_error(
"Bad variant access");
1015 if (variablename ==
"phi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)")))
1017 if (fabs(diff) > M_PI) {
1019 diff = diff - 2 * M_PI;
1021 diff = 2 * M_PI + diff;
1029 B2FATAL(
"Wrong number of arguments for meta function mcDaughterDiffOf");
1035 if (arguments.size() == 5) {
1041 }
catch (std::invalid_argument&) {
1042 B2FATAL(
"First four arguments of grandDaughterDiffOf meta function must be integers!");
1044 std::vector<std::string> new_arguments;
1045 new_arguments.push_back(std::string(arguments[0] +
":" + arguments[2]));
1046 new_arguments.push_back(std::string(arguments[1] +
":" + arguments[3]));
1047 new_arguments.push_back(arguments[4]);
1048 return daughterDiffOf(new_arguments);
1050 B2FATAL(
"Wrong number of arguments for meta function grandDaughterDiffOf");
1056 if (arguments.size() == 3) {
1057 auto func = [arguments](
const Particle * particle) ->
double {
1058 if (particle ==
nullptr)
1060 const Particle* dau_i = particle->getParticleFromGeneralizedIndexString(arguments[0]);
1061 const Particle* dau_j = particle->getParticleFromGeneralizedIndexString(arguments[1]);
1062 if (!(dau_i && dau_j))
1064 B2ERROR(
"One of the first two arguments doesn't specify a valid (grand-)daughter!");
1068 double iValue, jValue;
1069 if (std::holds_alternative<double>(var->function(dau_j)))
1071 iValue = std::get<double>(var->function(dau_i));
1072 jValue = std::get<double>(var->function(dau_j));
1073 }
else if (std::holds_alternative<int>(var->function(dau_j)))
1075 iValue = std::get<int>(var->function(dau_i));
1076 jValue = std::get<int>(var->function(dau_j));
1078 return (jValue - iValue) / (jValue + iValue);
1082 B2FATAL(
"Wrong number of arguments for meta function daughterNormDiffOf");
1088 if (arguments.size() == 2) {
1089 auto daughterFunction = convertToDaughterIndex({arguments[0]});
1090 std::string variableName = arguments[1];
1091 auto func = [daughterFunction, variableName](
const Particle * particle) ->
double {
1092 if (particle ==
nullptr)
1094 int daughterNumber = std::get<int>(daughterFunction(particle));
1095 if (daughterNumber >=
int(particle->getNDaughters()) or daughterNumber < 0)
1098 auto result_mother = var->function(particle);
1099 auto result_daughter = var->function(particle->getDaughter(daughterNumber));
1101 if (std::holds_alternative<double>(result_mother) && std::holds_alternative<double>(result_daughter))
1103 diff = std::get<double>(result_mother) - std::get<double>(result_daughter);
1104 }
else if (std::holds_alternative<int>(result_mother) && std::holds_alternative<int>(result_daughter))
1106 diff = std::get<int>(result_mother) - std::get<int>(result_daughter);
1109 throw std::runtime_error(
"Bad variant access");
1112 if (variableName ==
"phi" or variableName ==
"useCMSFrame(phi)")
1114 if (fabs(diff) > M_PI) {
1116 diff = diff - 2 * M_PI;
1118 diff = 2 * M_PI + diff;
1126 B2FATAL(
"Wrong number of arguments for meta function daughterMotherDiffOf");
1132 if (arguments.size() == 2) {
1133 auto daughterFunction = convertToDaughterIndex({arguments[0]});
1135 auto func = [var, daughterFunction](
const Particle * particle) ->
double {
1136 if (particle ==
nullptr)
1138 int daughterNumber = std::get<int>(daughterFunction(particle));
1139 if (daughterNumber >=
int(particle->getNDaughters()) or daughterNumber < 0)
1141 double daughterValue = 0.0, motherValue = 0.0;
1142 if (std::holds_alternative<double>(var->function(particle)))
1144 daughterValue = std::get<double>(var->function(particle->getDaughter(daughterNumber)));
1145 motherValue = std::get<double>(var->function(particle));
1146 }
else if (std::holds_alternative<int>(var->function(particle)))
1148 daughterValue = std::get<int>(var->function(particle->getDaughter(daughterNumber)));
1149 motherValue = std::get<int>(var->function(particle));
1151 return (motherValue - daughterValue) / (motherValue + daughterValue);
1155 B2FATAL(
"Wrong number of arguments for meta function daughterMotherNormDiffOf");
1161 if (arguments.size() >= 1) {
1163 auto func = [arguments](
const Particle * particle) ->
double {
1164 if (particle ==
nullptr)
1169 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
1170 for (
auto& generalizedIndex : arguments)
1172 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1173 if (dauPart) pSum += frame.getMomentum(dauPart);
1175 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
1181 ROOT::Math::PxPyPzEVector pIN = T.getBeamFourMomentum();
1182 ROOT::Math::PxPyPzEVector pRecoil = frame.getMomentum(pIN - particle->get4Vector());
1184 return ROOT::Math::VectorUtil::Angle(pRecoil, pSum);
1188 B2FATAL(
"Wrong number of arguments for meta function angleBetweenDaughterAndRecoil");
1192 Manager::FunctionPtr angleBetweenDaughterAndMissingMomentum(
const std::vector<std::string>& arguments)
1194 if (arguments.size() >= 1) {
1195 auto func = [arguments](
const Particle * particle) ->
double {
1196 if (particle ==
nullptr)
1199 StoreObjPtr<EventKinematics> evtShape;
1202 B2WARNING(
"Cannot find missing momentum information, did you forget to run EventKinematicsModule?");
1205 ROOT::Math::XYZVector missingMomentumCMS = evtShape->getMissingMomentumCMS();
1206 ROOT::Math::PxPyPzEVector missingTotalMomentumCMS(missingMomentumCMS.X(),
1207 missingMomentumCMS.Y(),
1208 missingMomentumCMS.Z(),
1209 evtShape->getMissingEnergyCMS());
1211 ROOT::Math::PxPyPzEVector missingTotalMomentumLab = T.rotateCmsToLab() * missingTotalMomentumCMS;
1214 ROOT::Math::PxPyPzEVector pMiss = frame.getMomentum(missingTotalMomentumLab);
1216 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
1217 for (
auto& generalizedIndex : arguments)
1219 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1220 if (dauPart) pSum += frame.getMomentum(dauPart);
1222 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
1227 return ROOT::Math::VectorUtil::Angle(pMiss, pSum);
1231 B2FATAL(
"Wrong number of arguments for meta function angleBetweenDaughterAndMissingMomentum");
1237 if (arguments.size() == 2 || arguments.size() == 3) {
1239 auto func = [arguments](
const Particle * particle) ->
double {
1240 if (particle ==
nullptr)
1243 std::vector<ROOT::Math::PxPyPzEVector> pDaus;
1247 for (
auto& generalizedIndex : arguments)
1249 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1251 pDaus.push_back(frame.getMomentum(dauPart));
1253 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
1259 if (pDaus.size() == 2)
1260 return ROOT::Math::VectorUtil::Angle(pDaus[0], pDaus[1]);
1262 return ROOT::Math::VectorUtil::Angle(pDaus[2], pDaus[0] + pDaus[1]);
1266 B2FATAL(
"Wrong number of arguments for meta function daughterAngle");
1270 double grandDaughterDecayAngle(
const Particle* particle,
const std::vector<double>& arguments)
1272 if (arguments.size() == 2) {
1277 int daughterIndex = std::lround(arguments[0]);
1278 if (daughterIndex >=
int(particle->getNDaughters()))
1280 const Particle* dau = particle->getDaughter(daughterIndex);
1282 int grandDaughterIndex = std::lround(arguments[1]);
1283 if (grandDaughterIndex >=
int(dau->getNDaughters()))
1286 ROOT::Math::XYZVector boost = dau->get4Vector().BoostToCM();
1288 ROOT::Math::PxPyPzEVector motherMomentum = - particle->get4Vector();
1289 motherMomentum = ROOT::Math::Boost(boost) * motherMomentum;
1291 ROOT::Math::PxPyPzEVector grandDaughterMomentum = dau->getDaughter(grandDaughterIndex)->get4Vector();
1292 grandDaughterMomentum = ROOT::Math::Boost(boost) * grandDaughterMomentum;
1294 return ROOT::Math::VectorUtil::Angle(motherMomentum, grandDaughterMomentum);
1297 B2FATAL(
"The variable grandDaughterDecayAngle needs exactly two integers as arguments!");
1303 if (arguments.size() == 2 || arguments.size() == 3) {
1305 auto func = [arguments](
const Particle * particle) ->
double {
1306 if (particle ==
nullptr)
1309 std::vector<ROOT::Math::PxPyPzEVector> pDaus;
1313 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_MCParticle)
1315 for (
auto& generalizedIndex : arguments) {
1316 const MCParticle* mcPart = particle->getMCParticle();
1317 if (mcPart ==
nullptr)
1319 const MCParticle* dauMcPart = mcPart->getParticleFromGeneralizedIndexString(generalizedIndex);
1320 if (dauMcPart ==
nullptr)
1323 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1327 for (
auto& generalizedIndex : arguments) {
1328 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1329 if (dauPart ==
nullptr)
1332 const MCParticle* dauMcPart = dauPart->getMCParticle();
1333 if (dauMcPart ==
nullptr)
1336 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1341 if (pDaus.size() == 2)
1342 return ROOT::Math::VectorUtil::Angle(pDaus[0], pDaus[1]);
1344 return ROOT::Math::VectorUtil::Angle(pDaus[2], pDaus[0] + pDaus[1]);
1348 B2FATAL(
"Wrong number of arguments for meta function mcDaughterAngle");
1352 double daughterClusterAngleInBetween(
const Particle* particle,
const std::vector<double>& daughterIndices)
1354 if (daughterIndices.size() == 2) {
1355 int daughterIndexi = std::lround(daughterIndices[0]);
1356 int daughterIndexj = std::lround(daughterIndices[1]);
1357 if (std::max(daughterIndexi, daughterIndexj) >=
int(particle->getNDaughters())) {
1360 const ECLCluster* clusteri = particle->getDaughter(daughterIndexi)->getECLCluster();
1361 const ECLCluster* clusterj = particle->getDaughter(daughterIndexj)->getECLCluster();
1362 if (clusteri and clusterj) {
1366 ClusterUtils clusutils;
1367 ROOT::Math::PxPyPzEVector pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit));
1368 ROOT::Math::PxPyPzEVector pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit));
1369 return ROOT::Math::VectorUtil::Angle(pi, pj);
1373 }
else if (daughterIndices.size() == 3) {
1374 int daughterIndexi = std::lround(daughterIndices[0]);
1375 int daughterIndexj = std::lround(daughterIndices[1]);
1376 int daughterIndexk = std::lround(daughterIndices[2]);
1377 if (std::max(std::max(daughterIndexi, daughterIndexj), daughterIndexk) >=
int(particle->getNDaughters())) {
1380 const ECLCluster* clusteri = (particle->getDaughter(daughterIndices[0]))->getECLCluster();
1381 const ECLCluster* clusterj = (particle->getDaughter(daughterIndices[1]))->getECLCluster();
1382 const ECLCluster* clusterk = (particle->getDaughter(daughterIndices[2]))->getECLCluster();
1383 if (clusteri and clusterj and clusterk) {
1388 ClusterUtils clusutils;
1389 ROOT::Math::PxPyPzEVector pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit));
1390 ROOT::Math::PxPyPzEVector pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit));
1391 ROOT::Math::PxPyPzEVector pk = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterk, clusterkBit));
1392 return ROOT::Math::VectorUtil::Angle(pk, pi + pj);
1397 B2FATAL(
"Wrong number of arguments for daughterClusterAngleInBetween!");
1403 if (arguments.size() > 1) {
1404 auto func = [arguments](
const Particle * particle) ->
double {
1406 ROOT::Math::PxPyPzEVector pSum;
1408 for (
auto& generalizedIndex : arguments)
1410 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1412 pSum += frame.getMomentum(dauPart);
1421 B2FATAL(
"Wrong number of arguments for meta function daughterInvM. At least two integers are needed.");
1427 if (arguments.size() == 2) {
1432 }
catch (std::invalid_argument&) {
1433 B2FATAL(
"Second argument of modulo meta function must be integer!");
1435 auto func = [var, divideBy](
const Particle * particle) ->
int {
1436 auto var_result = var->function(particle);
1437 if (std::holds_alternative<double>(var_result))
1439 return int(std::get<double>(var_result)) % divideBy;
1440 }
else if (std::holds_alternative<int>(var_result))
1442 return std::get<int>(var_result) % divideBy;
1443 }
else if (std::holds_alternative<bool>(var_result))
1445 return int(std::get<bool>(var_result)) % divideBy;
1450 B2FATAL(
"Wrong number of arguments for meta function modulo");
1456 if (arguments.size() == 1) {
1459 auto func = [var](
const Particle * particle) ->
bool {
return std::isnan(std::get<double>(var->function(particle))); };
1462 B2FATAL(
"Wrong number of arguments for meta function isNAN");
1468 if (arguments.size() == 2) {
1470 double defaultOutput;
1473 }
catch (std::invalid_argument&) {
1474 B2FATAL(
"The second argument of ifNANgiveX meta function must be a number!");
1476 auto func = [var, defaultOutput](
const Particle * particle) ->
double {
1477 double output = std::get<double>(var->function(particle));
1478 if (std::isnan(output))
return defaultOutput;
1483 B2FATAL(
"Wrong number of arguments for meta function ifNANgiveX");
1489 if (arguments.size() == 1) {
1492 auto func = [var](
const Particle * particle) ->
bool {
return std::isinf(std::get<double>(var->function(particle))); };
1495 B2FATAL(
"Wrong number of arguments for meta function isInfinity");
1501 if (arguments.size() >= 2) {
1507 for (
size_t i = 1; i < arguments.size(); ++i) {
1510 }
catch (std::invalid_argument&) {
1511 B2FATAL(
"The input flags to meta function unmask() should be integer!");
1517 auto func = [var, finalMask](
const Particle * particle) ->
double {
1519 auto var_result = var->function(particle);
1520 if (std::holds_alternative<double>(var_result))
1523 if (std::isnan(std::get<double>(var_result))) {
1526 value = int(std::get<double>(var_result));
1527 }
else if (std::holds_alternative<int>(var_result))
1529 value = std::get<int>(var_result);
1533 value &= (~finalMask);
1540 B2FATAL(
"Meta function unmask needs at least two arguments!");
1546 if (arguments.size() == 3) {
1548 std::string cutString = arguments[0];
1554 auto func = [cut, variableIfTrue, variableIfFalse](
const Particle * particle) ->
double {
1555 if (particle ==
nullptr)
1557 if (cut->check(particle))
1559 auto var_result = variableIfTrue->function(particle);
1560 if (std::holds_alternative<double>(var_result)) {
1561 return std::get<double>(var_result);
1562 }
else if (std::holds_alternative<int>(var_result)) {
1563 return std::get<int>(var_result);
1564 }
else if (std::holds_alternative<bool>(var_result)) {
1565 return std::get<bool>(var_result);
1569 auto var_result = variableIfFalse->function(particle);
1570 if (std::holds_alternative<double>(var_result)) {
1571 return std::get<double>(var_result);
1572 }
else if (std::holds_alternative<int>(var_result)) {
1573 return std::get<int>(var_result);
1574 }
else if (std::holds_alternative<bool>(var_result)) {
1575 return std::get<bool>(var_result);
1582 B2FATAL(
"Wrong number of arguments for meta function conditionalVariableSelector");
1588 if (arguments.size() > 0) {
1589 std::vector<const Variable::Manager::Var*> variables;
1590 for (
auto& argument : arguments)
1593 auto func = [variables, arguments](
const Particle * particle) ->
double {
1594 double pValueProduct = 1.;
1595 for (
auto variable : variables)
1597 double pValue = std::get<double>(variable->function(particle));
1601 pValueProduct *= pValue;
1603 double pValueSum = 1.;
1604 double factorial = 1.;
1605 for (
unsigned int i = 1; i < arguments.size(); ++i)
1608 pValueSum += pow(-std::log(pValueProduct), i) / factorial;
1610 return pValueProduct * pValueSum;
1614 B2FATAL(
"Wrong number of arguments for meta function pValueCombination");
1620 if (arguments.size() == 1) {
1622 auto func = [var](
const Particle * particle) ->
double {
1623 double pValueProduct = 1.;
1624 if (particle->getNDaughters() == 0)
1629 for (
unsigned j = 0; j < particle->getNDaughters(); ++j)
1631 double pValue = std::get<double>(var->function(particle->getDaughter(j)));
1632 if (pValue < 0)
return -1;
1633 else pValueProduct *= pValue;
1636 double pValueSum = 1.;
1637 double factorial = 1.;
1638 for (
unsigned int i = 1; i < particle->getNDaughters(); ++i)
1641 pValueSum += pow(-std::log(pValueProduct), i) / factorial;
1643 return pValueProduct * pValueSum;
1647 B2FATAL(
"Wrong number of arguments for meta function pValueCombinationOfDaughters");
1653 if (arguments.size() == 1) {
1655 auto func = [var](
const Particle * particle) ->
double {
1656 auto var_result = var->function(particle);
1657 if (std::holds_alternative<double>(var_result))
1659 return std::abs(std::get<double>(var_result));
1660 }
else if (std::holds_alternative<int>(var_result))
1662 return std::abs(std::get<int>(var_result));
1667 B2FATAL(
"Wrong number of arguments for meta function abs");
1673 if (arguments.size() == 2) {
1678 B2FATAL(
"One or both of the used variables doesn't exist!");
1680 auto func = [var1, var2](
const Particle * particle) ->
double {
1682 auto var_result1 = var1->function(particle);
1683 auto var_result2 = var2->function(particle);
1684 if (std::holds_alternative<double>(var_result1))
1686 val1 = std::get<double>(var_result1);
1687 }
else if (std::holds_alternative<int>(var_result1))
1689 val1 = std::get<int>(var_result1);
1690 }
else if (std::holds_alternative<bool>(var_result1))
1692 val1 = std::get<bool>(var_result1);
1695 B2FATAL(
"A variable in meta function max holds no double, int or bool values");
1697 if (std::holds_alternative<double>(var_result2))
1699 val2 = std::get<double>(var_result2);
1700 }
else if (std::holds_alternative<int>(var_result2))
1702 val2 = std::get<int>(var_result2);
1703 }
else if (std::holds_alternative<bool>(var_result2))
1705 val2 = std::get<bool>(var_result2);
1708 B2FATAL(
"A variable in meta function max holds no double, int or bool values");
1710 return std::max(val1, val2);
1714 B2FATAL(
"Wrong number of arguments for meta function max");
1720 if (arguments.size() == 2) {
1725 B2FATAL(
"One or both of the used variables doesn't exist!");
1727 auto func = [var1, var2](
const Particle * particle) ->
double {
1729 auto var_result1 = var1->function(particle);
1730 auto var_result2 = var2->function(particle);
1731 if (std::holds_alternative<double>(var_result1))
1733 val1 = std::get<double>(var_result1);
1734 }
else if (std::holds_alternative<int>(var_result1))
1736 val1 = std::get<int>(var_result1);
1737 }
else if (std::holds_alternative<bool>(var_result1))
1739 val1 = std::get<bool>(var_result1);
1742 B2FATAL(
"A variable in meta function min holds no double, int or bool values");
1744 if (std::holds_alternative<double>(var_result2))
1746 val2 = std::get<double>(var_result2);
1747 }
else if (std::holds_alternative<int>(var_result2))
1749 val2 = std::get<int>(var_result2);
1750 }
else if (std::holds_alternative<bool>(var_result2))
1752 val2 = std::get<bool>(var_result2);
1755 B2FATAL(
"A variable in meta function min holds no double, int or bool values");
1757 return std::min(val1, val2);
1761 B2FATAL(
"Wrong number of arguments for meta function min");
1767 if (arguments.size() == 1) {
1769 auto func = [var](
const Particle * particle) ->
double {
1770 auto var_result = var->function(particle);
1771 if (std::holds_alternative<double>(var_result))
1772 return std::sin(std::get<double>(var_result));
1773 else if (std::holds_alternative<int>(var_result))
1774 return std::sin(std::get<int>(var_result));
1779 B2FATAL(
"Wrong number of arguments for meta function sin");
1785 if (arguments.size() == 1) {
1787 auto func = [var](
const Particle * particle) ->
double {
1788 auto var_result = var->function(particle);
1789 if (std::holds_alternative<double>(var_result))
1790 return std::asin(std::get<double>(var_result));
1791 else if (std::holds_alternative<int>(var_result))
1792 return std::asin(std::get<int>(var_result));
1797 B2FATAL(
"Wrong number of arguments for meta function asin");
1803 if (arguments.size() == 1) {
1805 auto func = [var](
const Particle * particle) ->
double {
1806 auto var_result = var->function(particle);
1807 if (std::holds_alternative<double>(var_result))
1808 return std::cos(std::get<double>(var_result));
1809 else if (std::holds_alternative<int>(var_result))
1810 return std::cos(std::get<int>(var_result));
1815 B2FATAL(
"Wrong number of arguments for meta function cos");
1821 if (arguments.size() == 1) {
1823 auto func = [var](
const Particle * particle) ->
double {
1824 auto var_result = var->function(particle);
1825 if (std::holds_alternative<double>(var_result))
1826 return std::acos(std::get<double>(var_result));
1827 else if (std::holds_alternative<int>(var_result))
1828 return std::acos(std::get<int>(var_result));
1833 B2FATAL(
"Wrong number of arguments for meta function acos");
1839 if (arguments.size() == 1) {
1841 auto func = [var](
const Particle * particle) ->
double {
return std::tan(std::get<double>(var->function(particle))); };
1844 B2FATAL(
"Wrong number of arguments for meta function tan");
1850 if (arguments.size() == 1) {
1852 auto func = [var](
const Particle * particle) ->
double {
return std::atan(std::get<double>(var->function(particle))); };
1855 B2FATAL(
"Wrong number of arguments for meta function atan");
1861 if (arguments.size() == 1) {
1863 auto func = [var](
const Particle * particle) ->
double {
1864 auto var_result = var->function(particle);
1865 if (std::holds_alternative<double>(var_result))
1866 return std::exp(std::get<double>(var_result));
1867 else if (std::holds_alternative<int>(var_result))
1868 return std::exp(std::get<int>(var_result));
1873 B2FATAL(
"Wrong number of arguments for meta function exp");
1879 if (arguments.size() == 1) {
1881 auto func = [var](
const Particle * particle) ->
double {
1882 auto var_result = var->function(particle);
1883 if (std::holds_alternative<double>(var_result))
1884 return std::log(std::get<double>(var_result));
1885 else if (std::holds_alternative<int>(var_result))
1886 return std::log(std::get<int>(var_result));
1891 B2FATAL(
"Wrong number of arguments for meta function log");
1897 if (arguments.size() == 1) {
1899 auto func = [var](
const Particle * particle) ->
double {
1900 auto var_result = var->function(particle);
1901 if (std::holds_alternative<double>(var_result))
1902 return std::log10(std::get<double>(var_result));
1903 else if (std::holds_alternative<int>(var_result))
1904 return std::log10(std::get<int>(var_result));
1909 B2FATAL(
"Wrong number of arguments for meta function log10");
1915 if (arguments.size() == 1) {
1917 auto func = [var](
const Particle * particle) ->
double {
1918 if (particle ==
nullptr)
1921 StoreArray<Particle> particles;
1922 if (!particle->hasExtraInfo(
"original_index"))
1925 auto originalParticle = particles[particle->getExtraInfo(
"original_index")];
1926 if (!originalParticle)
1928 auto var_result = var->function(originalParticle);
1929 if (std::holds_alternative<double>(var_result))
1931 return std::get<double>(var_result);
1932 }
else if (std::holds_alternative<int>(var_result))
1934 return std::get<int>(var_result);
1935 }
else if (std::holds_alternative<bool>(var_result))
1937 return std::get<bool>(var_result);
1942 B2FATAL(
"Wrong number of arguments for meta function originalParticle");
1948 if (arguments.size() == 2) {
1949 auto daughterFunction = convertToDaughterIndex({arguments[0]});
1951 auto func = [var, daughterFunction](
const Particle * particle) ->
double {
1952 if (particle ==
nullptr)
1954 int daughterNumber = std::get<int>(daughterFunction(particle));
1955 if (daughterNumber >=
int(particle->getNDaughters()) or daughterNumber < 0)
1957 auto var_result = var->function(particle->getDaughter(daughterNumber));
1958 if (std::holds_alternative<double>(var_result))
1960 return std::get<double>(var_result);
1961 }
else if (std::holds_alternative<int>(var_result))
1963 return std::get<int>(var_result);
1964 }
else if (std::holds_alternative<bool>(var_result))
1966 return std::get<bool>(var_result);
1971 B2FATAL(
"Wrong number of arguments for meta function daughter");
1977 if (arguments.size() == 2) {
1978 auto daughterFunction = convertToDaughterIndex({arguments[0]});
1980 auto func = [var, daughterFunction](
const Particle * particle) ->
double {
1981 if (particle ==
nullptr)
1983 int daughterNumber = std::get<int>(daughterFunction(particle));
1984 if (daughterNumber >=
int(particle->getNDaughters()) or daughterNumber < 0)
1988 StoreArray<Particle> particles;
1989 if (!particle->getDaughter(daughterNumber)->hasExtraInfo(
"original_index"))
1991 auto originalDaughter = particles[particle->getDaughter(daughterNumber)->getExtraInfo(
"original_index")];
1992 if (!originalDaughter)
1995 auto var_result = var->function(originalDaughter);
1996 if (std::holds_alternative<double>(var_result)) {
1997 return std::get<double>(var_result);
1998 }
else if (std::holds_alternative<int>(var_result)) {
1999 return std::get<int>(var_result);
2000 }
else if (std::holds_alternative<bool>(var_result)) {
2001 return std::get<bool>(var_result);
2007 B2FATAL(
"Wrong number of arguments for meta function daughter");
2013 if (arguments.size() == 1) {
2014 std::string daughterString = arguments[0];
2015 auto func = [daughterString](
const Particle * particle) ->
int {
2016 if (particle ==
nullptr)
2018 int daughterNumber = 0;
2022 }
catch (std::invalid_argument&)
2024 auto daughterFunction = convertToInt({daughterString,
"-1"});
2025 auto daughterVarResult = daughterFunction(particle);
2026 daughterNumber = std::get<int>(daughterVarResult);
2028 return daughterNumber;
2032 B2FATAL(
"Wrong number of arguments for meta function convertToDaughterIndex");
2038 if (arguments.size() == 2) {
2039 auto daughterFunction = convertToDaughterIndex({arguments[0]});
2041 auto func = [var, daughterFunction](
const Particle * particle) ->
double {
2042 if (particle ==
nullptr)
2044 if (particle->getMCParticle())
2046 int daughterNumber = std::get<int>(daughterFunction(particle));
2047 if (daughterNumber >=
int(particle->getMCParticle()->getNDaughters()) or daughterNumber < 0)
2049 Particle tempParticle = Particle(particle->getMCParticle()->getDaughters().at(daughterNumber));
2050 auto var_result = var->function(&tempParticle);
2051 if (std::holds_alternative<double>(var_result)) {
2052 return std::get<double>(var_result);
2053 }
else if (std::holds_alternative<int>(var_result)) {
2054 return std::get<int>(var_result);
2055 }
else if (std::holds_alternative<bool>(var_result)) {
2056 return std::get<bool>(var_result);
2067 B2FATAL(
"Wrong number of arguments for meta function mcDaughter");
2073 if (arguments.size() == 1) {
2075 auto func = [var](
const Particle * particle) ->
double {
2076 if (particle ==
nullptr)
2078 if (particle->getMCParticle())
2080 if (particle->getMCParticle()->getMother() ==
nullptr) {
2083 Particle tempParticle = Particle(particle->getMCParticle()->getMother());
2084 auto var_result = var->function(&tempParticle);
2085 if (std::holds_alternative<double>(var_result)) {
2086 return std::get<double>(var_result);
2087 }
else if (std::holds_alternative<int>(var_result)) {
2088 return std::get<int>(var_result);
2089 }
else if (std::holds_alternative<bool>(var_result)) {
2090 return std::get<bool>(var_result);
2099 B2FATAL(
"Wrong number of arguments for meta function mcMother");
2105 if (arguments.size() == 2) {
2106 int particleNumber = 0;
2109 }
catch (std::invalid_argument&) {
2110 B2FATAL(
"First argument of genParticle meta function must be integer!");
2114 auto func = [var, particleNumber](
const Particle*) ->
double {
2115 StoreArray<MCParticle> mcParticles(
"MCParticles");
2116 if (particleNumber >= mcParticles.getEntries())
2121 MCParticle* mcParticle = mcParticles[particleNumber];
2122 Particle part = Particle(mcParticle);
2123 auto var_result = var->function(&part);
2124 if (std::holds_alternative<double>(var_result))
2126 return std::get<double>(var_result);
2127 }
else if (std::holds_alternative<int>(var_result))
2129 return std::get<int>(var_result);
2130 }
else if (std::holds_alternative<bool>(var_result))
2132 return std::get<bool>(var_result);
2137 B2FATAL(
"Wrong number of arguments for meta function genParticle");
2143 if (arguments.size() == 1) {
2146 auto func = [var](
const Particle*) ->
double {
2147 StoreArray<MCParticle> mcParticles(
"MCParticles");
2148 if (mcParticles.getEntries() == 0)
2153 MCParticle* mcUpsilon4S = mcParticles[0];
2154 if (mcUpsilon4S->isInitial()) mcUpsilon4S = mcParticles[2];
2155 if (mcUpsilon4S->getPDG() != 300553)
2160 Particle upsilon4S = Particle(mcUpsilon4S);
2161 auto var_result = var->function(&upsilon4S);
2162 if (std::holds_alternative<double>(var_result))
2164 return std::get<double>(var_result);
2165 }
else if (std::holds_alternative<int>(var_result))
2167 return std::get<int>(var_result);
2168 }
else if (std::holds_alternative<bool>(var_result))
2170 return std::get<bool>(var_result);
2175 B2FATAL(
"Wrong number of arguments for meta function genUpsilon4S");
2181 if (arguments.size() == 4) {
2182 std::string listName = arguments[0];
2183 std::string rankedVariableName = arguments[1];
2184 std::string returnVariableName = arguments[2];
2185 std::string extraInfoName = rankedVariableName +
"_rank";
2189 }
catch (std::invalid_argument&) {
2190 B2ERROR(
"3rd argument of getVariableByRank meta function (Rank) must be an integer!");
2195 auto func = [var, rank, extraInfoName, listName](
const Particle*)->
double {
2196 StoreObjPtr<ParticleList> list(listName);
2198 const unsigned int numParticles = list->getListSize();
2199 for (
unsigned int i = 0; i < numParticles; i++)
2201 const Particle* p = list->getParticle(i);
2202 if (p->getExtraInfo(extraInfoName) == rank) {
2203 auto var_result = var->function(p);
2204 if (std::holds_alternative<double>(var_result)) {
2205 return std::get<double>(var_result);
2206 }
else if (std::holds_alternative<int>(var_result)) {
2207 return std::get<int>(var_result);
2208 }
else if (std::holds_alternative<bool>(var_result)) {
2209 return std::get<bool>(var_result);
2214 return std::numeric_limits<double>::signaling_NaN();
2218 B2FATAL(
"Wrong number of arguments for meta function getVariableByRank");
2224 if (arguments.size() == 1 or arguments.size() == 2) {
2226 std::string listName = arguments[0];
2227 std::string cutString =
"";
2229 if (arguments.size() == 2) {
2230 cutString = arguments[1];
2235 auto func = [listName, cut](
const Particle*) ->
int {
2237 StoreObjPtr<ParticleList> list(listName);
2239 for (
unsigned int i = 0; i < list->getListSize(); i++)
2241 const Particle* particle = list->getParticle(i);
2242 if (cut->check(particle)) {
2250 B2FATAL(
"Wrong number of arguments for meta function countInList");
2256 if (arguments.size() == 2 or arguments.size() == 3) {
2258 std::string roeListName = arguments[0];
2259 std::string cutString = arguments[1];
2261 if (arguments.size() == 2) {
2262 B2INFO(
"Use pdgCode of electron as default in meta variable veto, other arguments: " << roeListName <<
", " << cutString);
2266 }
catch (std::invalid_argument&) {
2267 B2FATAL(
"Third argument of veto meta function must be integer!");
2274 auto func = [roeListName, cut, pdgCode, flavourType](
const Particle * particle) ->
bool {
2275 StoreObjPtr<ParticleList> roeList(roeListName);
2276 ROOT::Math::PxPyPzEVector vec = particle->get4Vector();
2277 for (
unsigned int i = 0; i < roeList->getListSize(); i++)
2279 const Particle* roeParticle = roeList->getParticle(i);
2280 if (not particle->overlapsWith(roeParticle)) {
2281 ROOT::Math::PxPyPzEVector tempCombination = roeParticle->get4Vector() + vec;
2282 std::vector<int> indices = { particle->getArrayIndex(), roeParticle->getArrayIndex() };
2283 Particle tempParticle = Particle(tempCombination, pdgCode, flavourType, indices, particle->getArrayPointer());
2284 if (cut->check(&tempParticle)) {
2293 B2FATAL(
"Wrong number of arguments for meta function veto");
2299 if (arguments.size() == 1) {
2300 std::string cutString = arguments[0];
2302 auto func = [cut](
const Particle * particle) ->
int {
2304 for (
auto& daughter : particle->getDaughters())
2306 if (cut->check(daughter))
2313 B2FATAL(
"Wrong number of arguments for meta function countDaughters");
2319 if (arguments.size() == 1) {
2320 std::string cutString = arguments[0];
2322 auto func = [cut](
const Particle * particle) ->
int {
2324 std::vector<const Particle*> fspDaughters;
2325 particle->fillFSPDaughters(fspDaughters);
2328 for (
auto& daughter : fspDaughters)
2330 if (cut->check(daughter))
2337 B2FATAL(
"Wrong number of arguments for meta function countFSPDaughters");
2343 if (arguments.size() == 1) {
2344 std::string cutString = arguments[0];
2346 auto func = [cut](
const Particle * particle) ->
int {
2348 std::vector<const Particle*> allDaughters;
2349 particle->fillAllDaughters(allDaughters);
2352 for (
auto& daughter : allDaughters)
2354 if (cut->check(daughter))
2361 B2FATAL(
"Wrong number of arguments for meta function countDescendants");
2365 Manager::FunctionPtr numberOfNonOverlappingParticles(
const std::vector<std::string>& arguments)
2368 auto func = [arguments](
const Particle * particle) ->
int {
2370 int _numberOfNonOverlappingParticles = 0;
2371 for (
const auto& listName : arguments)
2373 StoreObjPtr<ParticleList> list(listName);
2374 if (not list.isValid()) {
2375 B2FATAL(
"Invalid list named " << listName <<
" encountered in numberOfNonOverlappingParticles.");
2377 for (
unsigned int i = 0; i < list->getListSize(); i++) {
2378 const Particle* p = list->getParticle(i);
2379 if (not particle->overlapsWith(p)) {
2380 _numberOfNonOverlappingParticles++;
2384 return _numberOfNonOverlappingParticles;
2391 void appendDaughtersRecursive(Particle* mother, StoreArray<Particle>& container)
2394 auto* mcmother = mother->getRelated<MCParticle>();
2399 for (
auto* mcdaughter : mcmother->getDaughters()) {
2401 Particle tmp_daughter(mcdaughter);
2402 Particle* new_daughter = container.appendNew(tmp_daughter);
2403 new_daughter->addRelationTo(mcdaughter);
2404 mother->appendDaughter(new_daughter,
false);
2406 if (mcdaughter->getNDaughters() > 0)
2407 appendDaughtersRecursive(new_daughter, container);
2413 if (arguments.size() == 1) {
2415 auto func = [var](
const Particle * particle) ->
double {
2416 const MCParticle* mcp = particle->getMCParticle();
2421 StoreArray<Particle> tempParticles(
"tempParticles");
2422 tempParticles.clear();
2423 Particle tmpPart(mcp);
2424 Particle* newPart = tempParticles.appendNew(tmpPart);
2425 newPart->addRelationTo(mcp);
2427 appendDaughtersRecursive(newPart, tempParticles);
2429 auto var_result = var->function(newPart);
2430 if (std::holds_alternative<double>(var_result))
2432 return std::get<double>(var_result);
2433 }
else if (std::holds_alternative<int>(var_result))
2435 return std::get<int>(var_result);
2436 }
else if (std::holds_alternative<bool>(var_result))
2438 return std::get<bool>(var_result);
2443 B2FATAL(
"Wrong number of arguments for meta function matchedMC");
2449 if (arguments.size() == 1) {
2452 auto func = [var](
const Particle * particle) ->
double {
2454 const ECLCluster* cluster = particle->getECLCluster();
2457 auto mcps = cluster->getRelationsTo<MCParticle>();
2460 std::vector<std::pair<double, int>> weightsAndIndices;
2461 for (
unsigned int i = 0; i < mcps.size(); ++i)
2462 weightsAndIndices.emplace_back(mcps.weight(i), i);
2465 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
2466 ValueIndexPairSorting::higherPair<
decltype(weightsAndIndices)::value_type>);
2469 const MCParticle* mcp = mcps.object(weightsAndIndices[0].second);
2471 StoreArray<Particle> tempParticles(
"tempParticles");
2472 tempParticles.clear();
2473 Particle tmpPart(mcp);
2474 Particle* newPart = tempParticles.appendNew(tmpPart);
2475 newPart->addRelationTo(mcp);
2477 appendDaughtersRecursive(newPart, tempParticles);
2479 auto var_result = var->function(newPart);
2480 if (std::holds_alternative<double>(var_result))
2482 return std::get<double>(var_result);
2483 }
else if (std::holds_alternative<int>(var_result))
2485 return std::get<int>(var_result);
2486 }
else if (std::holds_alternative<bool>(var_result))
2488 return std::get<bool>(var_result);
2497 B2FATAL(
"Wrong number of arguments for meta function clusterBestMatchedMCParticle");
2503 if (arguments.size() == 1) {
2506 auto func = [var](
const Particle * particle) ->
double {
2508 const ECLCluster* cluster = particle->getECLCluster();
2511 auto mcps = cluster->getRelationsTo<MCParticle>();
2514 std::map<int, double> mapMCParticleIndxAndWeight;
2515 getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
2518 if (mapMCParticleIndxAndWeight.size() == 0)
2522 auto maxMap = std::max_element(mapMCParticleIndxAndWeight.begin(), mapMCParticleIndxAndWeight.end(),
2523 [](
const auto & x,
const auto & y) { return x.second < y.second; }
2526 StoreArray<MCParticle> mcparticles;
2527 const MCParticle* mcKlong = mcparticles[maxMap->first];
2529 Particle tmpPart(mcKlong);
2530 auto var_result = var->function(&tmpPart);
2531 if (std::holds_alternative<double>(var_result))
2533 return std::get<double>(var_result);
2534 }
else if (std::holds_alternative<int>(var_result))
2536 return std::get<int>(var_result);
2537 }
else if (std::holds_alternative<bool>(var_result))
2539 return std::get<bool>(var_result);
2548 B2FATAL(
"Wrong number of arguments for meta function clusterBestMatchedMCKlong");
2552 double matchedMCHasPDG(
const Particle* particle,
const std::vector<double>& pdgCode)
2554 if (pdgCode.size() != 1) {
2555 B2FATAL(
"Too many arguments provided to matchedMCHasPDG!");
2557 int inputPDG = std::lround(pdgCode[0]);
2559 const MCParticle* mcp = particle->getMCParticle();
2563 return std::abs(mcp->getPDG()) == inputPDG;
2568 if (arguments.size() == 1) {
2569 std::string listName = arguments[0];
2570 auto func = [listName](
const Particle * particle) ->
double {
2573 StoreObjPtr<ParticleList> listOfParticles(listName);
2575 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2576 double totalEnergy = 0;
2577 int nParticles = listOfParticles->getListSize();
2578 for (
int i = 0; i < nParticles; i++)
2580 const Particle* part = listOfParticles->getParticle(i);
2582 totalEnergy += frame.getMomentum(part).E();
2589 B2FATAL(
"Wrong number of arguments for meta function totalEnergyOfParticlesInList");
2595 if (arguments.size() == 1) {
2596 std::string listName = arguments[0];
2597 auto func = [listName](
const Particle*) ->
double {
2598 StoreObjPtr<ParticleList> listOfParticles(listName);
2600 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPxOfParticlesInList");
2602 int nParticles = listOfParticles->getListSize();
2604 for (
int i = 0; i < nParticles; i++)
2606 const Particle* part = listOfParticles->getParticle(i);
2607 totalPx += frame.getMomentum(part).Px();
2613 B2FATAL(
"Wrong number of arguments for meta function totalPxOfParticlesInList");
2619 if (arguments.size() == 1) {
2620 std::string listName = arguments[0];
2621 auto func = [listName](
const Particle*) ->
double {
2622 StoreObjPtr<ParticleList> listOfParticles(listName);
2624 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPyOfParticlesInList");
2626 int nParticles = listOfParticles->getListSize();
2628 for (
int i = 0; i < nParticles; i++)
2630 const Particle* part = listOfParticles->getParticle(i);
2631 totalPy += frame.getMomentum(part).Py();
2637 B2FATAL(
"Wrong number of arguments for meta function totalPyOfParticlesInList");
2643 if (arguments.size() == 1) {
2644 std::string listName = arguments[0];
2645 auto func = [listName](
const Particle*) ->
double {
2646 StoreObjPtr<ParticleList> listOfParticles(listName);
2648 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPzOfParticlesInList");
2650 int nParticles = listOfParticles->getListSize();
2652 for (
int i = 0; i < nParticles; i++)
2654 const Particle* part = listOfParticles->getParticle(i);
2655 totalPz += frame.getMomentum(part).Pz();
2661 B2FATAL(
"Wrong number of arguments for meta function totalPzOfParticlesInList");
2667 if (arguments.size() > 0) {
2669 auto func = [arguments](
const Particle * particle) ->
double {
2671 ROOT::Math::PxPyPzEVector total4Vector;
2673 std::vector<Particle*> particlePool;
2676 for (
const auto& argument : arguments)
2678 StoreObjPtr <ParticleList> listOfParticles(argument);
2680 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << argument <<
" given to invMassInLists");
2681 int nParticles = listOfParticles->getListSize();
2682 for (
int i = 0; i < nParticles; i++) {
2683 bool overlaps =
false;
2684 Particle* part = listOfParticles->getParticle(i);
2685 for (
auto poolPart : particlePool) {
2686 if (part->overlapsWith(poolPart)) {
2692 total4Vector += part->get4Vector();
2693 particlePool.push_back(part);
2697 double invariantMass = total4Vector.M();
2698 return invariantMass;
2703 B2FATAL(
"Wrong number of arguments for meta function invMassInLists");
2707 Manager::FunctionPtr totalECLEnergyOfParticlesInList(
const std::vector<std::string>& arguments)
2709 if (arguments.size() == 1) {
2710 std::string listName = arguments[0];
2711 auto func = [listName](
const Particle * particle) ->
double {
2714 StoreObjPtr<ParticleList> listOfParticles(listName);
2716 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2717 double totalEnergy = 0;
2718 int nParticles = listOfParticles->getListSize();
2719 for (
int i = 0; i < nParticles; i++)
2721 const Particle* part = listOfParticles->getParticle(i);
2722 const ECLCluster* cluster = part->getECLCluster();
2724 if (cluster !=
nullptr) {
2725 totalEnergy += cluster->getEnergy(clusterHypothesis);
2733 B2FATAL(
"Wrong number of arguments for meta function totalECLEnergyOfParticlesInList");
2739 if (arguments.size() == 1) {
2740 std::string listName = arguments[0];
2741 auto func = [listName](
const Particle*) ->
double {
2742 StoreObjPtr<ParticleList> listOfParticles(listName);
2744 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxPtInList");
2745 int nParticles = listOfParticles->getListSize();
2748 for (
int i = 0; i < nParticles; i++)
2750 const Particle* part = listOfParticles->getParticle(i);
2751 const double Pt = frame.getMomentum(part).Pt();
2752 if (Pt > maxPt) maxPt = Pt;
2758 B2FATAL(
"Wrong number of arguments for meta function maxPtInList");
2762 Manager::FunctionPtr eclClusterTrackMatchedWithCondition(
const std::vector<std::string>& arguments)
2764 if (arguments.size() <= 1) {
2766 std::string cutString;
2767 if (arguments.size() == 1)
2768 cutString = arguments[0];
2770 auto func = [cut](
const Particle * particle) ->
double {
2772 if (particle ==
nullptr)
2775 const ECLCluster* cluster = particle->getECLCluster();
2779 auto tracks = cluster->getRelationsFrom<Track>();
2781 for (
const auto& track : tracks) {
2784 if (cut->check(&trackParticle))
2793 B2FATAL(
"Wrong number of arguments for meta function eclClusterSpecialTrackMatched");
2799 if (arguments.size() == 2) {
2800 std::string listName = arguments[0];
2803 auto func = [listName, var](
const Particle*) ->
double {
2804 StoreObjPtr<ParticleList> listOfParticles(listName);
2806 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to averageValueInList");
2807 int nParticles = listOfParticles->getListSize();
2808 if (nParticles == 0)
2813 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2815 for (
int i = 0; i < nParticles; i++) {
2816 average += std::get<double>(var->function(listOfParticles->getParticle(i))) / nParticles;
2818 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2820 for (
int i = 0; i < nParticles; i++) {
2821 average += std::get<int>(var->function(listOfParticles->getParticle(i))) / nParticles;
2828 B2FATAL(
"Wrong number of arguments for meta function averageValueInList");
2834 if (arguments.size() == 2) {
2835 std::string listName = arguments[0];
2838 auto func = [listName, var](
const Particle*) ->
double {
2839 StoreObjPtr<ParticleList> listOfParticles(listName);
2841 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to medianValueInList");
2842 int nParticles = listOfParticles->getListSize();
2843 if (nParticles == 0)
2847 std::vector<double> valuesInList;
2848 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2850 for (
int i = 0; i < nParticles; i++) {
2851 valuesInList.push_back(std::get<double>(var->function(listOfParticles->getParticle(i))));
2853 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2855 for (
int i = 0; i < nParticles; i++) {
2856 valuesInList.push_back(std::get<int>(var->function(listOfParticles->getParticle(i))));
2859 std::sort(valuesInList.begin(), valuesInList.end());
2860 if (nParticles % 2 != 0)
2862 return valuesInList[nParticles / 2];
2865 return 0.5 * (valuesInList[nParticles / 2] + valuesInList[nParticles / 2 - 1]);
2870 B2FATAL(
"Wrong number of arguments for meta function medianValueInList");
2876 if (arguments.size() == 2) {
2877 std::string listName = arguments[0];
2880 auto func = [listName, var](
const Particle*) ->
double {
2881 StoreObjPtr<ParticleList> listOfParticles(listName);
2883 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to sumValueInList");
2884 int nParticles = listOfParticles->getListSize();
2885 if (nParticles == 0)
2890 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2892 for (
int i = 0; i < nParticles; i++) {
2893 sum += std::get<double>(var->function(listOfParticles->getParticle(i)));
2895 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2897 for (
int i = 0; i < nParticles; i++) {
2898 sum += std::get<int>(var->function(listOfParticles->getParticle(i)));
2905 B2FATAL(
"Wrong number of arguments for meta function sumValueInList");
2911 if (arguments.size() == 2) {
2912 std::string listName = arguments[0];
2915 auto func = [listName, var](
const Particle*) ->
double {
2916 StoreObjPtr<ParticleList> listOfParticles(listName);
2918 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to productValueInList");
2919 int nParticles = listOfParticles->getListSize();
2920 if (nParticles == 0)
2925 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2927 for (
int i = 0; i < nParticles; i++) {
2928 product *= std::get<double>(var->function(listOfParticles->getParticle(i)));
2930 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2932 for (
int i = 0; i < nParticles; i++) {
2933 product *= std::get<int>(var->function(listOfParticles->getParticle(i)));
2940 B2FATAL(
"Wrong number of arguments for meta function productValueInList");
2947 if (arguments.size() != 1)
2948 B2FATAL(
"Wrong number of arguments for meta function angleToClosestInList");
2950 std::string listname = arguments[0];
2952 auto func = [listname](
const Particle * particle) ->
double {
2954 StoreObjPtr<ParticleList> list(listname);
2955 if (not list.isValid())
2956 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToClosestInList");
2959 if (list->getListSize() == 0)
2964 const auto p_this = frame.getMomentum(particle);
2967 double minAngle = 2 * M_PI;
2968 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2970 const Particle* compareme = list->getParticle(i);
2971 const auto p_compare = frame.getMomentum(compareme);
2972 double angle = ROOT::Math::VectorUtil::Angle(p_compare, p_this);
2973 if (minAngle > angle) minAngle = angle;
2983 if (arguments.size() != 2)
2984 B2FATAL(
"Wrong number of arguments for meta function closestInList");
2986 std::string listname = arguments[0];
2991 auto func = [listname, var](
const Particle * particle) ->
double {
2993 StoreObjPtr<ParticleList> list(listname);
2994 if (not list.isValid())
2995 B2FATAL(
"Invalid particle list name " << listname <<
" given to closestInList");
2999 const auto p_this = frame.getMomentum(particle);
3002 double minAngle = 2 * M_PI;
3004 for (
unsigned int i = 0; i < list->getListSize(); ++i)
3006 const Particle* compareme = list->getParticle(i);
3007 const auto p_compare = frame.getMomentum(compareme);
3008 double angle = ROOT::Math::VectorUtil::Angle(p_compare, p_this);
3009 if (minAngle > angle) {
3017 auto var_result = var->function(list->getParticle(iClosest));
3018 if (std::holds_alternative<double>(var_result))
3020 return std::get<double>(var_result);
3021 }
else if (std::holds_alternative<int>(var_result))
3023 return std::get<int>(var_result);
3024 }
else if (std::holds_alternative<bool>(var_result))
3026 return std::get<bool>(var_result);
3035 if (arguments.size() != 1)
3036 B2FATAL(
"Wrong number of arguments for meta function angleToMostB2BInList");
3038 std::string listname = arguments[0];
3040 auto func = [listname](
const Particle * particle) ->
double {
3042 StoreObjPtr<ParticleList> list(listname);
3043 if (not list.isValid())
3044 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToMostB2BInList");
3047 if (list->getListSize() == 0)
3052 const auto p_this = frame.getMomentum(particle);
3056 double maxAngle = 0;
3057 for (
unsigned int i = 0; i < list->getListSize(); ++i)
3059 const Particle* compareme = list->getParticle(i);
3060 const auto p_compare = frame.getMomentum(compareme);
3061 double angle = ROOT::Math::VectorUtil::Angle(p_compare, p_this);
3062 if (maxAngle < angle) maxAngle = angle;
3072 if (arguments.size() != 1)
3073 B2FATAL(
"Wrong number of arguments for meta function deltaPhiToMostB2BPhiInList");
3075 std::string listname = arguments[0];
3077 auto func = [listname](
const Particle * particle) ->
double {
3079 StoreObjPtr<ParticleList> list(listname);
3080 if (not list.isValid())
3081 B2FATAL(
"Invalid particle list name " << listname <<
" given to deltaPhiToMostB2BPhiInList");
3084 if (list->getListSize() == 0)
3089 const auto phi_this = frame.getMomentum(particle).Phi();
3092 double maxAngle = 0;
3093 for (
unsigned int i = 0; i < list->getListSize(); ++i)
3095 const Particle* compareme = list->getParticle(i);
3096 const auto phi_compare = frame.getMomentum(compareme).Phi();
3097 double angle = std::abs(phi_compare - phi_this);
3098 if (angle > M_PI) {angle = 2 * M_PI - angle;}
3099 if (maxAngle < angle) maxAngle = angle;
3109 if (arguments.size() != 2)
3110 B2FATAL(
"Wrong number of arguments for meta function mostB2BInList");
3112 std::string listname = arguments[0];
3117 auto func = [listname, var](
const Particle * particle) ->
double {
3119 StoreObjPtr<ParticleList> list(listname);
3120 if (not list.isValid())
3121 B2FATAL(
"Invalid particle list name " << listname <<
" given to mostB2BInList");
3125 const auto p_this = frame.getMomentum(particle);
3129 double maxAngle = -1.0;
3131 for (
unsigned int i = 0; i < list->getListSize(); ++i)
3133 const Particle* compareme = list->getParticle(i);
3134 const auto p_compare = frame.getMomentum(compareme);
3135 double angle = ROOT::Math::VectorUtil::Angle(p_compare, p_this);
3136 if (maxAngle < angle) {
3144 auto var_result = var->function(list->getParticle(iMostB2B));
3145 if (std::holds_alternative<double>(var_result))
3147 return std::get<double>(var_result);
3148 }
else if (std::holds_alternative<int>(var_result))
3150 return std::get<int>(var_result);
3151 }
else if (std::holds_alternative<bool>(var_result))
3153 return std::get<bool>(var_result);
3161 if (arguments.size() == 1) {
3162 std::string listName = arguments[0];
3163 auto func = [listName](
const Particle*) ->
double {
3164 StoreObjPtr<ParticleList> listOfParticles(listName);
3166 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxOpeningAngleInList");
3167 int nParticles = listOfParticles->getListSize();
3172 double maxOpeningAngle = -1;
3173 for (
int i = 0; i < nParticles; i++)
3175 ROOT::Math::PxPyPzEVector v1 = frame.getMomentum(listOfParticles->getParticle(i));
3176 for (
int j = i + 1; j < nParticles; j++) {
3177 ROOT::Math::PxPyPzEVector v2 = frame.getMomentum(listOfParticles->getParticle(j));
3178 const double angle = ROOT::Math::VectorUtil::Angle(v1, v2);
3179 if (angle > maxOpeningAngle) maxOpeningAngle = angle;
3182 return maxOpeningAngle;
3186 B2FATAL(
"Wrong number of arguments for meta function maxOpeningAngleInList");
3193 if (arguments.size() >= 2) {
3198 auto func = [var, arguments](
const Particle * particle) ->
double {
3199 if (particle ==
nullptr)
3201 B2WARNING(
"Trying to access a daughter that does not exist. Skipping");
3207 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
3211 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++)
3213 auto generalizedIndex = arguments[iCoord];
3214 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
3216 pSum += frame.getMomentum(dauPart);
3218 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
3224 Particle sumOfDaughters(pSum, 100);
3226 auto var_result = var->function(&sumOfDaughters);
3228 if (std::holds_alternative<double>(var_result))
3230 return std::get<double>(var_result);
3231 }
else if (std::holds_alternative<int>(var_result))
3233 return std::get<int>(var_result);
3234 }
else if (std::holds_alternative<bool>(var_result))
3236 return std::get<bool>(var_result);
3241 B2FATAL(
"Wrong number of arguments for meta function daughterCombination");
3244 Manager::FunctionPtr useAlternativeDaughterHypothesis(
const std::vector<std::string>& arguments)
3257 if (arguments.size() >= 2) {
3268 std::unordered_map<unsigned int, int> mapOfReplacedDaughters;
3271 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++) {
3272 auto replacedDauString = arguments[iCoord];
3274 std::vector<std::string> indexAndMass;
3275 boost::split(indexAndMass, replacedDauString, boost::is_any_of(
":"));
3278 if (indexAndMass.size() > 2) {
3279 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 "
3280 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
3284 if (indexAndMass.size() < 2) {
3285 B2WARNING(
"The string indicating which daughter's mass should be replaced contains only one colon-separated element instead of two. The offending string is "
3286 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
3294 }
catch (std::invalid_argument&) {
3295 B2FATAL(
"Found the string " << indexAndMass[0] <<
"instead of a daughter index.");
3299 TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(indexAndMass[1].c_str());
3301 B2WARNING(
"Particle not in evt.pdl file! " << indexAndMass[1]);
3306 int pdgCode = particlePDG->PdgCode();
3307 mapOfReplacedDaughters[dauIndex] = pdgCode;
3311 if (mapOfReplacedDaughters.size() != arguments.size() - 1)
3312 B2FATAL(
"Overlapped daughter's index is detected in the meta-variable useAlternativeDaughterHypothesis");
3320 auto func = [var, mapOfReplacedDaughters](
const Particle * particle) ->
double {
3321 if (particle ==
nullptr)
3323 B2WARNING(
"Trying to access a particle that does not exist. Skipping");
3333 ROOT::Math::PxPyPzMVector pSum(0, 0, 0, 0);
3335 for (
unsigned int iDau = 0; iDau < particle->getNDaughters(); iDau++)
3337 const Particle* dauPart = particle->getDaughter(iDau);
3339 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << iDau);
3343 ROOT::Math::PxPyPzMVector dauMom = ROOT::Math::PxPyPzMVector(frame.getMomentum(dauPart));
3347 pdgCode = mapOfReplacedDaughters.at(iDau);
3348 }
catch (std::out_of_range&) {
3355 double p_x = dauMom.Px();
3356 double p_y = dauMom.Py();
3357 double p_z = dauMom.Pz();
3358 dauMom.SetCoordinates(p_x, p_y, p_z, TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass());
3359 const_cast<Particle*
>(dummy->getDaughter(iDau))->set4VectorDividingByMomentumScaling(ROOT::Math::PxPyPzEVector(dauMom));
3362 const int charge = dummy->getDaughter(iDau)->getCharge();
3363 if (TDatabasePDG::Instance()->GetParticle(pdgCode)->Charge() / 3.0 == charge)
3364 const_cast<Particle*
>(dummy->getDaughter(iDau))->setPDGCode(pdgCode);
3366 const_cast<Particle*
>(dummy->getDaughter(iDau))->setPDGCode(-1 * pdgCode);
3372 dummy->set4Vector(ROOT::Math::PxPyPzEVector(pSum));
3374 auto var_result = var->function(dummy);
3377 if (std::holds_alternative<double>(var_result))
3379 return std::get<double>(var_result);
3380 }
else if (std::holds_alternative<int>(var_result))
3382 return std::get<int>(var_result);
3383 }
else if (std::holds_alternative<bool>(var_result))
3385 return std::get<bool>(var_result);
3391 B2FATAL(
"Wrong number of arguments for meta function useAlternativeDaughterHypothesis");
3396 if (arguments.size() == 2) {
3398 std::string arg = arguments[0];
3400 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
3402 if (part !=
nullptr) {
3403 pdg_code = std::abs(part->PdgCode());
3407 }
catch (std::exception& e) {}
3410 if (pdg_code == -1) {
3411 B2FATAL(
"Ancestor " + arg +
" is not recognised. Please provide valid PDG code or particle name.");
3414 auto func = [pdg_code, var](
const Particle * particle) ->
double {
3415 const Particle* p = particle;
3417 int ancestor_level = std::get<double>(
Manager::Instance().getVariable(
"hasAncestor(" + std::to_string(pdg_code) +
", 0)")->function(p));
3418 if ((ancestor_level <= 0) or (std::isnan(ancestor_level)))
3423 const MCParticle* i_p = p->getMCParticle();
3425 for (
int a = 0; a < ancestor_level ; a = a + 1)
3427 i_p = i_p->getMother();
3430 StoreArray<Particle> tempParticles(
"tempParticles");
3431 tempParticles.clear();
3433 Particle* newPart = tempParticles.appendNew(m_p);
3434 newPart->addRelationTo(i_p);
3436 appendDaughtersRecursive(newPart, tempParticles);
3438 auto var_result = var->function(newPart);
3439 if (std::holds_alternative<double>(var_result))
3441 return std::get<double>(var_result);
3442 }
else if (std::holds_alternative<int>(var_result))
3444 return std::get<int>(var_result);
3445 }
else if (std::holds_alternative<bool>(var_result))
3447 return std::get<bool>(var_result);
3452 B2FATAL(
"Wrong number of arguments for meta function varForFirstMCAncestorOfType (expected 2: type and variable of interest)");
3458 if (arguments.size() != 1) {
3459 B2FATAL(
"Number of arguments for nTrackFitResults must be 1, particleType or PDGcode");
3462 std::string arg = arguments[0];
3463 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
3465 if (part !=
nullptr) {
3466 absPdg = std::abs(part->PdgCode());
3470 }
catch (std::exception& e) {}
3473 auto func = [absPdg](
const Particle*) ->
int {
3475 Const::ChargedStable type(absPdg);
3476 StoreArray<Track> tracks;
3478 int nTrackFitResults = 0;
3480 for (
const auto& track : tracks)
3482 const TrackFitResult* trackFit = track.getTrackFitResultWithClosestMass(type);
3484 if (!trackFit)
continue;
3485 if (trackFit->getChargeSign() == 0)
continue;
3490 return nTrackFitResults;
3499 if (arguments.size() == 2) {
3502 auto func = [var, default_val](
const Particle * particle) ->
int {
3503 auto var_result = var->function(particle);
3504 if (std::holds_alternative<double>(var_result))
3506 double value = std::get<double>(var_result);
3507 if (value > std::numeric_limits<int>::max())
3508 value = std::numeric_limits<int>::max();
3509 if (value < std::numeric_limits<int>::min())
3510 value = std::numeric_limits<int>::min();
3511 if (std::isnan(value))
3512 value = default_val;
3513 return static_cast<int>(value);
3514 }
else if (std::holds_alternative<int>(var_result))
3515 return std::get<int>(var_result);
3516 else if (std::holds_alternative<bool>(var_result))
3517 return static_cast<int>(std::get<bool>(var_result));
3518 else return default_val;
3522 B2FATAL(
"Wrong number of arguments for meta function int, please provide variable name and replacement value for NaN!");
3526 VARIABLE_GROUP(
"MetaFunctions");
3527 REGISTER_METAVARIABLE(
"nCleanedECLClusters(cut)", nCleanedECLClusters,
3528 "[Eventbased] Returns the number of clean Clusters in the event\n"
3529 "Clean clusters are defined by the clusters which pass the given cut assuming a photon hypothesis.",
3530 Manager::VariableDataType::c_int);
3531 REGISTER_METAVARIABLE(
"nCleanedTracks(cut)", nCleanedTracks,
3532 "[Eventbased] Returns the number of clean Tracks in the event\n"
3533 "Clean tracks are defined by the tracks which pass the given cut assuming a pion hypothesis.", Manager::VariableDataType::c_int);
3534 REGISTER_METAVARIABLE(
"formula(v1 + v2 * [v3 - v4] / v5^v6)", formula, R
"DOCSTRING(
3535Returns the result of the given formula, where v1 to vN are variables or floating
3536point numbers. Currently the only supported operations are addition (``+``),
3537subtraction (``-``), multiplication (``*``), division (``/``) and power (``^``
3538or ``**``). Parenthesis can be in the form of square brackets ``[v1 * v2]``
3539or normal brackets ``(v1 * v2)``. It will work also with variables taking
3540arguments. Operator precedence is taken into account. For example ::
3542 (daughter(0, E) + daughter(1, E))**2 - p**2 + 0.138
3544.. versionchanged:: release-03-00-00
3545 now both, ``[]`` and ``()`` can be used for grouping operations, ``**`` can
3546 be used for exponent and float literals are possible directly in the
3548)DOCSTRING", Manager::VariableDataType::c_double);
3549 REGISTER_METAVARIABLE("useRestFrame(variable)", useRestFrame,
3550 "Returns the value of the variable using the rest frame of the given particle as current reference frame.\n"
3551 "E.g. ``useRestFrame(daughter(0, p))`` returns the total momentum of the first daughter in its mother's rest-frame", Manager::VariableDataType::c_double);
3552 REGISTER_METAVARIABLE(
"useCMSFrame(variable)", useCMSFrame,
3553 "Returns the value of the variable using the CMS frame as current reference frame.\n"
3554 "E.g. ``useCMSFrame(E)`` returns the energy of a particle in the CMS frame.", Manager::VariableDataType::c_double);
3555 REGISTER_METAVARIABLE(
"useLabFrame(variable)", useLabFrame, R
"DOC(
3556Returns the value of ``variable`` in the *lab* frame.
3559 The lab frame is the default reference frame, usually you don't need to use this meta-variable.
3560 E.g. ``useLabFrame(E)`` returns the energy of a particle in the Lab frame, same as just ``E``.
3562Specifying the lab frame is useful in some corner-cases. For example:
3563``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.
3564)DOC", Manager::VariableDataType::c_double);
3565 REGISTER_METAVARIABLE("useTagSideRecoilRestFrame(variable, daughterIndexTagB)", useTagSideRecoilRestFrame,
3566 "Returns the value of the variable in the rest frame of the recoiling particle to the tag side B meson.\n"
3567 "The variable should only be applied to an Upsilon(4S) list.\n"
3568 "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);
3569 REGISTER_METAVARIABLE(
"useParticleRestFrame(variable, particleList)", useParticleRestFrame,
3570 "Returns the value of the variable in the rest frame of the first Particle contained in the given ParticleList.\n"
3571 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
3572 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
3573 "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);
3574 REGISTER_METAVARIABLE(
"useRecoilParticleRestFrame(variable, particleList)", useRecoilParticleRestFrame,
3575 "Returns the value of the variable in the rest frame of recoil system against the first Particle contained in the given ParticleList.\n"
3576 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
3577 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
3578 "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);
3579 REGISTER_METAVARIABLE(
"useDaughterRestFrame(variable, daughterIndex_1, [daughterIndex_2, ... daughterIndex_3])", useDaughterRestFrame,
3580 "Returns the value of the variable in the rest frame of the selected daughter particle.\n"
3581 "The daughter is identified via generalized daughter index, e.g. ``0:1`` identifies the second daughter (1) "
3582 "of the first daughter (0). If the daughter index is invalid, it returns NaN.\n"
3583 "If two or more indices are given, the rest frame of the sum of the daughters is used.",
3584 Manager::VariableDataType::c_double);
3585 REGISTER_METAVARIABLE(
"useDaughterRecoilRestFrame(variable, daughterIndex_1, [daughterIndex_2, ... daughterIndex_3])", useDaughterRecoilRestFrame,
3586 "Returns the value of the variable in the rest frame of the recoil of the selected daughter particle.\n"
3587 "The daughter is identified via generalized daughter index, e.g. ``0:1`` identifies the second daughter (1) "
3588 "of the first daughter (0). If the daughter index is invalid, it returns NaN.\n"
3589 "If two or more indices are given, the rest frame of the sum of the daughters is used.",
3590 Manager::VariableDataType::c_double);
3591 REGISTER_METAVARIABLE(
"useMCancestorBRestFrame(variable)", useMCancestorBRestFrame,
3592 "Returns the value of the variable in the rest frame of the ancestor B MC particle.\n"
3593 "If no B or no MC-matching is found, it returns NaN.", Manager::VariableDataType::c_double);
3594 REGISTER_METAVARIABLE(
"passesCut(cut)", passesCut,
3595 "Returns 1 if particle passes the cut otherwise 0.\n"
3596 "Useful if you want to write out if a particle would have passed a cut or not.", Manager::VariableDataType::c_bool);
3597 REGISTER_METAVARIABLE(
"passesEventCut(cut)", passesEventCut,
3598 "[Eventbased] Returns 1 if event passes the cut otherwise 0.\n"
3599 "Useful if you want to select events passing a cut without looping into particles, such as for skimming.\n", Manager::VariableDataType::c_bool);
3600 REGISTER_METAVARIABLE(
"countDaughters(cut)", countDaughters,
3601 "Returns number of direct daughters which satisfy the cut.\n"
3602 "Used by the skimming package (for what exactly?)", Manager::VariableDataType::c_int);
3603 REGISTER_METAVARIABLE(
"countFSPDaughters(cut)", countDescendants,
3604 "Returns number of final-state daughters which satisfy the cut.",
3605 Manager::VariableDataType::c_int);
3606 REGISTER_METAVARIABLE(
"countDescendants(cut)", countDescendants,
3607 "Returns number of descendants for all generations which satisfy the cut.",
3608 Manager::VariableDataType::c_int);
3609 REGISTER_METAVARIABLE(
"varFor(pdgCode, variable)", varFor,
3610 "Returns the value of the variable for the given particle if its abs(pdgCode) agrees with the given one.\n"
3611 "E.g. ``varFor(11, p)`` returns the momentum if the particle is an electron or a positron.", Manager::VariableDataType::c_double);
3612 REGISTER_METAVARIABLE(
"varForMCGen(variable)", varForMCGen,
3613 "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"
3614 "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"
3615 "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);
3616 REGISTER_METAVARIABLE(
"nParticlesInList(particleListName)", nParticlesInList,
3617 "[Eventbased] Returns number of particles in the given particle List.", Manager::VariableDataType::c_int);
3618 REGISTER_METAVARIABLE(
"isInList(particleListName)", isInList,
3619 "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);
3620 REGISTER_METAVARIABLE(
"isDaughterOfList(particleListNames)", isDaughterOfList,
3621 "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);
3622 REGISTER_METAVARIABLE(
"isDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isDescendantOfList, R
"DOC(
3623 Returns 1 if the given particle appears in the decay chain of the particles in the given ParticleLists.
3625 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
3627 * ``isDescendantOfList(<particle_list>,1)`` returns 1 if particle is a daughter of the list,
3628 * ``isDescendantOfList(<particle_list>,2)`` returns 1 if particle is a granddaughter of the list,
3629 * ``isDescendantOfList(<particle_list>,3)`` returns 1 if particle is a great-granddaughter of the list, etc.
3630 * Default value is ``-1`` that is inclusive for all generations.
3631 )DOC", Manager::VariableDataType::c_bool);
3632 REGISTER_METAVARIABLE("isMCDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isMCDescendantOfList, R
"DOC(
3633 Returns 1 if the given particle is linked to the same MC particle as any reconstructed daughter of the decay lists.
3635 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
3637 * ``isMCDescendantOfList(<particle_list>,1)`` returns 1 if particle is matched to the same particle as any daughter of the list,
3638 * ``isMCDescendantOfList(<particle_list>,2)`` returns 1 if particle is matched to the same particle as any granddaughter of the list,
3639 * ``isMCDescendantOfList(<particle_list>,3)`` returns 1 if particle is matched to the same particle as any great-granddaughter of the list, etc.
3640 * Default value is ``-1`` that is inclusive for all generations.
3642 It makes only sense for lists created with `fillParticleListFromMC` function with ``addDaughters=True`` argument.
3643 )DOC", Manager::VariableDataType::c_bool);
3645 REGISTER_METAVARIABLE("sourceObjectIsInList(particleListName)", sourceObjectIsInList, R
"DOC(
3646Returns 1 if the underlying mdst object (e.g. track, or cluster) was used to create a particle in ``particleListName``, 0 if not.
3649 This only makes sense for particles that are not composite. Returns -1 for composite particles.
3650)DOC", Manager::VariableDataType::c_int);
3652 REGISTER_METAVARIABLE("mcParticleIsInMCList(particleListName)", mcParticleIsInMCList, R
"DOC(
3653Returns 1 if the particle's matched MC particle is also matched to a particle in ``particleListName``
3654(or if either of the lists were filled from generator level `modularAnalysis.fillParticleListFromMC`.)
3656.. seealso:: :b2:var:`isMCDescendantOfList` to check daughters.
3657)DOC", Manager::VariableDataType::c_bool);
3659 REGISTER_METAVARIABLE("isGrandDaughterOfList(particleListNames)", isGrandDaughterOfList,
3660 "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);
3661 REGISTER_METAVARIABLE(
"originalParticle(variable)", originalParticle, R
"DOC(
3662 Returns value of variable for the original particle from which the given particle is copied.
3664 The copy of particle is created, for example, when the vertex fit updates the daughters and `modularAnalysis.copyParticles` is called.
3665 Returns NaN if the given particle is not copied and so there is no original particle.
3666 )DOC", Manager::VariableDataType::c_double);
3667 REGISTER_METAVARIABLE("daughter(i, variable)", daughter, R
"DOC(
3668 Returns value of variable for the i-th daughter. E.g.
3670 * ``daughter(0, p)`` returns the total momentum of the first daughter.
3671 * ``daughter(0, daughter(1, p)`` returns the total momentum of the second daughter of the first daughter.
3673 Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters).
3674 )DOC", Manager::VariableDataType::c_double);
3675 REGISTER_METAVARIABLE("originalDaughter(i, variable)", originalDaughter, R
"DOC(
3676 Returns value of variable for the original particle from which the i-th daughter is copied.
3678 The copy of particle is created, for example, when the vertex fit updates the daughters and `modularAnalysis.copyParticles` is called.
3679 Returns NaN if the daughter is not copied and so there is no original daughter.
3681 Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters).
3682 )DOC", Manager::VariableDataType::c_double);
3683 REGISTER_METAVARIABLE("mcDaughter(i, variable)", mcDaughter, R
"DOC(
3684 Returns the value of the requested variable for the i-th Monte Carlo daughter of the particle.
3686 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
3687 or if the i-th MC daughter does not exist.
3689 E.g. ``mcDaughter(0, PDG)`` will return the PDG code of the first MC daughter of the matched MC
3690 particle of the reconstructed particle the function is applied to.
3692 The meta variable can also be nested: ``mcDaughter(0, mcDaughter(1, PDG))``.
3693 )DOC", Manager::VariableDataType::c_double);
3694 REGISTER_METAVARIABLE("mcMother(variable)", mcMother, R
"DOC(
3695 Returns the value of the requested variable for the Monte Carlo mother of the particle.
3697 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
3698 or if the MC mother does not exist.
3700 E.g. ``mcMother(PDG)`` will return the PDG code of the MC mother of the matched MC
3701 particle of the reconstructed particle the function is applied to.
3703 The meta variable can also be nested: ``mcMother(mcMother(PDG))``.
3704 )DOC", Manager::VariableDataType::c_double);
3705 REGISTER_METAVARIABLE("genParticle(index, variable)", genParticle, R
"DOC(
3706[Eventbased] Returns the ``variable`` for the ith generator particle.
3707The arguments of the function must be the ``index`` of the particle in the MCParticle Array,
3708and ``variable``, the name of the function or variable for that generator particle.
3709If ``index`` goes beyond the length of the MCParticles array, NaN will be returned.
3711E.g. ``genParticle(0, p)`` returns the total momentum of the first MCParticle, which in a generic decay up to MC15 is
3712the Upsilon(4S) and for MC16 and beyond the initial electron.
3713)DOC", Manager::VariableDataType::c_double);
3714 REGISTER_METAVARIABLE("genUpsilon4S(variable)", genUpsilon4S, R
"DOC(
3715[Eventbased] Returns the ``variable`` evaluated for the generator-level :math:`\Upsilon(4S)`.
3716If no generator level :math:`\Upsilon(4S)` exists for the event, NaN will be returned.
3718E.g. ``genUpsilon4S(p)`` returns the total momentum of the :math:`\Upsilon(4S)` in a generic decay.
3719``genUpsilon4S(mcDaughter(1, p))`` returns the total momentum of the second daughter of the
3720generator-level :math:`\Upsilon(4S)` (i.e. the momentum of the second B meson in a generic decay).
3721)DOC", Manager::VariableDataType::c_double);
3722 REGISTER_METAVARIABLE("daughterProductOf(variable)", daughterProductOf,
3723 "Returns product of a variable over all daughters.\n"
3724 "E.g. ``daughterProductOf(extraInfo(SignalProbability))`` returns the product of the SignalProbabilitys of all daughters.", Manager::VariableDataType::c_double);
3725 REGISTER_METAVARIABLE(
"daughterSumOf(variable)", daughterSumOf,
3726 "Returns sum of a variable over all daughters.\n"
3727 "E.g. ``daughterSumOf(nDaughters)`` returns the number of grand-daughters.", Manager::VariableDataType::c_double);
3728 REGISTER_METAVARIABLE(
"daughterLowest(variable)", daughterLowest,
3729 "Returns the lowest value of the given variable among all daughters.\n"
3730 "E.g. ``useCMSFrame(daughterLowest(p))`` returns the lowest momentum in CMS frame.", Manager::VariableDataType::c_double);
3731 REGISTER_METAVARIABLE(
"daughterHighest(variable)", daughterHighest,
3732 "Returns the highest value of the given variable among all daughters.\n"
3733 "E.g. ``useCMSFrame(daughterHighest(p))`` returns the highest momentum in CMS frame.", Manager::VariableDataType::c_double);
3734 REGISTER_METAVARIABLE(
"daughterDiffOf(daughterIndex_i, daughterIndex_j, variable)", daughterDiffOf, R
"DOC(
3735 Returns the difference of a variable between the two given daughters.
3736 E.g. ``useRestFrame(daughterDiffOf(0, 1, p))`` returns the momentum difference between first and second daughter in the rest frame of the given particle.
3737 (That means that it returns :math:`p_j - p_i`)
3739 The daughters can be provided as generalized daughter indexes, which are simply colon-separated
3740 lists of daughter indexes, ordered starting from the root particle. For example, ``0:1``
3741 identifies the second daughter (1) of the first daughter (0) of the mother particle.
3743 )DOC", Manager::VariableDataType::c_double);
3744 REGISTER_METAVARIABLE("mcDaughterDiffOf(i, j, variable)", mcDaughterDiffOf,
3745 "MC matched version of the `daughterDiffOf` function.", Manager::VariableDataType::c_double);
3746 REGISTER_METAVARIABLE(
"grandDaughterDiffOf(i, j, variable)", grandDaughterDiffOf,
3747 "Returns the difference of a variable between the first daughters of the two given daughters.\n"
3748 "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"
3749 "(That means that it returns :math:`p_j - p_i`)", Manager::VariableDataType::c_double);
3750 MAKE_DEPRECATED(
"grandDaughterDiffOf",
false,
"light-2402-ocicat", R
"DOC(
3751 The difference between any combination of (grand-)daughters can be calculated with the more general variable :b2:var:`daughterDiffOf`
3752 by using generalized daughter indexes.)DOC");
3753 REGISTER_METAVARIABLE("daughterNormDiffOf(i, j, variable)", daughterNormDiffOf,
3754 "Returns the normalized difference of a variable between the two given daughters.\n"
3755 "E.g. ``daughterNormDiffOf(0, 1, p)`` returns the normalized momentum difference between first and second daughter in the lab frame.", Manager::VariableDataType::c_double);
3756 REGISTER_METAVARIABLE(
"daughterMotherDiffOf(i, variable)", daughterMotherDiffOf,
3757 "Returns the difference of a variable between the given daughter and the mother particle itself.\n"
3758 "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);
3759 REGISTER_METAVARIABLE(
"daughterMotherNormDiffOf(i, variable)", daughterMotherNormDiffOf,
3760 "Returns the normalized difference of a variable between the given daughter and the mother particle itself.\n"
3761 "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);
3762 REGISTER_METAVARIABLE(
"angleBetweenDaughterAndRecoil(daughterIndex_1, daughterIndex_2, ... )", angleBetweenDaughterAndRecoil, R
"DOC(
3763 Returns the angle between the momentum recoiling against the particle and the sum of the momenta of the given daughters.
3764 The unit of the angle is ``rad``.
3766 The particles are identified via generalized daughter indexes, which are simply colon-separated lists of
3767 daughter indexes, ordered starting from the root particle. For example, ``0:1:3`` identifies the fourth
3768 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply
3769 identifies the second daughter of the root particle.
3771 At least one generalized index has to be given to ``angleBetweenDaughterAndRecoil``.
3774 ``angleBetweenDaughterAndRecoil(0)`` will return the angle between pRecoil and the momentum of the first daughter.
3776 ``angleBetweenDaughterAndRecoil(0, 1)`` will return the angle between pRecoil and the sum of the momenta of the first and second daughter.
3778 ``angleBetweenDaughterAndRecoil(0:0, 3:0)`` will return the angle between pRecoil and the sum of the momenta of the: first daughter of the first daughter, and
3779 the first daughter of the fourth daughter.)DOC", Manager::VariableDataType::c_double);
3780 REGISTER_METAVARIABLE("angleBetweenDaughterAndMissingMomentum(daughterIndex_1, daughterIndex_2, ... )", angleBetweenDaughterAndMissingMomentum, R
"DOC(
3781 Returns the angle between the missing momentum in the event and the sum of the momenta of the given daughters.
3782 The unit of the angle is ``rad``. EventKinematics module has to be called to use this.
3784 The particles are identified via generalized daughter indexes, which are simply colon-separated lists of
3785 daughter indexes, ordered starting from the root particle. For example, ``0:1:3`` identifies the fourth
3786 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply
3787 identifies the second daughter of the root particle.
3789 At least one generalized index has to be given to ``angleBetweenDaughterAndMissingMomentum``.
3792 ``angleBetweenDaughterAndMissingMomentum(0)`` will return the angle between missMom and the momentum of the first daughter.
3794 ``angleBetweenDaughterAndMissingMomentum(0, 1)`` will return the angle between missMom and the sum of the momenta of the first and second daughter.
3796 ``angleBetweenDaughterAndMissingMomentum(0:0, 3:0)`` will return the angle between missMom and the sum of the momenta of the: first daughter of the first daughter, and
3797 the first daughter of the fourth daughter.)DOC", Manager::VariableDataType::c_double);
3798 REGISTER_METAVARIABLE("daughterAngle(daughterIndex_1, daughterIndex_2[, daughterIndex_3])", daughterAngle, R
"DOC(
3799 Returns the angle in between any pair of particles belonging to the same decay tree.
3800 The unit of the angle is ``rad``.
3802 The particles are identified via generalized daughter indexes, which are simply colon-separated lists of
3803 daughter indexes, ordered starting from the root particle. For example, ``0:1:3`` identifies the fourth
3804 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply
3805 identifies the second daughter of the root particle.
3807 Both two and three generalized indexes can be given to ``daughterAngle``. If two indices are given, the
3808 variable returns the angle between the momenta of the two given particles. If three indices are given, the
3809 variable returns the angle between the momentum of the third particle and a vector which is the sum of the
3810 first two daughter momenta.
3813 ``daughterAngle(0, 3)`` will return the angle between the first and fourth daughter.
3814 ``daughterAngle(0, 1, 3)`` will return the angle between the fourth daughter and the sum of the first and
3816 ``daughterAngle(0:0, 3:0)`` will return the angle between the first daughter of the first daughter, and
3817 the first daughter of the fourth daughter.
3819 )DOC", Manager::VariableDataType::c_double);
3820 REGISTER_METAVARIABLE("mcDaughterAngle(daughterIndex_1, daughterIndex_2, [daughterIndex_3])", mcDaughterAngle,
3821 "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);
3822 REGISTER_VARIABLE(
"grandDaughterDecayAngle(i, j)", grandDaughterDecayAngle,
3823 "Returns the decay angle of the granddaughter in the daughter particle's rest frame.\n"
3824 "It is calculated with respect to the reverted momentum vector of the particle.\n"
3825 "Two arguments representing the daughter and granddaughter indices have to be provided as arguments.\n\n",
"rad");
3826 REGISTER_VARIABLE(
"daughterClusterAngleInBetween(i, j)", daughterClusterAngleInBetween,
3827 "Returns the angle between clusters associated to the two daughters."
3828 "If two indices given: returns the angle between the momenta of the clusters associated to the two given daughters."
3829 "If three indices given: returns the angle between the momentum of the third particle's cluster and a vector "
3830 "which is the sum of the first two daughter's cluster momenta."
3831 "Returns nan if any of the daughters specified don't have an associated cluster."
3832 "The arguments in the argument vector must be integers corresponding to the ith and jth (and kth) daughters.\n\n",
"rad");
3833 REGISTER_METAVARIABLE(
"daughterInvM(i[, j, ...])", daughterInvM, R
"DOC(
3834 Returns the invariant mass adding the Lorentz vectors of the given daughters. The unit of the invariant mass is GeV/:math:`\text{c}^2`
3835 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.
3837 Daughters from different generations of the decay tree can be combined using generalized daughter indexes,
3838 which are simply colon-separated daughter indexes for each generation, starting from the root particle. For
3839 example, ``0:1:3`` identifies the fourth daughter (3) of the second daughter (1) of the first daughter(0) of
3840 the mother particle.
3842 Returns NaN if the given daughter-index is out of bound (>= number of daughters))DOC", Manager::VariableDataType::c_double);
3843 REGISTER_METAVARIABLE("extraInfo(name)", extraInfo,
3844 "Returns extra info stored under the given name.\n"
3845 "The extraInfo has to be set by a module first.\n"
3846 "E.g. ``extraInfo(SignalProbability)`` returns the SignalProbability calculated by the ``MVAExpert`` module.\n"
3847 "If nothing is set under the given name or if the particle is a nullptr, NaN is returned.\n"
3848 "In the latter case please use `eventExtraInfo` if you want to access an EventExtraInfo variable.", Manager::VariableDataType::c_double);
3849 REGISTER_METAVARIABLE(
"eventExtraInfo(name)", eventExtraInfo,
3850 "[Eventbased] Returns extra info stored under the given name in the event extra info.\n"
3851 "The extraInfo has to be set first by another module like MVAExpert in event mode.\n"
3852 "If nothing is set under this name, NaN is returned.", Manager::VariableDataType::c_double);
3853 REGISTER_METAVARIABLE(
"eventCached(variable)", eventCached,
3854 "[Eventbased] Returns value of event-based variable and caches this value in the EventExtraInfo.\n"
3855 "The result of second call to this variable in the same event will be provided from the cache.\n"
3856 "It is recommended to use this variable in order to declare custom aliases as event-based. This is "
3857 "necessary if using the eventwise mode of variablesToNtuple).", Manager::VariableDataType::c_double);
3858 REGISTER_METAVARIABLE(
"particleCached(variable)", particleCached,
3859 "Returns value of given variable and caches this value in the ParticleExtraInfo of the provided particle.\n"
3860 "The result of second call to this variable on the same particle will be provided from the cache.", Manager::VariableDataType::c_double);
3861 REGISTER_METAVARIABLE(
"modulo(variable, n)", modulo,
3862 "Returns rest of division of variable by n.", Manager::VariableDataType::c_int);
3863 REGISTER_METAVARIABLE(
"abs(variable)", abs,
3864 "Returns absolute value of the given variable.\n"
3865 "E.g. abs(mcPDG) returns the absolute value of the mcPDG, which is often useful for cuts.", Manager::VariableDataType::c_double);
3866 REGISTER_METAVARIABLE(
"max(var1,var2)", max,
"Returns max value of two variables.\n", Manager::VariableDataType::c_double);
3867 REGISTER_METAVARIABLE(
"min(var1,var2)", min,
"Returns min value of two variables.\n", Manager::VariableDataType::c_double);
3868 REGISTER_METAVARIABLE(
"sin(variable)", sin,
"Returns sine value of the given variable.", Manager::VariableDataType::c_double);
3869 REGISTER_METAVARIABLE(
"asin(variable)", asin,
"Returns arcsine of the given variable. The unit of the asin() is ``rad``", Manager::VariableDataType::c_double);
3870 REGISTER_METAVARIABLE(
"cos(variable)", cos,
"Returns cosine value of the given variable.", Manager::VariableDataType::c_double);
3871 REGISTER_METAVARIABLE(
"acos(variable)", acos,
"Returns arccosine value of the given variable. The unit of the acos() is ``rad``", Manager::VariableDataType::c_double);
3872 REGISTER_METAVARIABLE(
"tan(variable)", tan,
"Returns tangent value of the given variable.", Manager::VariableDataType::c_double);
3873 REGISTER_METAVARIABLE(
"atan(variable)", atan,
"Returns arctangent value of the given variable. The unit of the atan() is ``rad``", Manager::VariableDataType::c_double);
3874 REGISTER_METAVARIABLE(
"exp(variable)", exp,
"Returns exponential evaluated for the given variable.", Manager::VariableDataType::c_double);
3875 REGISTER_METAVARIABLE(
"log(variable)", log,
"Returns natural logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
3876 REGISTER_METAVARIABLE(
"log10(variable)", log10,
"Returns base-10 logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
3877 REGISTER_METAVARIABLE(
"int(variable, nan_replacement)", convertToInt, R
"DOC(
3878 Casts the output of the variable to an integer value.
3881 Overflow and underflow are clipped at maximum and minimum values, respectively. NaN values are replaced with the value of the 2nd argument.
3883 )DOC", Manager::VariableDataType::c_int);
3884 REGISTER_METAVARIABLE("isNAN(variable)", isNAN,
3885 "Returns true if variable value evaluates to nan (determined via std::isnan(double)).\n"
3886 "Useful for debugging.", Manager::VariableDataType::c_bool);
3887 REGISTER_METAVARIABLE(
"ifNANgiveX(variable, x)", ifNANgiveX,
3888 "Returns x (has to be a number) if variable value is nan (determined via std::isnan(double)).\n"
3889 "Useful for technical purposes while training MVAs.", Manager::VariableDataType::c_double);
3890 REGISTER_METAVARIABLE(
"isInfinity(variable)", isInfinity,
3891 "Returns true if variable value evaluates to infinity (determined via std::isinf(double)).\n"
3892 "Useful for debugging.", Manager::VariableDataType::c_bool);
3893 REGISTER_METAVARIABLE(
"unmask(variable, flag1, flag2, ...)", unmask,
3894 "unmask(variable, flag1, flag2, ...) or unmask(variable, mask) sets certain bits in the variable to zero.\n"
3895 "For example, if you want to set the second, fourth and fifth bits to zero, you could call \n"
3896 "``unmask(variable, 2, 8, 16)`` or ``unmask(variable, 26)``.\n"
3897 "", Manager::VariableDataType::c_double);
3898 REGISTER_METAVARIABLE(
"conditionalVariableSelector(cut, variableIfTrue, variableIfFalse)", conditionalVariableSelector,
3899 "Returns one of the two supplied variables, depending on whether the particle passes the supplied cut.\n"
3900 "The first variable is returned if the particle passes the cut, and the second variable is returned otherwise.", Manager::VariableDataType::c_double);
3901 REGISTER_METAVARIABLE(
"pValueCombination(p1, p2, ...)", pValueCombination,
3902 "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"
3903 "If any of the p-values is invalid, i.e. smaller than zero, -1 is returned.", Manager::VariableDataType::c_double);
3904 REGISTER_METAVARIABLE(
"pValueCombinationOfDaughters(variable)", pValueCombinationOfDaughters,
3905 "Returns the combined p-value of the daughter 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"
3906 "If any of the p-values is invalid, i.e. smaller than zero, -1 is returned.", Manager::VariableDataType::c_double);
3907 REGISTER_METAVARIABLE(
"veto(particleList, cut, pdgCode = 11)", veto,
3908 "Combines current particle with particles from the given particle list and returns 1 if the combination passes the provided cut. \n"
3909 "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"
3910 "around the neutral Pion mass (e.g. ``0.130 < M < 0.140``). \n"
3911 "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);
3912 REGISTER_METAVARIABLE(
"matchedMC(variable)", matchedMC,
3913 "Returns variable output for the matched MCParticle by constructing a temporary Particle from it.\n"
3914 "This may not work too well if your variable requires accessing daughters of the particle.\n"
3915 "E.g. ``matchedMC(p)`` returns the total momentum of the related MCParticle.\n"
3916 "Returns NaN if no matched MCParticle exists.", Manager::VariableDataType::c_double);
3917 REGISTER_METAVARIABLE(
"clusterBestMatchedMCParticle(variable)", clusterBestMatchedMCParticle,
3918 "Returns variable output for the MCParticle that is best-matched with the ECLCluster of the given Particle.\n"
3919 "E.g. To get the energy of the MCParticle that matches best with an ECLCluster, one could use ``clusterBestMatchedMCParticle(E)``\n"
3920 "When the variable is called for ``gamma`` and if the ``gamma`` is matched with MCParticle, it works same as `matchedMC`.\n"
3921 "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"
3922 "Returns NaN if the particle is not matched to an ECLCluster, or if the ECLCluster has no matching MCParticles", Manager::VariableDataType::c_double);
3923 REGISTER_METAVARIABLE(
"varForBestMatchedMCKlong(variable)", clusterBestMatchedMCKlong,
3924 "Returns variable output for the Klong MCParticle which has the best match with the ECLCluster of the given Particle.\n"
3925 "Returns NaN if the particle is not matched to an ECLCluster, or if the ECLCluster has no matching Klong MCParticle", Manager::VariableDataType::c_double);
3927 REGISTER_METAVARIABLE(
"countInList(particleList, cut='')", countInList,
"[Eventbased] "
3928 "Returns number of particle which pass given in cut in the specified particle list.\n"
3929 "Useful for creating statistics about the number of particles in a list.\n"
3930 "E.g. ``countInList(e+, isSignal == 1)`` returns the number of correctly reconstructed electrons in the event.\n"
3931 "The variable is event-based and does not need a valid particle pointer as input.", Manager::VariableDataType::c_int);
3932 REGISTER_METAVARIABLE(
"getVariableByRank(particleList, rankedVariableName, variableName, rank)", getVariableByRank, R
"DOC(
3933 [Eventbased] Returns the value of ``variableName`` for the candidate in the ``particleList`` with the requested ``rank``.
3936 The `BestCandidateSelection` module available via `rankByHighest` / `rankByLowest` has to be used before.
3939 The first candidate matching the given rank is used.
3940 Thus, it is not recommended to use this variable in conjunction with ``allowMultiRank`` in the `BestCandidateSelection` module.
3942 The suffix ``_rank`` is automatically added to the argument ``rankedVariableName``,
3943 which either has to be the name of the variable used to order the candidates or the selected outputVariable name without the ending ``_rank``.
3944 This means that your selected name for the rank variable has to end with ``_rank``.
3946 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>`_
3947 )DOC", Manager::VariableDataType::c_double);
3948 REGISTER_VARIABLE("matchedMCHasPDG(PDGCode)", matchedMCHasPDG,
3949 "Returns if the absolute value of the PDGCode of the MCParticle related to the Particle matches a given PDGCode."
3950 "Returns 0/NAN/1 if PDGCode does not match/is not available/ matches");
3951 REGISTER_METAVARIABLE(
"numberOfNonOverlappingParticles(pList1, pList2, ...)", numberOfNonOverlappingParticles,
3952 "Returns the number of non-overlapping particles in the given particle lists"
3953 "Useful to check if there is additional physics going on in the detector if one reconstructed the Y4S", Manager::VariableDataType::c_int);
3954 REGISTER_METAVARIABLE(
"totalEnergyOfParticlesInList(particleListName)", totalEnergyOfParticlesInList,
3955 "[Eventbased] Returns the total energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
3956 REGISTER_METAVARIABLE(
"totalPxOfParticlesInList(particleListName)", totalPxOfParticlesInList,
3957 "[Eventbased] Returns the total momentum Px of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3958 REGISTER_METAVARIABLE(
"totalPyOfParticlesInList(particleListName)", totalPyOfParticlesInList,
3959 "[Eventbased] Returns the total momentum Py of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3960 REGISTER_METAVARIABLE(
"totalPzOfParticlesInList(particleListName)", totalPzOfParticlesInList,
3961 "[Eventbased] Returns the total momentum Pz of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3962 REGISTER_METAVARIABLE(
"invMassInLists(pList1, pList2, ...)", invMassInLists,
3963 "[Eventbased] Returns the invariant mass of the combination of particles in the given particle lists. The unit of the invariant mass is GeV/:math:`\\text{c}^2` ", Manager::VariableDataType::c_double);
3964 REGISTER_METAVARIABLE(
"totalECLEnergyOfParticlesInList(particleListName)", totalECLEnergyOfParticlesInList,
3965 "[Eventbased] Returns the total ECL energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
3966 REGISTER_METAVARIABLE(
"maxPtInList(particleListName)", maxPtInList,
3967 "[Eventbased] Returns maximum transverse momentum Pt in the given particle List. The unit of the transverse momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3968 REGISTER_METAVARIABLE(
"eclClusterSpecialTrackMatched(cut)", eclClusterTrackMatchedWithCondition,
3969 "Returns if at least one Track that satisfies the given condition is related to the ECLCluster of the Particle.", Manager::VariableDataType::c_double);
3970 REGISTER_METAVARIABLE(
"averageValueInList(particleListName, variable)", averageValueInList,
3971 "[Eventbased] Returns the arithmetic mean of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3972 REGISTER_METAVARIABLE(
"medianValueInList(particleListName, variable)", medianValueInList,
3973 "[Eventbased] Returns the median value of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3974 REGISTER_METAVARIABLE(
"sumValueInList(particleListName, variable)", sumValueInList,
3975 "[Eventbased] Returns the sum of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3976 REGISTER_METAVARIABLE(
"productValueInList(particleListName, variable)", productValueInList,
3977 "[Eventbased] Returns the product of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3978 REGISTER_METAVARIABLE(
"angleToClosestInList(particleListName)", angleToClosestInList,
3979 "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);
3980 REGISTER_METAVARIABLE(
"closestInList(particleListName, variable)", closestInList,
3981 "Returns `variable` for the closest particle (smallest opening angle) in the list provided.", Manager::VariableDataType::c_double);
3982 REGISTER_METAVARIABLE(
"angleToMostB2BInList(particleListName)", angleToMostB2BInList,
3983 "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);
3984 REGISTER_METAVARIABLE(
"deltaPhiToMostB2BPhiInList(particleListName)", deltaPhiToMostB2BPhiInList,
3985 "Returns the abs(delta phi) between this particle and the most back-to-back particle in phi (closest opening angle to 180) in the list provided. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3986 REGISTER_METAVARIABLE(
"mostB2BInList(particleListName, variable)", mostB2BInList,
3987 "Returns `variable` for the most back-to-back particle (closest opening angle to 180) in the list provided.", Manager::VariableDataType::c_double);
3988 REGISTER_METAVARIABLE(
"maxOpeningAngleInList(particleListName)", maxOpeningAngleInList,
3989 "[Eventbased] Returns maximum opening angle in the given particle List. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3990 REGISTER_METAVARIABLE(
"daughterCombination(variable, daughterIndex_1, daughterIndex_2 ... daughterIndex_n)", daughterCombination,R
"DOC(
3991Returns a ``variable`` function only of the 4-momentum calculated on an arbitrary set of (grand)daughters.
3994 ``variable`` can only be a function of the daughters' 4-momenta.
3996Daughters from different generations of the decay tree can be combined using generalized daughter indexes, which are simply colon-separated
3997the list of daughter indexes, starting from the root particle: for example, ``0:1:3`` identifies the fourth
3998daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle.
4001 ``daughterCombination(M, 0, 3, 4)`` will return the invariant mass of the system made of the first, fourth and fifth daughter of particle.
4002 ``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.
4004)DOC", Manager::VariableDataType::c_double);
4005 REGISTER_METAVARIABLE("useAlternativeDaughterHypothesis(variable, daughterIndex_1:newMassHyp_1, ..., daughterIndex_n:newMassHyp_n)", useAlternativeDaughterHypothesis,R
"DOC(
4006Returns a ``variable`` calculated using new mass hypotheses for (some of) the particle's daughters.
4009 ``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.
4010 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.
4011 Also, the track fit is not performed again: the variable only re-calculates the 4-vectors using different mass assumptions.
4012 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).
4015 Generalized daughter indexes are not supported (yet!): this variable can be used only on first-generation daughters.
4018 ``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.
4019 ``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.
4021)DOC", Manager::VariableDataType::c_double);
4022 REGISTER_METAVARIABLE("varForFirstMCAncestorOfType(type, variable)",varForFirstMCAncestorOfType,R
"DOC(Returns requested variable of the first ancestor of the given type.
4023Ancestor type can be set up by PDG code or by particle name (check evt.pdl for valid particle names))DOC", Manager::VariableDataType::c_double);
4025 REGISTER_METAVARIABLE("nTrackFitResults(particleType)", nTrackFitResults,
4026 "[Eventbased] Returns the total number of TrackFitResults for a given particleType. The argument can be the name of particle (e.g. pi+) or PDG code (e.g. 211).",
4027 Manager::VariableDataType::c_int);
4029 REGISTER_METAVARIABLE(
"convertToDaughterIndex(variable)", convertToDaughterIndex, R
"DOC(Converts the variable of the given particle into integer and returns it if it is a valid daughter index, else returns -1.)DOC", Manager::VariableDataType::c_int);
int getPDGCode() const
PDG code.
static const ChargedStable pion
charged pion particle
static const double doubleNaN
quiet_NaN
static const ChargedStable electron
electron particle
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
@ c_nPhotons
CR is split into n photons (N1)
static std::unique_ptr< GeneralCut > compile(const std::string &cut)
@ 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.
EParticleSourceObject
particle source enumerators
@ c_Flavored
Is either particle or antiparticle.
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
#define MAKE_DEPRECATED(name, make_fatal, version, description)
Registers a variable as deprecated.
T convertString(const std::string &str)
Converts a string to type T (one of float, double, long double, int, long int, unsigned long int).
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.