10 #include <analysis/variables/MetaVariables.h>
12 #include <analysis/VariableManager/Utility.h>
13 #include <analysis/dataobjects/EventExtraInfo.h>
14 #include <analysis/dataobjects/Particle.h>
15 #include <analysis/dataobjects/ParticleList.h>
16 #include <analysis/dataobjects/RestOfEvent.h>
17 #include <analysis/utility/PCmsLabTransform.h>
18 #include <analysis/utility/ReferenceFrame.h>
19 #include <analysis/utility/EvtPDLUtil.h>
20 #include <analysis/ClusterUtility/ClusterUtils.h>
21 #include <analysis/variables/VariableFormulaConstructor.h>
23 #include <framework/logging/Logger.h>
24 #include <framework/datastore/StoreArray.h>
25 #include <framework/datastore/StoreObjPtr.h>
26 #include <framework/utilities/Conversion.h>
27 #include <framework/utilities/MakeROOTCompatible.h>
28 #include <framework/gearbox/Const.h>
30 #include <mdst/dataobjects/Track.h>
31 #include <mdst/dataobjects/MCParticle.h>
32 #include <mdst/dataobjects/ECLCluster.h>
33 #include <mdst/dataobjects/TrackFitResult.h>
35 #include <boost/algorithm/string.hpp>
43 #include <TDatabasePDG.h>
44 #include <Math/Vector4D.h>
55 if (arguments.size() == 1) {
57 auto func = [var](
const Particle * particle) ->
double {
58 UseReferenceFrame<RestFrame> frame(particle);
59 double result = std::get<double>(var->function(particle));
64 B2FATAL(
"Wrong number of arguments for meta function useRestFrame");
70 if (arguments.size() == 1) {
72 auto func = [var](
const Particle * particle) ->
double {
73 UseReferenceFrame<CMSFrame> frame;
74 double result = std::get<double>(var->function(particle));
79 B2FATAL(
"Wrong number of arguments for meta function useCMSFrame");
85 if (arguments.size() == 1) {
87 auto func = [var](
const Particle * particle) ->
double {
88 UseReferenceFrame<LabFrame> frame;
89 double result = std::get<double>(var->function(particle));
94 B2FATAL(
"Wrong number of arguments for meta function useLabFrame");
100 if (arguments.size() == 2) {
103 int daughterIndexTagB = 0;
105 daughterIndexTagB = Belle2::convertString<int>(arguments[1]);
106 }
catch (std::invalid_argument&) {
107 B2FATAL(
"Second argument of useTagSideRecoilRestFrame meta function must be integer!");
110 auto func = [var, daughterIndexTagB](
const Particle * particle) ->
double {
111 if (particle->getPDGCode() != 300553)
113 B2ERROR(
"Variable should only be used on a Upsilon(4S) Particle List!");
114 return std::numeric_limits<float>::quiet_NaN();
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();
141 return std::numeric_limits<float>::quiet_NaN();
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();
166 return std::numeric_limits<float>::quiet_NaN();
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() == 1) {
190 auto extraInfoName = arguments[0];
191 auto func = [extraInfoName](
const Particle * particle) ->
double {
192 if (particle ==
nullptr)
194 B2WARNING(
"Returns NaN because the particle is nullptr! If you want EventExtraInfo variables, please use eventExtraInfo() instead");
195 return std::numeric_limits<float>::quiet_NaN();
197 if (particle->hasExtraInfo(extraInfoName))
199 return particle->getExtraInfo(extraInfoName);
202 return std::numeric_limits<float>::quiet_NaN();
207 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
213 if (arguments.size() == 1) {
214 auto extraInfoName = arguments[0];
215 auto func = [extraInfoName](
const Particle*) ->
double {
216 StoreObjPtr<EventExtraInfo> eventExtraInfo;
217 if (not eventExtraInfo.isValid())
218 return std::numeric_limits<float>::quiet_NaN();
219 if (eventExtraInfo->hasExtraInfo(extraInfoName))
221 return eventExtraInfo->getExtraInfo(extraInfoName);
224 return std::numeric_limits<float>::quiet_NaN();
229 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
235 if (arguments.size() == 1) {
238 auto func = [var, key](
const Particle*) ->
double {
240 StoreObjPtr<EventExtraInfo> eventExtraInfo;
241 if (not eventExtraInfo.isValid())
242 eventExtraInfo.create();
243 if (eventExtraInfo->hasExtraInfo(key))
245 return eventExtraInfo->getExtraInfo(key);
248 double value = std::numeric_limits<double>::quiet_NaN();
249 auto var_result = var->function(
nullptr);
250 if (std::holds_alternative<double>(var_result)) {
251 value = std::get<double>(var_result);
252 }
else if (std::holds_alternative<int>(var_result)) {
253 return std::get<int>(var_result);
254 }
else if (std::holds_alternative<bool>(var_result)) {
255 return std::get<bool>(var_result);
257 eventExtraInfo->addExtraInfo(key, value);
263 B2FATAL(
"Wrong number of arguments for meta function eventCached");
269 if (arguments.size() == 1) {
272 auto func = [var, key](
const Particle * particle) ->
double {
274 if (particle->hasExtraInfo(key))
276 return particle->getExtraInfo(key);
279 double value = std::get<double>(var->function(particle));
287 const_cast<Particle*
>(particle)->addExtraInfo(key, value);
293 B2FATAL(
"Wrong number of arguments for meta function particleCached");
302 if (arguments.size() != 1) B2FATAL(
"Wrong number of arguments for meta function formula");
303 FormulaParser<VariableFormulaConstructor> parser;
305 return parser.parse(arguments[0]);
306 }
catch (std::runtime_error& e) {
313 if (arguments.size() <= 1) {
315 std::string cutString;
316 if (arguments.size() == 1)
317 cutString = arguments[0];
319 auto func = [cut](
const Particle*) ->
int {
321 int number_of_tracks = 0;
322 StoreArray<Track> tracks;
323 for (
const auto& track : tracks)
325 const TrackFitResult* trackFit = track.getTrackFitResultWithClosestMass(
Const::pion);
326 if (trackFit->getChargeSign() == 0) {
330 if (cut->check(&particle))
335 return number_of_tracks;
340 B2FATAL(
"Wrong number of arguments for meta function nCleanedTracks");
346 if (arguments.size() <= 1) {
348 std::string cutString;
349 if (arguments.size() == 1)
350 cutString = arguments[0];
352 auto func = [cut](
const Particle*) ->
int {
354 int number_of_clusters = 0;
355 StoreArray<ECLCluster> clusters;
356 for (
const auto& cluster : clusters)
362 Particle particle(&cluster);
363 if (cut->check(&particle))
364 number_of_clusters++;
367 return number_of_clusters;
372 B2FATAL(
"Wrong number of arguments for meta function nCleanedECLClusters");
378 if (arguments.size() == 1) {
379 std::string cutString = arguments[0];
381 auto func = [cut](
const Particle * particle) ->
bool {
382 if (cut->check(particle))
389 B2FATAL(
"Wrong number of arguments for meta function passesCut");
395 if (arguments.size() == 1) {
396 std::string cutString = arguments[0];
398 auto func = [cut](
const Particle*) ->
bool {
399 if (cut->check(
nullptr))
406 B2FATAL(
"Wrong number of arguments for meta function passesEventCut");
412 if (arguments.size() == 2) {
415 pdgCode = Belle2::convertString<int>(arguments[0]);
416 }
catch (std::invalid_argument&) {
417 B2FATAL(
"The first argument of varFor meta function must be a positive integer!");
420 auto func = [pdgCode, var](
const Particle * particle) ->
double {
421 if (std::abs(particle->getPDGCode()) == std::abs(pdgCode))
423 auto var_result = var->function(particle);
424 if (std::holds_alternative<double>(var_result)) {
425 return std::get<double>(var_result);
426 }
else if (std::holds_alternative<int>(var_result)) {
427 return std::get<int>(var_result);
428 }
else if (std::holds_alternative<bool>(var_result)) {
429 return std::get<bool>(var_result);
430 }
else return std::numeric_limits<double>::quiet_NaN();
431 }
else return std::numeric_limits<double>::quiet_NaN();
435 B2FATAL(
"Wrong number of arguments for meta function varFor");
441 if (arguments.size() == 1) {
443 auto func = [var](
const Particle * particle) ->
double {
444 if (particle->getMCParticle())
449 auto var_result = var->function(particle);
450 if (std::holds_alternative<double>(var_result)) {
451 return std::get<double>(var_result);
452 }
else if (std::holds_alternative<int>(var_result)) {
453 return std::get<int>(var_result);
454 }
else if (std::holds_alternative<bool>(var_result)) {
455 return std::get<bool>(var_result);
456 }
else return std::numeric_limits<double>::quiet_NaN();
457 }
else return std::numeric_limits<double>::quiet_NaN();
458 }
else return std::numeric_limits<double>::quiet_NaN();
462 B2FATAL(
"Wrong number of arguments for meta function varForMCGen");
468 if (arguments.size() == 1) {
469 std::string listName = arguments[0];
470 auto func = [listName](
const Particle * particle) ->
int {
473 StoreObjPtr<ParticleList> listOfParticles(listName);
475 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to nParticlesInList");
477 return listOfParticles->getListSize();
482 B2FATAL(
"Wrong number of arguments for meta function nParticlesInList");
489 if (arguments.size() != 1) {
490 B2FATAL(
"Wrong number of arguments for isInList");
492 auto listName = arguments[0];
494 auto func = [listName](
const Particle * particle) ->
bool {
497 StoreObjPtr<ParticleList> list(listName);
498 if (!(list.isValid()))
500 B2FATAL(
"Invalid Listname " << listName <<
" given to isInList");
504 return list->contains(particle);
513 if (arguments.size() != 1) {
514 B2FATAL(
"Wrong number of arguments for sourceObjectIsInList");
516 auto listName = arguments[0];
518 auto func = [listName](
const Particle * particle) ->
int {
521 StoreObjPtr<ParticleList> list(listName);
522 if (!(list.isValid()))
524 B2FATAL(
"Invalid Listname " << listName <<
" given to sourceObjectIsInList");
530 if (particlesource == Particle::EParticleSourceObject::c_Composite
531 or particlesource == Particle::EParticleSourceObject::c_Undefined)
537 for (
unsigned i = 0; i < list->getListSize(); ++i)
539 Particle* iparticle = list->getParticle(i);
540 if (particlesource == iparticle->getParticleSource())
541 if (particle->getMdstArrayIndex() == iparticle->getMdstArrayIndex())
553 if (arguments.size() != 1) {
554 B2FATAL(
"Wrong number of arguments for mcParticleIsInMCList");
556 auto listName = arguments[0];
558 auto func = [listName](
const Particle * particle) ->
bool {
561 StoreObjPtr<ParticleList> list(listName);
562 if (!(list.isValid()))
563 B2FATAL(
"Invalid Listname " << listName <<
" given to mcParticleIsInMCList");
567 if (mcp ==
nullptr)
return false;
570 for (
unsigned i = 0; i < list->getListSize(); ++i)
572 const MCParticle* imcp = list->getParticle(i)->
getMCParticle();
573 if ((imcp !=
nullptr) and (mcp->getArrayIndex() == imcp->getArrayIndex()))
583 B2WARNING(
"isDaughterOfList is outdated and replaced by isDescendantOfList.");
584 std::vector<std::string> new_arguments = arguments;
585 new_arguments.push_back(std::string(
"1"));
586 return isDescendantOfList(new_arguments);
591 B2WARNING(
"isGrandDaughterOfList is outdated and replaced by isDescendantOfList.");
592 std::vector<std::string> new_arguments = arguments;
593 new_arguments.push_back(std::string(
"2"));
594 return isDescendantOfList(new_arguments);
599 if (arguments.size() > 0) {
600 auto listNames = arguments;
601 auto func = [listNames](
const Particle * particle) ->
bool {
603 int generation_flag = -1;
606 generation_flag = Belle2::convertString<int>(listNames.back());
607 }
catch (std::exception& e) {}
609 for (
auto& iListName : listNames)
612 Belle2::convertString<int>(iListName);
614 }
catch (std::exception& e) {}
617 auto list_comparison = [](
auto&&
self,
const Particle * m,
const Particle * p,
int flag)->
bool {
619 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
621 const Particle* daughter = m->getDaughter(i);
622 if ((flag == 1.) or (flag < 0)) {
623 if (p->isCopyOf(daughter)) {
629 if (daughter->getNDaughters() > 0) {
630 result =
self(
self, daughter, p, flag - 1);
640 StoreObjPtr<ParticleList> listOfParticles(iListName);
642 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isDescendantOfList");
644 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
645 Particle* iParticle = listOfParticles->getParticle(i);
646 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
656 B2FATAL(
"Wrong number of arguments for meta function isDescendantOfList");
662 if (arguments.size() > 0) {
663 auto listNames = arguments;
664 auto func = [listNames](
const Particle * particle) ->
bool {
666 int generation_flag = -1;
669 generation_flag = Belle2::convertString<int>(listNames.back());
670 }
catch (std::exception& e) {}
672 if (particle->getMCParticle() ==
nullptr)
677 for (
auto& iListName : listNames)
680 std::stod(iListName);
682 }
catch (std::exception& e) {}
684 auto list_comparison = [](
auto&&
self,
const Particle * m,
const Particle * p,
int flag)->
bool {
686 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
688 const Particle* daughter = m->getDaughter(i);
689 if ((flag == 1.) or (flag < 0)) {
690 if (daughter->getMCParticle() !=
nullptr) {
691 if (p->getMCParticle()->getArrayIndex() == daughter->getMCParticle()->getArrayIndex()) {
697 if (daughter->getNDaughters() > 0) {
698 result =
self(
self, daughter, p, flag - 1);
708 StoreObjPtr<ParticleList> listOfParticles(iListName);
710 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isMCDescendantOfList");
712 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
713 Particle* iParticle = listOfParticles->getParticle(i);
714 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
724 B2FATAL(
"Wrong number of arguments for meta function isMCDescendantOfList");
730 if (arguments.size() == 1) {
732 auto func = [var](
const Particle * particle) ->
double {
733 double product = 1.0;
734 if (particle->getNDaughters() == 0)
736 return std::numeric_limits<double>::quiet_NaN();
738 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
740 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
741 product *= std::get<double>(var->function(particle->getDaughter(j)));
743 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
745 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
746 product *= std::get<int>(var->function(particle->getDaughter(j)));
748 }
else return std::numeric_limits<double>::quiet_NaN();
753 B2FATAL(
"Wrong number of arguments for meta function daughterProductOf");
759 if (arguments.size() == 1) {
761 auto func = [var](
const Particle * particle) ->
double {
763 if (particle->getNDaughters() == 0)
765 return std::numeric_limits<double>::quiet_NaN();
767 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
769 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
770 sum += std::get<double>(var->function(particle->getDaughter(j)));
772 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
774 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
775 sum += std::get<int>(var->function(particle->getDaughter(j)));
777 }
else return std::numeric_limits<double>::quiet_NaN();
782 B2FATAL(
"Wrong number of arguments for meta function daughterSumOf");
788 if (arguments.size() == 1) {
790 auto func = [var](
const Particle * particle) ->
double {
791 double min = std::numeric_limits<double>::quiet_NaN();
792 if (particle->getNDaughters() == 0)
794 return std::numeric_limits<double>::quiet_NaN();
796 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
798 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
799 double iValue = std::get<double>(var->function(particle->getDaughter(j)));
800 if (std::isnan(iValue))
continue;
801 if (std::isnan(min)) min = iValue;
802 if (iValue < min) min = iValue;
804 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
806 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
807 int iValue = std::get<int>(var->function(particle->getDaughter(j)));
808 if (std::isnan(min)) min = iValue;
809 if (iValue < min) min = iValue;
816 B2FATAL(
"Wrong number of arguments for meta function daughterLowest");
822 if (arguments.size() == 1) {
824 auto func = [var](
const Particle * particle) ->
double {
825 double max = std::numeric_limits<double>::quiet_NaN();
826 if (particle->getNDaughters() == 0)
828 return std::numeric_limits<double>::quiet_NaN();
830 if (std::holds_alternative<double>(var->function(particle->getDaughter(0))))
832 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
833 double iValue = std::get<double>(var->function(particle->getDaughter(j)));
834 if (std::isnan(iValue))
continue;
835 if (std::isnan(max)) max = iValue;
836 if (iValue > max) max = iValue;
838 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(0))))
840 for (
unsigned j = 0; j < particle->getNDaughters(); ++j) {
841 int iValue = std::get<int>(var->function(particle->getDaughter(j)));
842 if (std::isnan(max)) max = iValue;
843 if (iValue > max) max = iValue;
850 B2FATAL(
"Wrong number of arguments for meta function daughterHighest");
856 if (arguments.size() == 3) {
857 int iDaughterNumber = 0;
858 int jDaughterNumber = 0;
860 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
861 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
862 }
catch (std::invalid_argument&) {
863 B2FATAL(
"First two arguments of daughterDiffOf meta function must be integers!");
865 auto variablename = arguments[2];
866 auto func = [variablename, iDaughterNumber, jDaughterNumber](
const Particle * particle) ->
double {
867 if (particle ==
nullptr)
868 return std::numeric_limits<double>::quiet_NaN();
869 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
870 return std::numeric_limits<double>::quiet_NaN();
874 auto result_j = var->function(particle->getDaughter(jDaughterNumber));
875 auto result_i = var->function(particle->getDaughter(iDaughterNumber));
876 double diff = std::numeric_limits<double>::quiet_NaN();
877 if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i)) {
878 diff = std::get<double>(result_j) - std::get<double>(result_i);
879 }
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i)) {
880 diff = std::get<int>(result_j) - std::get<int>(result_i);
882 throw std::runtime_error(
"Bad variant access");
884 if (variablename ==
"phi" or variablename ==
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))
885 or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)"))) {
886 if (fabs(diff) > M_PI) {
888 diff = diff - 2 * M_PI;
890 diff = 2 * M_PI + diff;
899 B2FATAL(
"Wrong number of arguments for meta function daughterDiffOf");
905 if (arguments.size() == 3) {
906 int iDaughterNumber = 0;
907 int jDaughterNumber = 0;
909 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
910 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
911 }
catch (std::invalid_argument&) {
912 B2FATAL(
"First two arguments of mcDaughterDiffOf meta function must be integers!");
914 auto variablename = arguments[2];
915 auto func = [variablename, iDaughterNumber, jDaughterNumber](
const Particle * particle) ->
double {
916 if (particle ==
nullptr)
917 return std::numeric_limits<double>::quiet_NaN();
918 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
919 return std::numeric_limits<double>::quiet_NaN();
920 if (particle->getDaughter(jDaughterNumber)->getMCParticle() ==
nullptr || particle->getDaughter(iDaughterNumber)->getMCParticle() ==
nullptr)
921 return std::numeric_limits<double>::quiet_NaN();
926 Particle iTmpPart(iMcDaughter);
927 Particle jTmpPart(jMcDaughter);
929 auto result_j = var->function(&jTmpPart);
930 auto result_i = var->function(&iTmpPart);
931 double diff = std::numeric_limits<double>::quiet_NaN();
932 if (std::holds_alternative<double>(result_j) && std::holds_alternative<double>(result_i)) {
933 diff = std::get<double>(result_j) - std::get<double>(result_i);
934 }
else if (std::holds_alternative<int>(result_j) && std::holds_alternative<int>(result_i)) {
935 diff = std::get<int>(result_j) - std::get<int>(result_i);
937 throw std::runtime_error(
"Bad variant access");
939 if (variablename ==
"phi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))) {
940 if (fabs(diff) > M_PI) {
942 diff = diff - 2 * M_PI;
944 diff = 2 * M_PI + diff;
953 B2FATAL(
"Wrong number of arguments for meta function mcDaughterDiffOf");
959 if (arguments.size() == 5) {
960 int iDaughterNumber = 0, jDaughterNumber = 0, agrandDaughterNumber = 0, bgrandDaughterNumber = 0;
962 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
963 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
964 agrandDaughterNumber = Belle2::convertString<int>(arguments[2]);
965 bgrandDaughterNumber = Belle2::convertString<int>(arguments[3]);
966 }
catch (std::invalid_argument&) {
967 B2FATAL(
"First four arguments of grandDaughterDiffOf meta function must be integers!");
969 auto variablename = arguments[4];
970 auto func = [variablename, iDaughterNumber, jDaughterNumber, agrandDaughterNumber,
971 bgrandDaughterNumber](
const Particle * particle) ->
double {
972 if (particle ==
nullptr)
973 return std::numeric_limits<double>::quiet_NaN();
974 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
975 return std::numeric_limits<double>::quiet_NaN();
976 if (agrandDaughterNumber >=
int((particle->getDaughter(iDaughterNumber))->getNDaughters()) || bgrandDaughterNumber >=
int((particle->getDaughter(jDaughterNumber))->getNDaughters()))
977 return std::numeric_limits<double>::quiet_NaN();
981 double diff = std::get<double>(var->function((particle->getDaughter(jDaughterNumber))->getDaughter(
982 bgrandDaughterNumber))) - std::get<double>(var->function((particle->getDaughter(iDaughterNumber))->getDaughter(
983 agrandDaughterNumber)));
984 if (variablename ==
"phi" or variablename ==
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)"))
985 or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)"))) {
986 if (fabs(diff) > M_PI) {
988 diff = diff - 2 * M_PI;
990 diff = 2 * M_PI + diff;
999 B2FATAL(
"Wrong number of arguments for meta function grandDaughterDiffOf");
1005 std::vector<std::string> new_arguments = arguments;
1006 new_arguments.push_back(std::string(
"phi"));
1007 return daughterDiffOf(new_arguments);
1012 std::vector<std::string> new_arguments = arguments;
1013 new_arguments.push_back(std::string(
"phi"));
1014 return mcDaughterDiffOf(new_arguments);
1019 std::vector<std::string> new_arguments = arguments;
1020 new_arguments.push_back(std::string(
"phi"));
1021 return grandDaughterDiffOf(new_arguments);
1026 std::vector<std::string> new_arguments = arguments;
1027 new_arguments.push_back(std::string(
"clusterPhi"));
1028 return daughterDiffOf(new_arguments);
1033 std::vector<std::string> new_arguments = arguments;
1034 new_arguments.push_back(std::string(
"clusterPhi"));
1035 return grandDaughterDiffOf(new_arguments);
1040 std::vector<std::string> new_arguments = arguments;
1041 new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
1042 return daughterDiffOf(new_arguments);
1047 std::vector<std::string> new_arguments = arguments;
1048 new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
1049 return mcDaughterDiffOf(new_arguments);
1054 std::vector<std::string> new_arguments = arguments;
1055 new_arguments.push_back(std::string(
"useCMSFrame(clusterPhi)"));
1056 return daughterDiffOf(new_arguments);
1061 if (arguments.size() == 3) {
1062 int iDaughterNumber = 0;
1063 int jDaughterNumber = 0;
1065 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
1066 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
1067 }
catch (std::invalid_argument&) {
1068 B2FATAL(
"First two arguments of daughterDiffOf meta function must be integers!");
1071 auto func = [var, iDaughterNumber, jDaughterNumber](
const Particle * particle) ->
double {
1072 if (particle ==
nullptr)
1073 return std::numeric_limits<double>::quiet_NaN();
1074 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
1075 return std::numeric_limits<double>::quiet_NaN();
1078 double iValue, jValue;
1079 if (std::holds_alternative<double>(var->function(particle->getDaughter(jDaughterNumber)))) {
1080 iValue = std::get<double>(var->function(particle->getDaughter(iDaughterNumber)));
1081 jValue = std::get<double>(var->function(particle->getDaughter(jDaughterNumber)));
1082 }
else if (std::holds_alternative<int>(var->function(particle->getDaughter(jDaughterNumber)))) {
1083 iValue = std::get<int>(var->function(particle->getDaughter(iDaughterNumber)));
1084 jValue = std::get<int>(var->function(particle->getDaughter(jDaughterNumber)));
1085 }
else return std::numeric_limits<double>::quiet_NaN();
1086 return (jValue - iValue) / (jValue + iValue);
1091 B2FATAL(
"Wrong number of arguments for meta function daughterNormDiffOf");
1097 if (arguments.size() == 2) {
1098 int daughterNumber = 0;
1100 daughterNumber = Belle2::convertString<int>(arguments[0]);
1101 }
catch (std::invalid_argument&) {
1102 B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
1104 auto variablename = arguments[1];
1105 auto func = [variablename, daughterNumber](
const Particle * particle) ->
double {
1106 if (particle ==
nullptr)
1107 return std::numeric_limits<double>::quiet_NaN();
1108 if (daughterNumber >=
int(particle->getNDaughters()))
1109 return std::numeric_limits<double>::quiet_NaN();
1113 auto result_mother = var->function(particle);
1114 auto result_daughter = var->function(particle->getDaughter(daughterNumber));
1115 double diff = std::numeric_limits<double>::quiet_NaN();
1116 if (std::holds_alternative<double>(result_mother) && std::holds_alternative<double>(result_daughter)) {
1117 diff = std::get<double>(result_mother) - std::get<double>(result_daughter);
1118 }
else if (std::holds_alternative<int>(result_mother) && std::holds_alternative<int>(result_daughter)) {
1119 diff = std::get<int>(result_mother) - std::get<int>(result_daughter);
1121 throw std::runtime_error(
"Bad variant access");
1124 if (variablename ==
"phi" or variablename ==
"useCMSFrame(phi)") {
1125 if (fabs(diff) > M_PI) {
1127 diff = diff - 2 * M_PI;
1129 diff = 2 * M_PI + diff;
1138 B2FATAL(
"Wrong number of arguments for meta function daughterMotherDiffOf");
1144 if (arguments.size() == 2) {
1145 int daughterNumber = 0;
1147 daughterNumber = Belle2::convertString<int>(arguments[0]);
1148 }
catch (std::invalid_argument&) {
1149 B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
1152 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1153 if (particle ==
nullptr)
1154 return std::numeric_limits<double>::quiet_NaN();
1155 if (daughterNumber >=
int(particle->getNDaughters()))
1156 return std::numeric_limits<double>::quiet_NaN();
1159 double daughterValue = 0.0, motherValue = 0.0;
1160 if (std::holds_alternative<double>(var->function(particle))) {
1161 daughterValue = std::get<double>(var->function(particle->getDaughter(daughterNumber)));
1162 motherValue = std::get<double>(var->function(particle));
1163 }
else if (std::holds_alternative<int>(var->function(particle))) {
1164 daughterValue = std::get<int>(var->function(particle->getDaughter(daughterNumber)));
1165 motherValue = std::get<int>(var->function(particle));
1167 return (motherValue - daughterValue) / (motherValue + daughterValue);
1172 B2FATAL(
"Wrong number of arguments for meta function daughterMotherNormDiffOf");
1178 if (arguments.size() == 2 || arguments.size() == 3) {
1180 auto func = [arguments](
const Particle * particle) ->
double {
1181 if (particle ==
nullptr)
1182 return std::numeric_limits<double>::quiet_NaN();
1184 std::vector<ROOT::Math::PxPyPzEVector> pDaus;
1188 for (
auto& generalizedIndex : arguments)
1190 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1192 pDaus.push_back(frame.getMomentum(dauPart));
1194 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
1195 return std::numeric_limits<double>::quiet_NaN();
1200 if (pDaus.size() == 2)
1207 B2FATAL(
"Wrong number of arguments for meta function daughterAngle");
1211 double grandDaughterDecayAngle(
const Particle* particle,
const std::vector<double>& arguments)
1213 if (arguments.size() == 2) {
1216 return std::numeric_limits<double>::quiet_NaN();
1218 int daughterIndex = std::lround(arguments[0]);
1219 if (daughterIndex >=
int(particle->getNDaughters()))
1220 return std::numeric_limits<float>::quiet_NaN();
1221 const Particle* dau = particle->getDaughter(daughterIndex);
1223 int grandDaughterIndex = std::lround(arguments[1]);
1224 if (grandDaughterIndex >=
int(dau->getNDaughters()))
1225 return std::numeric_limits<float>::quiet_NaN();
1227 B2Vector3D boost = dau->get4Vector().BoostToCM();
1229 ROOT::Math::PxPyPzEVector motherMomentum = - particle->get4Vector();
1230 motherMomentum = ROOT::Math::Boost(boost) * motherMomentum;
1232 ROOT::Math::PxPyPzEVector grandDaughterMomentum = dau->getDaughter(grandDaughterIndex)->get4Vector();
1233 grandDaughterMomentum = ROOT::Math::Boost(boost) * grandDaughterMomentum;
1238 B2FATAL(
"The variable grandDaughterDecayAngle needs exactly two integers as arguments!");
1244 if (arguments.size() == 2 || arguments.size() == 3) {
1246 auto func = [arguments](
const Particle * particle) ->
double {
1247 if (particle ==
nullptr)
1248 return std::numeric_limits<double>::quiet_NaN();
1250 std::vector<ROOT::Math::PxPyPzEVector> pDaus;
1254 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_MCParticle)
1256 for (
auto& generalizedIndex : arguments) {
1258 if (mcPart ==
nullptr)
1259 return std::numeric_limits<double>::quiet_NaN();
1261 if (dauMcPart ==
nullptr)
1262 return std::numeric_limits<double>::quiet_NaN();
1264 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1268 for (
auto& generalizedIndex : arguments) {
1269 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1270 if (dauPart ==
nullptr)
1271 return std::numeric_limits<double>::quiet_NaN();
1274 if (dauMcPart ==
nullptr)
1275 return std::numeric_limits<double>::quiet_NaN();
1277 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1282 if (pDaus.size() == 2)
1289 B2FATAL(
"Wrong number of arguments for meta function mcDaughterAngle");
1293 double daughterClusterAngleInBetween(
const Particle* particle,
const std::vector<double>& daughterIndices)
1295 if (daughterIndices.size() == 2) {
1296 int daughterIndexi = std::lround(daughterIndices[0]);
1297 int daughterIndexj = std::lround(daughterIndices[1]);
1298 if (std::max(daughterIndexi, daughterIndexj) >=
int(particle->getNDaughters())) {
1299 return std::numeric_limits<double>::quiet_NaN();
1301 const ECLCluster* clusteri = particle->getDaughter(daughterIndexi)->getECLCluster();
1302 const ECLCluster* clusterj = particle->getDaughter(daughterIndexj)->getECLCluster();
1303 if (clusteri and clusterj) {
1307 ClusterUtils clusutils;
1308 B2Vector3D pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
1309 B2Vector3D pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
1310 return pi.Angle(pj);
1312 return std::numeric_limits<float>::quiet_NaN();
1314 }
else if (daughterIndices.size() == 3) {
1315 int daughterIndexi = std::lround(daughterIndices[0]);
1316 int daughterIndexj = std::lround(daughterIndices[1]);
1317 int daughterIndexk = std::lround(daughterIndices[2]);
1318 if (std::max(std::max(daughterIndexi, daughterIndexj), daughterIndexk) >=
int(particle->getNDaughters())) {
1319 return std::numeric_limits<double>::quiet_NaN();
1321 const ECLCluster* clusteri = (particle->getDaughter(daughterIndices[0]))->getECLCluster();
1322 const ECLCluster* clusterj = (particle->getDaughter(daughterIndices[1]))->getECLCluster();
1323 const ECLCluster* clusterk = (particle->getDaughter(daughterIndices[2]))->getECLCluster();
1324 if (clusteri and clusterj and clusterk) {
1329 ClusterUtils clusutils;
1330 B2Vector3D pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
1331 B2Vector3D pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
1332 B2Vector3D pk = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterk, clusterkBit)).Vect();
1333 return pk.
Angle(pi + pj);
1335 return std::numeric_limits<float>::quiet_NaN();
1338 B2FATAL(
"Wrong number of arguments for daughterClusterAngleInBetween!");
1344 if (arguments.size() > 1) {
1345 auto func = [arguments](
const Particle * particle) ->
double {
1347 ROOT::Math::PxPyPzEVector pSum;
1349 for (
auto& generalizedIndex : arguments)
1351 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1353 pSum += frame.getMomentum(dauPart);
1355 return std::numeric_limits<float>::quiet_NaN();
1362 B2FATAL(
"Wrong number of arguments for meta function daughterInvM. At least two integers are needed.");
1368 if (arguments.size() == 2) {
1372 divideBy = Belle2::convertString<int>(arguments[1]);
1373 }
catch (std::invalid_argument&) {
1374 B2FATAL(
"Second argument of modulo meta function must be integer!");
1376 auto func = [var, divideBy](
const Particle * particle) ->
int {
1377 auto var_result = var->function(particle);
1378 if (std::holds_alternative<double>(var_result))
1380 return int(std::get<double>(var_result)) % divideBy;
1381 }
else if (std::holds_alternative<int>(var_result))
1383 return std::get<int>(var_result) % divideBy;
1384 }
else if (std::holds_alternative<bool>(var_result))
1386 return int(std::get<bool>(var_result)) % divideBy;
1391 B2FATAL(
"Wrong number of arguments for meta function modulo");
1397 if (arguments.size() == 1) {
1400 auto func = [var](
const Particle * particle) ->
bool {
return std::isnan(std::get<double>(var->function(particle))); };
1403 B2FATAL(
"Wrong number of arguments for meta function isNAN");
1409 if (arguments.size() == 2) {
1411 double defaultOutput;
1413 defaultOutput = Belle2::convertString<double>(arguments[1]);
1414 }
catch (std::invalid_argument&) {
1415 B2FATAL(
"The second argument of ifNANgiveX meta function must be a number!");
1417 auto func = [var, defaultOutput](
const Particle * particle) ->
double {
1418 double output = std::get<double>(var->function(particle));
1419 if (std::isnan(output))
return defaultOutput;
1424 B2FATAL(
"Wrong number of arguments for meta function ifNANgiveX");
1430 if (arguments.size() == 1) {
1433 auto func = [var](
const Particle * particle) ->
bool {
return std::isinf(std::get<double>(var->function(particle))); };
1436 B2FATAL(
"Wrong number of arguments for meta function isInfinity");
1442 if (arguments.size() >= 2) {
1448 for (
size_t i = 1; i < arguments.size(); ++i) {
1450 finalMask |= Belle2::convertString<int>(arguments[i]);
1451 }
catch (std::invalid_argument&) {
1452 B2FATAL(
"The input flags to meta function unmask() should be integer!");
1458 auto func = [var, finalMask](
const Particle * particle) ->
double {
1460 auto var_result = var->function(particle);
1461 if (std::holds_alternative<double>(var_result))
1464 if (std::isnan(std::get<double>(var_result))) {
1465 return std::numeric_limits<double>::quiet_NaN();
1467 value = int(std::get<double>(var_result));
1468 }
else if (std::holds_alternative<int>(var_result))
1470 value = std::get<int>(var_result);
1474 value &= (~finalMask);
1481 B2FATAL(
"Meta function unmask needs at least two arguments!");
1487 if (arguments.size() == 3) {
1489 std::string cutString = arguments[0];
1495 auto func = [cut, variableIfTrue, variableIfFalse](
const Particle * particle) ->
double {
1496 if (particle ==
nullptr)
1497 return std::numeric_limits<float>::quiet_NaN();
1498 if (cut->check(particle))
1500 auto var_result = variableIfTrue->function(particle);
1501 if (std::holds_alternative<double>(var_result)) {
1502 return std::get<double>(var_result);
1503 }
else if (std::holds_alternative<int>(var_result)) {
1504 return std::get<int>(var_result);
1505 }
else if (std::holds_alternative<bool>(var_result)) {
1506 return std::get<bool>(var_result);
1507 }
else return std::numeric_limits<double>::quiet_NaN();
1510 auto var_result = variableIfFalse->function(particle);
1511 if (std::holds_alternative<double>(var_result)) {
1512 return std::get<double>(var_result);
1513 }
else if (std::holds_alternative<int>(var_result)) {
1514 return std::get<int>(var_result);
1515 }
else if (std::holds_alternative<bool>(var_result)) {
1516 return std::get<bool>(var_result);
1517 }
else return std::numeric_limits<double>::quiet_NaN();
1523 B2FATAL(
"Wrong number of arguments for meta function conditionalVariableSelector");
1529 if (arguments.size() > 0) {
1530 std::vector<const Variable::Manager::Var*> variables;
1531 for (
auto& argument : arguments)
1534 auto func = [variables, arguments](
const Particle * particle) ->
double {
1535 double pValueProduct = 1.;
1536 for (
auto variable : variables)
1538 double pValue = std::get<double>(variable->function(particle));
1542 pValueProduct *= pValue;
1544 double pValueSum = 1.;
1545 double factorial = 1.;
1546 for (
unsigned int i = 1; i < arguments.size(); ++i)
1549 pValueSum += pow(-std::log(pValueProduct), i) / factorial;
1551 return pValueProduct * pValueSum;
1555 B2FATAL(
"Wrong number of arguments for meta function pValueCombination");
1561 if (arguments.size() == 1) {
1563 auto func = [var](
const Particle * particle) ->
double {
1564 auto var_result = var->function(particle);
1565 if (std::holds_alternative<double>(var_result))
1567 return std::abs(std::get<double>(var_result));
1568 }
else if (std::holds_alternative<int>(var_result))
1570 return std::abs(std::get<int>(var_result));
1571 }
else return std::numeric_limits<double>::quiet_NaN();
1575 B2FATAL(
"Wrong number of arguments for meta function abs");
1581 if (arguments.size() == 2) {
1586 B2FATAL(
"One or both of the used variables doesn't exist!");
1588 auto func = [var1, var2](
const Particle * particle) ->
double {
1590 auto var_result1 = var1->function(particle);
1591 auto var_result2 = var2->function(particle);
1592 if (std::holds_alternative<double>(var_result1))
1594 val1 = std::get<double>(var_result1);
1595 }
else if (std::holds_alternative<int>(var_result1))
1597 val1 = std::get<int>(var_result1);
1599 if (std::holds_alternative<double>(var_result2))
1601 val2 = std::get<double>(var_result2);
1602 }
else if (std::holds_alternative<int>(var_result2))
1604 val2 = std::get<int>(var_result2);
1606 return std::max(val1, val2);
1610 B2FATAL(
"Wrong number of arguments for meta function max");
1616 if (arguments.size() == 2) {
1621 B2FATAL(
"One or both of the used variables doesn't exist!");
1623 auto func = [var1, var2](
const Particle * particle) ->
double {
1625 auto var_result1 = var1->function(particle);
1626 auto var_result2 = var2->function(particle);
1627 if (std::holds_alternative<double>(var_result1))
1629 val1 = std::get<double>(var_result1);
1630 }
else if (std::holds_alternative<int>(var_result1))
1632 val1 = std::get<int>(var_result1);
1634 if (std::holds_alternative<double>(var_result2))
1636 val2 = std::get<double>(var_result2);
1637 }
else if (std::holds_alternative<int>(var_result2))
1639 val2 = std::get<int>(var_result2);
1641 return std::min(val1, val2);
1645 B2FATAL(
"Wrong number of arguments for meta function min");
1651 if (arguments.size() == 1) {
1653 auto func = [var](
const Particle * particle) ->
double {
1654 auto var_result = var->function(particle);
1655 if (std::holds_alternative<double>(var_result))
1656 return std::sin(std::get<double>(var_result));
1657 else if (std::holds_alternative<int>(var_result))
1658 return std::sin(std::get<int>(var_result));
1659 else return std::numeric_limits<double>::quiet_NaN();
1663 B2FATAL(
"Wrong number of arguments for meta function sin");
1669 if (arguments.size() == 1) {
1671 auto func = [var](
const Particle * particle) ->
double {
1672 auto var_result = var->function(particle);
1673 if (std::holds_alternative<double>(var_result))
1674 return std::asin(std::get<double>(var_result));
1675 else if (std::holds_alternative<int>(var_result))
1676 return std::asin(std::get<int>(var_result));
1677 else return std::numeric_limits<double>::quiet_NaN();
1681 B2FATAL(
"Wrong number of arguments for meta function asin");
1687 if (arguments.size() == 1) {
1689 auto func = [var](
const Particle * particle) ->
double {
1690 auto var_result = var->function(particle);
1691 if (std::holds_alternative<double>(var_result))
1692 return std::cos(std::get<double>(var_result));
1693 else if (std::holds_alternative<int>(var_result))
1694 return std::cos(std::get<int>(var_result));
1695 else return std::numeric_limits<double>::quiet_NaN();
1699 B2FATAL(
"Wrong number of arguments for meta function cos");
1705 if (arguments.size() == 1) {
1707 auto func = [var](
const Particle * particle) ->
double {
1708 auto var_result = var->function(particle);
1709 if (std::holds_alternative<double>(var_result))
1710 return std::acos(std::get<double>(var_result));
1711 else if (std::holds_alternative<int>(var_result))
1712 return std::acos(std::get<int>(var_result));
1713 else return std::numeric_limits<double>::quiet_NaN();
1717 B2FATAL(
"Wrong number of arguments for meta function acos");
1723 if (arguments.size() == 1) {
1725 auto func = [var](
const Particle * particle) ->
double {
return std::tan(std::get<double>(var->function(particle))); };
1728 B2FATAL(
"Wrong number of arguments for meta function tan");
1734 if (arguments.size() == 1) {
1736 auto func = [var](
const Particle * particle) ->
double {
return std::atan(std::get<double>(var->function(particle))); };
1739 B2FATAL(
"Wrong number of arguments for meta function atan");
1745 if (arguments.size() == 1) {
1747 auto func = [var](
const Particle * particle) ->
double {
1748 auto var_result = var->function(particle);
1749 if (std::holds_alternative<double>(var_result))
1750 return std::exp(std::get<double>(var_result));
1751 else if (std::holds_alternative<int>(var_result))
1752 return std::exp(std::get<int>(var_result));
1753 else return std::numeric_limits<double>::quiet_NaN();
1757 B2FATAL(
"Wrong number of arguments for meta function exp");
1763 if (arguments.size() == 1) {
1765 auto func = [var](
const Particle * particle) ->
double {
1766 auto var_result = var->function(particle);
1767 if (std::holds_alternative<double>(var_result))
1768 return std::log(std::get<double>(var_result));
1769 else if (std::holds_alternative<int>(var_result))
1770 return std::log(std::get<int>(var_result));
1771 else return std::numeric_limits<double>::quiet_NaN();
1775 B2FATAL(
"Wrong number of arguments for meta function log");
1781 if (arguments.size() == 1) {
1783 auto func = [var](
const Particle * particle) ->
double {
1784 auto var_result = var->function(particle);
1785 if (std::holds_alternative<double>(var_result))
1786 return std::log10(std::get<double>(var_result));
1787 else if (std::holds_alternative<int>(var_result))
1788 return std::log10(std::get<int>(var_result));
1789 else return std::numeric_limits<double>::quiet_NaN();
1793 B2FATAL(
"Wrong number of arguments for meta function log10");
1799 if (arguments.size() == 2) {
1800 int daughterNumber = 0;
1802 daughterNumber = Belle2::convertString<int>(arguments[0]);
1803 }
catch (std::invalid_argument&) {
1804 B2FATAL(
"First argument of daughter meta function must be integer!");
1807 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1808 if (particle ==
nullptr)
1809 return std::numeric_limits<float>::quiet_NaN();
1810 if (daughterNumber >=
int(particle->getNDaughters()))
1811 return std::numeric_limits<float>::quiet_NaN();
1814 auto var_result = var->function(particle->getDaughter(daughterNumber));
1815 if (std::holds_alternative<double>(var_result)) {
1816 return std::get<double>(var_result);
1817 }
else if (std::holds_alternative<int>(var_result)) {
1818 return std::get<int>(var_result);
1819 }
else if (std::holds_alternative<bool>(var_result)) {
1820 return std::get<bool>(var_result);
1821 }
else return std::numeric_limits<double>::quiet_NaN();
1826 B2FATAL(
"Wrong number of arguments for meta function daughter");
1832 if (arguments.size() == 2) {
1833 int daughterNumber = 0;
1835 daughterNumber = Belle2::convertString<int>(arguments[0]);
1836 }
catch (std::invalid_argument&) {
1837 B2FATAL(
"First argument of mcDaughter meta function must be integer!");
1840 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1841 if (particle ==
nullptr)
1842 return std::numeric_limits<float>::quiet_NaN();
1843 if (particle->getMCParticle())
1845 if (daughterNumber >=
int(particle->getMCParticle()->getNDaughters())) {
1846 return std::numeric_limits<float>::quiet_NaN();
1848 Particle tempParticle = Particle(particle->getMCParticle()->getDaughters().at(daughterNumber));
1849 auto var_result = var->function(&tempParticle);
1850 if (std::holds_alternative<double>(var_result)) {
1851 return std::get<double>(var_result);
1852 }
else if (std::holds_alternative<int>(var_result)) {
1853 return std::get<int>(var_result);
1854 }
else if (std::holds_alternative<bool>(var_result)) {
1855 return std::get<bool>(var_result);
1856 }
else return std::numeric_limits<double>::quiet_NaN();
1859 return std::numeric_limits<float>::quiet_NaN();
1864 B2FATAL(
"Wrong number of arguments for meta function mcDaughter");
1870 if (arguments.size() == 1) {
1872 auto func = [var](
const Particle * particle) ->
double {
1873 if (particle ==
nullptr)
1874 return std::numeric_limits<float>::quiet_NaN();
1875 if (particle->getMCParticle())
1877 if (particle->getMCParticle()->getMother() ==
nullptr) {
1878 return std::numeric_limits<float>::quiet_NaN();
1880 Particle tempParticle = Particle(particle->getMCParticle()->getMother());
1881 auto var_result = var->function(&tempParticle);
1882 if (std::holds_alternative<double>(var_result)) {
1883 return std::get<double>(var_result);
1884 }
else if (std::holds_alternative<int>(var_result)) {
1885 return std::get<int>(var_result);
1886 }
else if (std::holds_alternative<bool>(var_result)) {
1887 return std::get<bool>(var_result);
1888 }
else return std::numeric_limits<double>::quiet_NaN();
1891 return std::numeric_limits<float>::quiet_NaN();
1896 B2FATAL(
"Wrong number of arguments for meta function mcMother");
1902 if (arguments.size() == 2) {
1903 int particleNumber = 0;
1905 particleNumber = Belle2::convertString<int>(arguments[0]);
1906 }
catch (std::invalid_argument&) {
1907 B2FATAL(
"First argument of genParticle meta function must be integer!");
1911 auto func = [var, particleNumber](
const Particle*) ->
double {
1912 StoreArray<MCParticle> mcParticles(
"MCParticles");
1913 if (particleNumber >= mcParticles.getEntries())
1915 return std::numeric_limits<float>::quiet_NaN();
1918 MCParticle* mcParticle = mcParticles[particleNumber];
1919 Particle part = Particle(mcParticle);
1920 auto var_result = var->function(&part);
1921 if (std::holds_alternative<double>(var_result))
1923 return std::get<double>(var_result);
1924 }
else if (std::holds_alternative<int>(var_result))
1926 return std::get<int>(var_result);
1927 }
else if (std::holds_alternative<bool>(var_result))
1929 return std::get<bool>(var_result);
1930 }
else return std::numeric_limits<double>::quiet_NaN();
1934 B2FATAL(
"Wrong number of arguments for meta function genParticle");
1940 if (arguments.size() == 1) {
1943 auto func = [var](
const Particle*) ->
double {
1944 StoreArray<MCParticle> mcParticles(
"MCParticles");
1945 if (mcParticles.getEntries() == 0)
1947 return std::numeric_limits<float>::quiet_NaN();
1950 MCParticle* mcUpsilon4S = mcParticles[0];
1951 if (mcUpsilon4S->getPDG() != 300553)
1953 return std::numeric_limits<float>::quiet_NaN();
1956 Particle upsilon4S = Particle(mcUpsilon4S);
1957 auto var_result = var->function(&upsilon4S);
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);
1967 }
else return std::numeric_limits<double>::quiet_NaN();
1971 B2FATAL(
"Wrong number of arguments for meta function genUpsilon4S");
1977 if (arguments.size() == 4) {
1978 std::string listName = arguments[0];
1979 std::string rankedVariableName = arguments[1];
1980 std::string returnVariableName = arguments[2];
1981 std::string extraInfoName = rankedVariableName +
"_rank";
1984 rank = Belle2::convertString<int>(arguments[3]);
1985 }
catch (std::invalid_argument&) {
1986 B2ERROR(
"3rd argument of getVariableByRank meta function (Rank) must be an integer!");
1991 auto func = [var, rank, extraInfoName, listName](
const Particle*)->
double {
1992 StoreObjPtr<ParticleList> list(listName);
1994 const unsigned int numParticles = list->getListSize();
1995 for (
unsigned int i = 0; i < numParticles; i++)
1997 const Particle* p = list->getParticle(i);
1998 if (p->getExtraInfo(extraInfoName) == rank) {
1999 auto var_result = var->function(p);
2000 if (std::holds_alternative<double>(var_result)) {
2001 return std::get<double>(var_result);
2002 }
else if (std::holds_alternative<int>(var_result)) {
2003 return std::get<int>(var_result);
2004 }
else if (std::holds_alternative<bool>(var_result)) {
2005 return std::get<bool>(var_result);
2006 }
else return std::numeric_limits<double>::quiet_NaN();
2010 return std::numeric_limits<double>::signaling_NaN();
2014 B2FATAL(
"Wrong number of arguments for meta function getVariableByRank");
2020 if (arguments.size() == 1 or arguments.size() == 2) {
2022 std::string listName = arguments[0];
2023 std::string cutString =
"";
2025 if (arguments.size() == 2) {
2026 cutString = arguments[1];
2031 auto func = [listName, cut](
const Particle*) ->
int {
2033 StoreObjPtr<ParticleList> list(listName);
2035 for (
unsigned int i = 0; i < list->getListSize(); i++)
2037 const Particle* particle = list->getParticle(i);
2038 if (cut->check(particle)) {
2046 B2FATAL(
"Wrong number of arguments for meta function countInList");
2052 if (arguments.size() == 2 or arguments.size() == 3) {
2054 std::string roeListName = arguments[0];
2055 std::string cutString = arguments[1];
2057 if (arguments.size() == 2) {
2058 B2INFO(
"Use pdgCode of electron as default in meta variable veto, other arguments: " << roeListName <<
", " << cutString);
2061 pdgCode = Belle2::convertString<int>(arguments[2]);;
2062 }
catch (std::invalid_argument&) {
2063 B2FATAL(
"Third argument of veto meta function must be integer!");
2070 auto func = [roeListName, cut, pdgCode, flavourType](
const Particle * particle) ->
bool {
2071 StoreObjPtr<ParticleList> roeList(roeListName);
2072 ROOT::Math::PxPyPzEVector vec = particle->get4Vector();
2073 for (
unsigned int i = 0; i < roeList->getListSize(); i++)
2075 const Particle* roeParticle = roeList->getParticle(i);
2076 if (not particle->overlapsWith(roeParticle)) {
2077 ROOT::Math::PxPyPzEVector tempCombination = roeParticle->get4Vector() + vec;
2078 std::vector<int> indices = { particle->getArrayIndex(), roeParticle->getArrayIndex() };
2079 Particle tempParticle = Particle(tempCombination, pdgCode, flavourType, indices, particle->getArrayPointer());
2080 if (cut->check(&tempParticle)) {
2089 B2FATAL(
"Wrong number of arguments for meta function veto");
2095 if (arguments.size() == 1) {
2096 std::string cutString = arguments[0];
2098 auto func = [cut](
const Particle * particle) ->
int {
2100 for (
auto& daughter : particle->getDaughters())
2102 if (cut->check(daughter))
2109 B2FATAL(
"Wrong number of arguments for meta function countDaughters");
2113 Manager::FunctionPtr numberOfNonOverlappingParticles(
const std::vector<std::string>& arguments)
2116 auto func = [arguments](
const Particle * particle) ->
int {
2118 int _numberOfNonOverlappingParticles = 0;
2119 for (
const auto& listName : arguments)
2121 StoreObjPtr<ParticleList> list(listName);
2122 if (not list.isValid()) {
2123 B2FATAL(
"Invalid list named " << listName <<
" encountered in numberOfNonOverlappingParticles.");
2125 for (
unsigned int i = 0; i < list->getListSize(); i++) {
2126 const Particle* p = list->getParticle(i);
2127 if (not particle->overlapsWith(p)) {
2128 _numberOfNonOverlappingParticles++;
2132 return _numberOfNonOverlappingParticles;
2141 if (arguments.size() == 1) {
2143 auto func = [var](
const Particle * particle) ->
double {
2147 return std::numeric_limits<float>::quiet_NaN();
2149 Particle tmpPart(mcp);
2150 auto var_result = var->function(&tmpPart);
2151 if (std::holds_alternative<double>(var_result))
2153 return std::get<double>(var_result);
2154 }
else if (std::holds_alternative<int>(var_result))
2156 return std::get<int>(var_result);
2157 }
else if (std::holds_alternative<bool>(var_result))
2159 return std::get<bool>(var_result);
2160 }
else return std::numeric_limits<double>::quiet_NaN();
2164 B2FATAL(
"Wrong number of arguments for meta function matchedMC");
2168 double matchedMCHasPDG(
const Particle* particle,
const std::vector<double>& pdgCode)
2170 if (pdgCode.size() != 1) {
2171 B2FATAL(
"Too many arguments provided to matchedMCHasPDG!");
2173 int inputPDG = std::lround(pdgCode[0]);
2177 return std::numeric_limits<double>::quiet_NaN();
2179 return std::abs(mcp->getPDG()) == inputPDG;
2184 if (arguments.size() == 1) {
2185 std::string listName = arguments[0];
2186 auto func = [listName](
const Particle * particle) ->
double {
2189 StoreObjPtr<ParticleList> listOfParticles(listName);
2191 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2192 double totalEnergy = 0;
2193 int nParticles = listOfParticles->getListSize();
2194 for (
int i = 0; i < nParticles; i++)
2196 const Particle* part = listOfParticles->getParticle(i);
2198 totalEnergy += frame.getMomentum(part).E();
2205 B2FATAL(
"Wrong number of arguments for meta function totalEnergyOfParticlesInList");
2211 if (arguments.size() == 1) {
2212 std::string listName = arguments[0];
2213 auto func = [listName](
const Particle*) ->
double {
2214 StoreObjPtr<ParticleList> listOfParticles(listName);
2216 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPxOfParticlesInList");
2218 int nParticles = listOfParticles->getListSize();
2220 for (
int i = 0; i < nParticles; i++)
2222 const Particle* part = listOfParticles->getParticle(i);
2223 totalPx += frame.getMomentum(part).Px();
2229 B2FATAL(
"Wrong number of arguments for meta function totalPxOfParticlesInList");
2235 if (arguments.size() == 1) {
2236 std::string listName = arguments[0];
2237 auto func = [listName](
const Particle*) ->
double {
2238 StoreObjPtr<ParticleList> listOfParticles(listName);
2240 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPyOfParticlesInList");
2242 int nParticles = listOfParticles->getListSize();
2244 for (
int i = 0; i < nParticles; i++)
2246 const Particle* part = listOfParticles->getParticle(i);
2247 totalPy += frame.getMomentum(part).Py();
2253 B2FATAL(
"Wrong number of arguments for meta function totalPyOfParticlesInList");
2259 if (arguments.size() == 1) {
2260 std::string listName = arguments[0];
2261 auto func = [listName](
const Particle*) ->
double {
2262 StoreObjPtr<ParticleList> listOfParticles(listName);
2264 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPzOfParticlesInList");
2266 int nParticles = listOfParticles->getListSize();
2268 for (
int i = 0; i < nParticles; i++)
2270 const Particle* part = listOfParticles->getParticle(i);
2271 totalPz += frame.getMomentum(part).Pz();
2277 B2FATAL(
"Wrong number of arguments for meta function totalPzOfParticlesInList");
2283 if (arguments.size() > 0) {
2285 auto func = [arguments](
const Particle * particle) ->
double {
2287 ROOT::Math::PxPyPzEVector total4Vector;
2289 std::vector<Particle*> particlePool;
2292 for (
const auto& argument : arguments)
2294 StoreObjPtr <ParticleList> listOfParticles(argument);
2296 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << argument <<
" given to invMassInLists");
2297 int nParticles = listOfParticles->getListSize();
2298 for (
int i = 0; i < nParticles; i++) {
2299 bool overlaps =
false;
2300 Particle* part = listOfParticles->getParticle(i);
2301 for (
auto poolPart : particlePool) {
2302 if (part->overlapsWith(poolPart)) {
2308 total4Vector += part->get4Vector();
2309 particlePool.push_back(part);
2313 double invariantMass = total4Vector.M();
2314 return invariantMass;
2319 B2FATAL(
"Wrong number of arguments for meta function invMassInLists");
2323 Manager::FunctionPtr totalECLEnergyOfParticlesInList(
const std::vector<std::string>& arguments)
2325 if (arguments.size() == 1) {
2326 std::string listName = arguments[0];
2327 auto func = [listName](
const Particle * particle) ->
double {
2330 StoreObjPtr<ParticleList> listOfParticles(listName);
2332 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2333 double totalEnergy = 0;
2334 int nParticles = listOfParticles->getListSize();
2335 for (
int i = 0; i < nParticles; i++)
2337 const Particle* part = listOfParticles->getParticle(i);
2338 const ECLCluster* cluster = part->getECLCluster();
2340 if (cluster !=
nullptr) {
2341 totalEnergy += cluster->getEnergy(clusterHypothesis);
2349 B2FATAL(
"Wrong number of arguments for meta function totalECLEnergyOfParticlesInList");
2355 if (arguments.size() == 1) {
2356 std::string listName = arguments[0];
2357 auto func = [listName](
const Particle*) ->
double {
2358 StoreObjPtr<ParticleList> listOfParticles(listName);
2360 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxPtInList");
2361 int nParticles = listOfParticles->getListSize();
2364 for (
int i = 0; i < nParticles; i++)
2366 const Particle* part = listOfParticles->getParticle(i);
2367 const double Pt = frame.getMomentum(part).Pt();
2368 if (Pt > maxPt) maxPt = Pt;
2374 B2FATAL(
"Wrong number of arguments for meta function maxPtInList");
2378 Manager::FunctionPtr eclClusterTrackMatchedWithCondition(
const std::vector<std::string>& arguments)
2380 if (arguments.size() <= 1) {
2382 std::string cutString;
2383 if (arguments.size() == 1)
2384 cutString = arguments[0];
2386 auto func = [cut](
const Particle * particle) ->
double {
2388 if (particle ==
nullptr)
2389 return std::numeric_limits<double>::quiet_NaN();
2391 const ECLCluster* cluster = particle->getECLCluster();
2395 auto tracks = cluster->getRelationsFrom<Track>();
2397 for (
const auto& track : tracks) {
2400 if (cut->check(&trackParticle))
2405 return std::numeric_limits<double>::quiet_NaN();
2409 B2FATAL(
"Wrong number of arguments for meta function eclClusterSpecialTrackMatched");
2415 if (arguments.size() == 2) {
2416 std::string listName = arguments[0];
2419 auto func = [listName, var](
const Particle*) ->
double {
2420 StoreObjPtr<ParticleList> listOfParticles(listName);
2422 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to averageValueInList");
2423 int nParticles = listOfParticles->getListSize();
2424 if (nParticles == 0)
2426 return std::numeric_limits<double>::quiet_NaN();
2429 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2431 for (
int i = 0; i < nParticles; i++) {
2432 average += std::get<double>(var->function(listOfParticles->getParticle(i))) / nParticles;
2434 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2436 for (
int i = 0; i < nParticles; i++) {
2437 average += std::get<int>(var->function(listOfParticles->getParticle(i))) / nParticles;
2439 }
else return std::numeric_limits<double>::quiet_NaN();
2444 B2FATAL(
"Wrong number of arguments for meta function averageValueInList");
2450 if (arguments.size() == 2) {
2451 std::string listName = arguments[0];
2454 auto func = [listName, var](
const Particle*) ->
double {
2455 StoreObjPtr<ParticleList> listOfParticles(listName);
2457 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to medianValueInList");
2458 int nParticles = listOfParticles->getListSize();
2459 if (nParticles == 0)
2461 return std::numeric_limits<double>::quiet_NaN();
2463 std::vector<double> valuesInList;
2464 if (std::holds_alternative<double>(var->function(listOfParticles->getParticle(0))))
2466 for (
int i = 0; i < nParticles; i++) {
2467 valuesInList.push_back(std::get<double>(var->function(listOfParticles->getParticle(i))));
2469 }
else if (std::holds_alternative<int>(var->function(listOfParticles->getParticle(0))))
2471 for (
int i = 0; i < nParticles; i++) {
2472 valuesInList.push_back(std::get<int>(var->function(listOfParticles->getParticle(i))));
2474 }
else return std::numeric_limits<double>::quiet_NaN();
2475 std::sort(valuesInList.begin(), valuesInList.end());
2476 if (nParticles % 2 != 0)
2478 return valuesInList[nParticles / 2];
2481 return 0.5 * (valuesInList[nParticles / 2] + valuesInList[nParticles / 2 - 1]);
2486 B2FATAL(
"Wrong number of arguments for meta function medianValueInList");
2493 if (arguments.size() != 1)
2494 B2FATAL(
"Wrong number of arguments for meta function angleToClosestInList");
2496 std::string listname = arguments[0];
2498 auto func = [listname](
const Particle * particle) ->
double {
2500 StoreObjPtr<ParticleList> list(listname);
2501 if (not list.isValid())
2502 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToClosestInList");
2505 if (list->getListSize() == 0)
2506 return std::numeric_limits<double>::quiet_NaN();
2510 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2513 double minAngle = 2 * M_PI;
2514 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2516 const Particle* compareme = list->getParticle(i);
2517 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2518 double angle = p_compare.Angle(p_this);
2519 if (minAngle > angle) minAngle = angle;
2529 if (arguments.size() != 2)
2530 B2FATAL(
"Wrong number of arguments for meta function closestInList");
2532 std::string listname = arguments[0];
2537 auto func = [listname, var](
const Particle * particle) ->
double {
2539 StoreObjPtr<ParticleList> list(listname);
2540 if (not list.isValid())
2541 B2FATAL(
"Invalid particle list name " << listname <<
" given to closestInList");
2545 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2548 double minAngle = 2 * M_PI;
2550 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2552 const Particle* compareme = list->getParticle(i);
2553 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2554 double angle = p_compare.Angle(p_this);
2555 if (minAngle > angle) {
2562 if (iClosest == -1)
return std::numeric_limits<double>::quiet_NaN();
2563 auto var_result = var->function(list->getParticle(iClosest));
2564 if (std::holds_alternative<double>(var_result))
2566 return std::get<double>(var_result);
2567 }
else if (std::holds_alternative<int>(var_result))
2569 return std::get<int>(var_result);
2570 }
else if (std::holds_alternative<bool>(var_result))
2572 return std::get<bool>(var_result);
2573 }
else return std::numeric_limits<double>::quiet_NaN();
2581 if (arguments.size() != 1)
2582 B2FATAL(
"Wrong number of arguments for meta function angleToMostB2BInList");
2584 std::string listname = arguments[0];
2586 auto func = [listname](
const Particle * particle) ->
double {
2588 StoreObjPtr<ParticleList> list(listname);
2589 if (not list.isValid())
2590 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToMostB2BInList");
2593 if (list->getListSize() == 0)
2594 return std::numeric_limits<double>::quiet_NaN();
2598 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2602 double maxAngle = 0;
2603 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2605 const Particle* compareme = list->getParticle(i);
2606 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2607 double angle = p_compare.Angle(p_this);
2608 if (maxAngle < angle) maxAngle = angle;
2618 if (arguments.size() != 2)
2619 B2FATAL(
"Wrong number of arguments for meta function mostB2BInList");
2621 std::string listname = arguments[0];
2626 auto func = [listname, var](
const Particle * particle) ->
double {
2628 StoreObjPtr<ParticleList> list(listname);
2629 if (not list.isValid())
2630 B2FATAL(
"Invalid particle list name " << listname <<
" given to mostB2BInList");
2634 const auto p_this =
B2Vector3D(frame.getMomentum(particle).Vect());
2638 double maxAngle = -1.0;
2640 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2642 const Particle* compareme = list->getParticle(i);
2643 const auto p_compare =
B2Vector3D(frame.getMomentum(compareme).Vect());
2644 double angle = p_compare.Angle(p_this);
2645 if (maxAngle < angle) {
2652 if (iMostB2B == -1)
return std::numeric_limits<double>::quiet_NaN();
2653 auto var_result = var->function(list->getParticle(iMostB2B));
2654 if (std::holds_alternative<double>(var_result))
2656 return std::get<double>(var_result);
2657 }
else if (std::holds_alternative<int>(var_result))
2659 return std::get<int>(var_result);
2660 }
else if (std::holds_alternative<bool>(var_result))
2662 return std::get<bool>(var_result);
2663 }
else return std::numeric_limits<double>::quiet_NaN();
2670 if (arguments.size() == 1) {
2671 std::string listName = arguments[0];
2672 auto func = [listName](
const Particle*) ->
double {
2673 StoreObjPtr<ParticleList> listOfParticles(listName);
2675 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxOpeningAngleInList");
2676 int nParticles = listOfParticles->getListSize();
2678 if (nParticles < 2)
return std::numeric_limits<double>::quiet_NaN();
2681 double maxOpeningAngle = -1;
2682 for (
int i = 0; i < nParticles; i++)
2684 B2Vector3D v1 = frame.getMomentum(listOfParticles->getParticle(i)).Vect();
2685 for (
int j = i + 1; j < nParticles; j++) {
2686 B2Vector3D v2 = frame.getMomentum(listOfParticles->getParticle(j)).Vect();
2687 const double angle = v1.
Angle(v2);
2688 if (angle > maxOpeningAngle) maxOpeningAngle = angle;
2691 return maxOpeningAngle;
2695 B2FATAL(
"Wrong number of arguments for meta function maxOpeningAngleInList");
2702 if (arguments.size() >= 2) {
2707 auto func = [var, arguments](
const Particle * particle) ->
double {
2708 if (particle ==
nullptr)
2710 B2WARNING(
"Trying to access a daughter that does not exist. Skipping");
2711 return std::numeric_limits<float>::quiet_NaN();
2716 ROOT::Math::PxPyPzEVector pSum(0, 0, 0, 0);
2720 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++)
2722 auto generalizedIndex = arguments[iCoord];
2723 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
2725 pSum += frame.getMomentum(dauPart);
2727 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
2728 return std::numeric_limits<float>::quiet_NaN();
2733 Particle sumOfDaughters(pSum, 100);
2735 auto var_result = var->function(&sumOfDaughters);
2737 if (std::holds_alternative<double>(var_result))
2739 return std::get<double>(var_result);
2740 }
else if (std::holds_alternative<int>(var_result))
2742 return std::get<int>(var_result);
2743 }
else if (std::holds_alternative<bool>(var_result))
2745 return std::get<bool>(var_result);
2746 }
else return std::numeric_limits<double>::quiet_NaN();
2750 B2FATAL(
"Wrong number of arguments for meta function daughterCombination");
2753 Manager::FunctionPtr useAlternativeDaughterHypothesis(
const std::vector<std::string>& arguments)
2766 if (arguments.size() >= 2) {
2777 std::vector<unsigned int>indexesToBeReplaced = {};
2778 std::vector<double>massesToBeReplaced = {};
2781 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++) {
2782 auto replacedDauString = arguments[iCoord];
2784 std::vector<std::string> indexAndMass;
2785 boost::split(indexAndMass, replacedDauString, boost::is_any_of(
":"));
2788 if (indexAndMass.size() > 2) {
2789 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 "
2790 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
2794 if (indexAndMass.size() < 2) {
2795 B2WARNING(
"The string indicating which daughter's mass should be replaced contains only one colon-separated element instead of two. The offending string is "
2796 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
2803 dauIndex = Belle2::convertString<int>(indexAndMass[0]);
2804 }
catch (std::invalid_argument&) {
2805 B2FATAL(
"Found the string " << indexAndMass[0] <<
"instead of a daughter index.");
2809 TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(indexAndMass[1].c_str());
2811 B2WARNING(
"Particle not in evt.pdl file! " << indexAndMass[1]);
2816 int pdgCode = particlePDG->PdgCode();
2817 double dauNewMass = TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass() ;
2818 indexesToBeReplaced.push_back(dauIndex);
2819 massesToBeReplaced.push_back(dauNewMass);
2828 auto func = [var, indexesToBeReplaced, massesToBeReplaced](
const Particle * particle) ->
double {
2829 if (particle ==
nullptr)
2831 B2WARNING(
"Trying to access a particle that does not exist. Skipping");
2832 return std::numeric_limits<float>::quiet_NaN();
2838 ROOT::Math::PxPyPzMVector pSum(0, 0, 0, 0);
2840 for (
unsigned int iDau = 0; iDau < particle->getNDaughters(); iDau++)
2842 const Particle* dauPart = particle->getDaughter(iDau);
2844 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << iDau);
2845 return std::numeric_limits<float>::quiet_NaN();
2848 ROOT::Math::PxPyPzMVector dauMom = ROOT::Math::PxPyPzMVector(frame.getMomentum(dauPart));
2852 for (
unsigned int iReplace = 0; iReplace < indexesToBeReplaced.size(); iReplace++) {
2853 if (indexesToBeReplaced[iReplace] == iDau) {
2854 double p_x = dauMom.Px();
2855 double p_y = dauMom.Py();
2856 double p_z = dauMom.Pz();
2857 dauMom.SetCoordinates(p_x, p_y, p_z, massesToBeReplaced[iReplace]);
2865 Particle sumOfDaughters(ROOT::Math::PxPyPzEVector(pSum), 100);
2867 auto var_result = var->function(&sumOfDaughters);
2869 if (std::holds_alternative<double>(var_result))
2871 return std::get<double>(var_result);
2872 }
else if (std::holds_alternative<int>(var_result))
2874 return std::get<int>(var_result);
2875 }
else if (std::holds_alternative<bool>(var_result))
2877 return std::get<bool>(var_result);
2878 }
else return std::numeric_limits<double>::quiet_NaN();
2883 B2FATAL(
"Wrong number of arguments for meta function useAlternativeDaughterHypothesis");
2888 if (arguments.size() == 2) {
2890 std::string arg = arguments[0];
2892 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
2894 if (part !=
nullptr) {
2895 pdg_code = std::abs(part->PdgCode());
2898 pdg_code = Belle2::convertString<int>(arg);
2899 }
catch (std::exception& e) {}
2902 if (pdg_code == -1) {
2903 B2FATAL(
"Ancestor " + arg +
" is not recognised. Please provide valid PDG code or particle name.");
2906 auto func = [pdg_code, var](
const Particle * particle) ->
double {
2907 const Particle* p = particle;
2909 int ancestor_level = std::get<double>(
Manager::Instance().getVariable(
"hasAncestor(" + std::to_string(pdg_code) +
", 0)")->
function(p));
2910 if ((ancestor_level <= 0) or (std::isnan(ancestor_level)))
2912 return std::numeric_limits<float>::quiet_NaN();
2915 const MCParticle* i_p = p->getMCParticle();
2917 for (
int a = 0; a < ancestor_level ; a = a + 1)
2919 i_p = i_p->getMother();
2922 auto var_result = var->function(&m_p);
2923 if (std::holds_alternative<double>(var_result))
2925 return std::get<double>(var_result);
2926 }
else if (std::holds_alternative<int>(var_result))
2928 return std::get<int>(var_result);
2929 }
else if (std::holds_alternative<bool>(var_result))
2931 return std::get<bool>(var_result);
2932 }
else return std::numeric_limits<double>::quiet_NaN();
2936 B2FATAL(
"Wrong number of arguments for meta function varForFirstMCAncestorOfType (expected 2: type and variable of interest)");
2940 VARIABLE_GROUP(
"MetaFunctions");
2941 REGISTER_METAVARIABLE(
"nCleanedECLClusters(cut)", nCleanedECLClusters,
2942 "[Eventbased] Returns the number of clean Clusters in the event\n"
2943 "Clean clusters are defined by the clusters which pass the given cut assuming a photon hypothesis.",
2944 Manager::VariableDataType::c_int);
2945 REGISTER_METAVARIABLE(
"nCleanedTracks(cut)", nCleanedTracks,
2946 "[Eventbased] Returns the number of clean Tracks in the event\n"
2947 "Clean tracks are defined by the tracks which pass the given cut assuming a pion hypothesis.", Manager::VariableDataType::c_int);
2948 REGISTER_METAVARIABLE(
"formula(v1 + v2 * [v3 - v4] / v5^v6)", formula, R
"DOCSTRING(
2949 Returns the result of the given formula, where v1 to vN are variables or floating
2950 point numbers. Currently the only supported operations are addition (``+``),
2951 subtraction (``-``), multiplication (``*``), division (``/``) and power (``^``
2952 or ``**``). Parenthesis can be in the form of square brackets ``[v1 * v2]``
2953 or normal brackets ``(v1 * v2)``. It will work also with variables taking
2954 arguments. Operator precedence is taken into account. For example ::
2956 (daughter(0, E) + daughter(1, E))**2 - p**2 + 0.138
2958 .. versionchanged:: release-03-00-00
2959 now both, ``[]`` and ``()`` can be used for grouping operations, ``**`` can
2960 be used for exponent and float literals are possible directly in the
2962 )DOCSTRING", Manager::VariableDataType::c_double);
2963 REGISTER_METAVARIABLE("useRestFrame(variable)", useRestFrame,
2964 "Returns the value of the variable using the rest frame of the given particle as current reference frame.\n"
2965 "E.g. ``useRestFrame(daughter(0, p))`` returns the total momentum of the first daughter in its mother's rest-frame", Manager::VariableDataType::c_double);
2966 REGISTER_METAVARIABLE(
"useCMSFrame(variable)", useCMSFrame,
2967 "Returns the value of the variable using the CMS frame as current reference frame.\n"
2968 "E.g. ``useCMSFrame(E)`` returns the energy of a particle in the CMS frame.", Manager::VariableDataType::c_double);
2969 REGISTER_METAVARIABLE(
"useLabFrame(variable)", useLabFrame, R
"DOC(
2970 Returns the value of ``variable`` in the *lab* frame.
2973 The lab frame is the default reference frame, usually you don't need to use this meta-variable.
2974 E.g. ``useLabFrame(E)`` returns the energy of a particle in the Lab frame, same as just ``E``.
2976 Specifying the lab frame is useful in some corner-cases. For example:
2977 ``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.
2978 )DOC", Manager::VariableDataType::c_double);
2979 REGISTER_METAVARIABLE("useTagSideRecoilRestFrame(variable, daughterIndexTagB)", useTagSideRecoilRestFrame,
2980 "Returns the value of the variable in the rest frame of the recoiling particle to the tag side B meson.\n"
2981 "The variable should only be applied to an Upsilon(4S) list.\n"
2982 "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);
2983 REGISTER_METAVARIABLE(
"useParticleRestFrame(variable, particleList)", useParticleRestFrame,
2984 "Returns the value of the variable in the rest frame of the first Particle contained in the given ParticleList.\n"
2985 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
2986 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
2987 "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);
2988 REGISTER_METAVARIABLE(
"useRecoilParticleRestFrame(variable, particleList)", useRecoilParticleRestFrame,
2989 "Returns the value of the variable in the rest frame of recoil system against the first Particle contained in the given ParticleList.\n"
2990 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
2991 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
2992 "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);
2993 REGISTER_METAVARIABLE(
"passesCut(cut)", passesCut,
2994 "Returns 1 if particle passes the cut otherwise 0.\n"
2995 "Useful if you want to write out if a particle would have passed a cut or not.", Manager::VariableDataType::c_bool);
2996 REGISTER_METAVARIABLE(
"passesEventCut(cut)", passesEventCut,
2997 "[Eventbased] Returns 1 if event passes the cut otherwise 0.\n"
2998 "Useful if you want to select events passing a cut without looping into particles, such as for skimming.\n", Manager::VariableDataType::c_bool);
2999 REGISTER_METAVARIABLE(
"countDaughters(cut)", countDaughters,
3000 "Returns number of direct daughters which satisfy the cut.\n"
3001 "Used by the skimming package (for what exactly?)", Manager::VariableDataType::c_int);
3002 REGISTER_METAVARIABLE(
"varFor(pdgCode, variable)", varFor,
3003 "Returns the value of the variable for the given particle if its abs(pdgCode) agrees with the given one.\n"
3004 "E.g. ``varFor(11, p)`` returns the momentum if the particle is an electron or a positron.", Manager::VariableDataType::c_double);
3005 REGISTER_METAVARIABLE(
"varForMCGen(variable)", varForMCGen,
3006 "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"
3007 "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"
3008 "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);
3009 REGISTER_METAVARIABLE(
"nParticlesInList(particleListName)", nParticlesInList,
3010 "[Eventbased] Returns number of particles in the given particle List.", Manager::VariableDataType::c_int);
3011 REGISTER_METAVARIABLE(
"isInList(particleListName)", isInList,
3012 "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);
3013 REGISTER_METAVARIABLE(
"isDaughterOfList(particleListNames)", isDaughterOfList,
3014 "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);
3015 REGISTER_METAVARIABLE(
"isDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isDescendantOfList, R
"DOC(
3016 Returns 1 if the given particle appears in the decay chain of the particles in the given ParticleLists.
3018 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
3020 * ``isDescendantOfList(<particle_list>,1)`` returns 1 if particle is a daughter of the list,
3021 * ``isDescendantOfList(<particle_list>,2)`` returns 1 if particle is a granddaughter of the list,
3022 * ``isDescendantOfList(<particle_list>,3)`` returns 1 if particle is a great-granddaughter of the list, etc.
3023 * Default value is ``-1`` that is inclusive for all generations.
3024 )DOC", Manager::VariableDataType::c_bool);
3025 REGISTER_METAVARIABLE("isMCDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isMCDescendantOfList, R
"DOC(
3026 Returns 1 if the given particle is linked to the same MC particle as any reconstructed daughter of the decay lists.
3028 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
3030 * ``isMCDescendantOfList(<particle_list>,1)`` returns 1 if particle is matched to the same particle as any daughter of the list,
3031 * ``isMCDescendantOfList(<particle_list>,2)`` returns 1 if particle is matched to the same particle as any granddaughter of the list,
3032 * ``isMCDescendantOfList(<particle_list>,3)`` returns 1 if particle is matched to the same particle as any great-granddaughter of the list, etc.
3033 * Default value is ``-1`` that is inclusive for all generations.
3035 It makes only sense for lists created with `fillParticleListFromMC` function with ``addDaughters=True`` argument.
3036 )DOC", Manager::VariableDataType::c_bool);
3038 REGISTER_METAVARIABLE("sourceObjectIsInList(particleListName)", sourceObjectIsInList, R
"DOC(
3039 Returns 1 if the underlying mdst object (e.g. track, or cluster) was used to create a particle in ``particleListName``, 0 if not.
3042 This only makes sense for particles that are not composite. Returns -1 for composite particles.
3043 )DOC", Manager::VariableDataType::c_int);
3045 REGISTER_METAVARIABLE("mcParticleIsInMCList(particleListName)", mcParticleIsInMCList, R
"DOC(
3046 Returns 1 if the particle's matched MC particle is also matched to a particle in ``particleListName``
3047 (or if either of the lists were filled from generator level `modularAnalysis.fillParticleListFromMC`.)
3049 .. seealso:: :b2:var:`isMCDescendantOfList` to check daughters.
3050 )DOC", Manager::VariableDataType::c_bool);
3052 REGISTER_METAVARIABLE("isGrandDaughterOfList(particleListNames)", isGrandDaughterOfList,
3053 "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);
3054 REGISTER_METAVARIABLE(
"daughter(i, variable)", daughter, R
"DOC(
3055 Returns value of variable for the i-th daughter. E.g.
3057 * ``daughter(0, p)`` returns the total momentum of the first daughter.
3058 * ``daughter(0, daughter(1, p)`` returns the total momentum of the second daughter of the first daughter.
3060 Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters).
3061 )DOC", Manager::VariableDataType::c_double);
3062 REGISTER_METAVARIABLE("mcDaughter(i, variable)", mcDaughter, R
"DOC(
3063 Returns the value of the requested variable for the i-th Monte Carlo daughter of the particle.
3065 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
3066 or if the i-th MC daughter does not exist.
3068 E.g. ``mcDaughter(0, PDG)`` will return the PDG code of the first MC daughter of the matched MC
3069 particle of the reconstructed particle the function is applied to.
3071 The meta variable can also be nested: ``mcDaughter(0, mcDaughter(1, PDG))``.
3072 )DOC", Manager::VariableDataType::c_double);
3073 REGISTER_METAVARIABLE("mcMother(variable)", mcMother, R
"DOC(
3074 Returns the value of the requested variable for the Monte Carlo mother of the particle.
3076 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
3077 or if the MC mother does not exist.
3079 E.g. ``mcMother(PDG)`` will return the PDG code of the MC mother of the matched MC
3080 particle of the reconstructed particle the function is applied to.
3082 The meta variable can also be nested: ``mcMother(mcMother(PDG))``.
3083 )DOC", Manager::VariableDataType::c_double);
3084 REGISTER_METAVARIABLE("genParticle(index, variable)", genParticle, R
"DOC(
3085 [Eventbased] Returns the ``variable`` for the ith generator particle.
3086 The arguments of the function must be the ``index`` of the particle in the MCParticle Array,
3087 and ``variable``, the name of the function or variable for that generator particle.
3088 If ``index`` goes beyond the length of the MCParticles array, NaN will be returned.
3090 E.g. ``genParticle(0, p)`` returns the total momentum of the first MCParticle, which is
3091 the Upsilon(4S) in a generic decay.
3092 ``genParticle(0, mcDaughter(1, p)`` returns the total momentum of the second daughter of
3093 the first MC Particle, which is the momentum of the second B meson in a generic decay.
3094 )DOC", Manager::VariableDataType::c_double);
3095 REGISTER_METAVARIABLE("genUpsilon4S(variable)", genUpsilon4S, R
"DOC(
3096 [Eventbased] Returns the ``variable`` evaluated for the generator-level :math:`\Upsilon(4S)`.
3097 If no generator level :math:`\Upsilon(4S)` exists for the event, NaN will be returned.
3099 E.g. ``genUpsilon4S(p)`` returns the total momentum of the :math:`\Upsilon(4S)` in a generic decay.
3100 ``genUpsilon4S(mcDaughter(1, p)`` returns the total momentum of the second daughter of the
3101 generator-level :math:`\Upsilon(4S)` (i.e. the momentum of the second B meson in a generic decay.
3102 )DOC", Manager::VariableDataType::c_double);
3103 REGISTER_METAVARIABLE("daughterProductOf(variable)", daughterProductOf,
3104 "Returns product of a variable over all daughters.\n"
3105 "E.g. ``daughterProductOf(extraInfo(SignalProbability))`` returns the product of the SignalProbabilitys of all daughters.", Manager::VariableDataType::c_double);
3106 REGISTER_METAVARIABLE(
"daughterSumOf(variable)", daughterSumOf,
3107 "Returns sum of a variable over all daughters.\n"
3108 "E.g. ``daughterSumOf(nDaughters)`` returns the number of grand-daughters.", Manager::VariableDataType::c_double);
3109 REGISTER_METAVARIABLE(
"daughterLowest(variable)", daughterLowest,
3110 "Returns the lowest value of the given variable among all daughters.\n"
3111 "E.g. ``useCMSFrame(daughterLowest(p))`` returns the lowest momentum in CMS frame.", Manager::VariableDataType::c_double);
3112 REGISTER_METAVARIABLE(
"daughterHighest(variable)", daughterHighest,
3113 "Returns the highest value of the given variable among all daughters.\n"
3114 "E.g. ``useCMSFrame(daughterHighest(p))`` returns the highest momentum in CMS frame.", Manager::VariableDataType::c_double);
3115 REGISTER_METAVARIABLE(
"daughterDiffOf(i, j, variable)", daughterDiffOf,
3116 "Returns the difference of a variable between the two given daughters.\n"
3117 "E.g. ``useRestFrame(daughterDiffOf(0, 1, p))`` returns the momentum difference between first and second daughter in the rest frame of the given particle.\n"
3118 "(That means that it returns :math:`p_j - p_i`)\n"
3119 "Nota Bene: for the particular case 'variable=phi' you should use the :b2:var:`daughterDiffOfPhi` function.", Manager::VariableDataType::c_double);
3120 REGISTER_METAVARIABLE(
"mcDaughterDiffOf(i, j, variable)", mcDaughterDiffOf,
3121 "MC matched version of the `daughterDiffOf` function.", Manager::VariableDataType::c_double);
3122 REGISTER_METAVARIABLE(
"grandDaughterDiffOf(i, j, variable)", grandDaughterDiffOf,
3123 "Returns the difference of a variable between the first daughters of the two given daughters.\n"
3124 "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"
3125 "(That means that it returns :math:`p_j - p_i`)\n"
3126 "Nota Bene: for the particular case 'variable=phi' you should use the :b2:var:`grandDaughterDiffOfPhi` function.", Manager::VariableDataType::c_double);
3127 REGISTER_METAVARIABLE(
"daughterDiffOfPhi(i, j)", daughterDiffOfPhi,
3128 "Returns the difference in :math:`\\phi` between the two given daughters. The unit of the angle is ``rad``.\n"
3129 "The difference is signed and takes account of the ordering of the given daughters.\n"
3130 "The function returns :math:`\\phi_j - \\phi_i`.", Manager::VariableDataType::c_double);
3131 MAKE_DEPRECATED(
"daughterDiffOfPhi",
false,
"release-06-00-00", R
"DOC(
3132 The difference of the azimuthal angle :math:`\\phi` of two daughters can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3133 REGISTER_METAVARIABLE("mcDaughterDiffOfPhi(i, j)", mcDaughterDiffOfPhi,
3134 "MC matched version of the `daughterDiffOfPhi` function. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
3135 MAKE_DEPRECATED(
"mcDaughterDiffOfPhi",
false,
"release-06-00-00", R
"DOC(
3136 The difference of the azimuthal angle :math:`\\phi` of the MC partners of two daughters can be calculated with the generic variable :b2:var:`mcDaughterDiffOf`.)DOC");
3137 REGISTER_METAVARIABLE("grandDaughterDiffOfPhi(i, j)", grandDaughterDiffOfPhi,
3138 "Returns the difference in :math:`\\phi` between the first daughters of the two given daughters. The unit of the angle is ``rad``.\n"
3139 "The difference is signed and takes account of the ordering of the given daughters.\n"
3140 "The function returns :math:`\\phi_j - \\phi_i`.\n", Manager::VariableDataType::c_double);
3141 MAKE_DEPRECATED(
"grandDaughterDiffOfPhi",
false,
"release-06-00-00", R
"DOC(
3142 The difference of the azimuthal angle :math:`\\phi` of two granddaughters can be calculated with the generic variable :b2:var:`grandDaughterDiffOf`.)DOC");
3143 REGISTER_METAVARIABLE("daughterDiffOfClusterPhi(i, j)", daughterDiffOfClusterPhi,
3144 "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters. The unit of the angle is ``rad``.\n"
3145 "The difference is signed and takes account of the ordering of the given daughters.\n"
3146 "The function returns :math:`\\phi_j - \\phi_i`.\n"
3147 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.", Manager::VariableDataType::c_double);
3148 MAKE_DEPRECATED(
"daughterDiffOfClusterPhi",
false,
"release-06-00-00", R
"DOC(
3149 The difference of the azimuthal angle :math:`\\phi` of the related ECL clusters of two daughters can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3150 REGISTER_METAVARIABLE("grandDaughterDiffOfClusterPhi(i, j)", grandDaughterDiffOfClusterPhi,
3151 "Returns the difference in :math:`\\phi` between the ECLClusters of the daughters of the two given daughters. The unit of the angle is ``rad``.\n"
3152 "The difference is signed and takes account of the ordering of the given daughters.\n"
3153 "The function returns :math:`\\phi_j - \\phi_i`.\n"
3154 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.\n", Manager::VariableDataType::c_double);
3155 MAKE_DEPRECATED(
"grandDaughterDiffOfClusterPhi",
false,
"release-06-00-00", R
"DOC(
3156 The difference of the azimuthal angle :math:`\\phi` of the related ECL clusters of two granddaughters can be calculated with the generic variable :b2:var:`grandDaughterDiffOf`.)DOC");
3157 REGISTER_METAVARIABLE("daughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
3158 "Returns the difference in :math:`\\phi` between the two given daughters in the CMS frame. The unit of the angle is ``rad``.\n"
3159 "The difference is signed and takes account of the ordering of the given daughters.\n"
3160 "The function returns :math:`\\phi_j - \\phi_i`.", Manager::VariableDataType::c_double);
3161 MAKE_DEPRECATED(
"daughterDiffOfPhiCMS",
false,
"release-06-00-00", R
"DOC(
3162 The difference of the azimuthal angle :math:`\\phi` of two daughters in the CMS frame can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3163 REGISTER_METAVARIABLE("mcDaughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
3164 "MC matched version of the `daughterDiffOfPhiCMS` function. The unit of the angle is ``rad``", Manager::VariableDataType::c_double);
3165 MAKE_DEPRECATED(
"mcDaughterDiffOfPhiCMS",
false,
"release-06-00-00", R
"DOC(
3166 The difference of the azimuthal angle :math:`\\phi` of the MC partners of two daughters in the CMS frame can be calculated with the generic variable :b2:var:`mcDaughterDiffOf`.)DOC");
3167 REGISTER_METAVARIABLE("daughterDiffOfClusterPhiCMS(i, j)", daughterDiffOfClusterPhiCMS,
3168 "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters in the CMS frame. The unit of the angle is ``rad``.\n"
3169 "The difference is signed and takes account of the ordering of the given daughters.\n"
3170 "The function returns :math:`\\phi_j - \\phi_i``.\n"
3171 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.", Manager::VariableDataType::c_double);
3172 MAKE_DEPRECATED(
"daughterDiffOfClusterPhiCMS",
false,
"release-06-00-00", R
"DOC(
3173 The difference of the azimuthal angle :math:`\\phi` of the related ECL clusters of two daughters in the CMS frame can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
3174 REGISTER_METAVARIABLE("daughterNormDiffOf(i, j, variable)", daughterNormDiffOf,
3175 "Returns the normalized difference of a variable between the two given daughters.\n"
3176 "E.g. ``daughterNormDiffOf(0, 1, p)`` returns the normalized momentum difference between first and second daughter in the lab frame.", Manager::VariableDataType::c_double);
3177 REGISTER_METAVARIABLE(
"daughterMotherDiffOf(i, variable)", daughterMotherDiffOf,
3178 "Returns the difference of a variable between the given daughter and the mother particle itself.\n"
3179 "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);
3180 REGISTER_METAVARIABLE(
"daughterMotherNormDiffOf(i, variable)", daughterMotherNormDiffOf,
3181 "Returns the normalized difference of a variable between the given daughter and the mother particle itself.\n"
3182 "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);
3183 REGISTER_METAVARIABLE(
"daughterAngle(daughterIndex_1, daughterIndex_2[, daughterIndex_3])", daughterAngle, R
"DOC(
3184 Returns the angle in between any pair of particles belonging to the same decay tree.
3185 The unit of the angle is ``rad``.
3187 The particles are identified via generalized daughter indexes, which are simply colon-separated lists of
3188 daughter indexes, ordered starting from the root particle. For example, ``0:1:3`` identifies the fourth
3189 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply
3190 identifies the second daughter of the root particle.
3192 Both two and three generalized indexes can be given to ``daughterAngle``. If two indices are given, the
3193 variable returns the angle between the momenta of the two given particles. If three indices are given, the
3194 variable returns the angle between the momentum of the third particle and a vector which is the sum of the
3195 first two daughter momenta.
3198 ``daughterAngle(0, 3)`` will return the angle between the first and fourth daughter.
3199 ``daughterAngle(0, 1, 3)`` will return the angle between the fourth daughter and the sum of the first and
3201 ``daughterAngle(0:0, 3:0)`` will return the angle between the first daughter of the first daughter, and
3202 the first daughter of the fourth daughter.
3204 )DOC", Manager::VariableDataType::c_double);
3205 REGISTER_METAVARIABLE("mcDaughterAngle(daughterIndex_1, daughterIndex_2, [daughterIndex_3])", mcDaughterAngle,
3206 "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);
3207 REGISTER_VARIABLE(
"grandDaughterDecayAngle(i, j)", grandDaughterDecayAngle,
3208 "Returns the decay angle of the granddaughter in the daughter particle's rest frame.\n"
3209 "It is calculated with respect to the reverted momentum vector of the particle.\n"
3210 "Two arguments representing the daughter and granddaughter indices have to be provided as arguments.",
"rad");
3211 REGISTER_VARIABLE(
"daughterClusterAngleInBetween(i, j)", daughterClusterAngleInBetween,
3212 "Returns the angle between clusters associated to the two daughters."
3213 "If two indices given: returns the angle between the momenta of the clusters associated to the two given daughters."
3214 "If three indices given: returns the angle between the momentum of the third particle's cluster and a vector "
3215 "which is the sum of the first two daughter's cluster momenta."
3216 "Returns nan if any of the daughters specified don't have an associated cluster."
3217 "The arguments in the argument vector must be integers corresponding to the ith and jth (and kth) daughters.",
"rad");
3218 REGISTER_METAVARIABLE(
"daughterInvM(i[, j, ...])", daughterInvM, R
"DOC(
3219 Returns the invariant mass adding the Lorentz vectors of the given daughters. The unit of the invariant mass is GeV/:math:`\text{c}^2`
3220 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.
3222 Daughters from different generations of the decay tree can be combined using generalized daughter indexes,
3223 which are simply colon-separated daughter indexes for each generation, starting from the root particle. For
3224 example, ``0:1:3`` identifies the fourth daughter (3) of the second daughter (1) of the first daughter(0) of
3225 the mother particle.
3227 Returns NaN if the given daughter-index is out of bound (>= number of daughters))DOC", Manager::VariableDataType::c_double);
3228 REGISTER_METAVARIABLE("extraInfo(name)", extraInfo,
3229 "Returns extra info stored under the given name.\n"
3230 "The extraInfo has to be set by a module first.\n"
3231 "E.g. ``extraInfo(SignalProbability)`` returns the SignalProbability calculated by the ``MVAExpert`` module.\n"
3232 "If nothing is set under the given name or if the particle is a nullptr, NaN is returned.\n"
3233 "In the latter case please use `eventExtraInfo` if you want to access an EventExtraInfo variable.", Manager::VariableDataType::c_double);
3234 REGISTER_METAVARIABLE(
"eventExtraInfo(name)", eventExtraInfo,
3235 "[Eventbased] Returns extra info stored under the given name in the event extra info.\n"
3236 "The extraInfo has to be set first by another module like MVAExpert in event mode.\n"
3237 "If nothing is set under this name, NaN is returned.", Manager::VariableDataType::c_double);
3238 REGISTER_METAVARIABLE(
"eventCached(variable)", eventCached,
3239 "[Eventbased] Returns value of event-based variable and caches this value in the EventExtraInfo.\n"
3240 "The result of second call to this variable in the same event will be provided from the cache.\n"
3241 "It is recommended to use this variable in order to declare custom aliases as event-based. This is "
3242 "necessary if using the eventwise mode of variablesToNtuple).", Manager::VariableDataType::c_double);
3243 REGISTER_METAVARIABLE(
"particleCached(variable)", particleCached,
3244 "Returns value of given variable and caches this value in the ParticleExtraInfo of the provided particle.\n"
3245 "The result of second call to this variable on the same particle will be provided from the cache.", Manager::VariableDataType::c_double);
3246 REGISTER_METAVARIABLE(
"modulo(variable, n)", modulo,
3247 "Returns rest of division of variable by n.", Manager::VariableDataType::c_int);
3248 REGISTER_METAVARIABLE(
"abs(variable)", abs,
3249 "Returns absolute value of the given variable.\n"
3250 "E.g. abs(mcPDG) returns the absolute value of the mcPDG, which is often useful for cuts.", Manager::VariableDataType::c_double);
3251 REGISTER_METAVARIABLE(
"max(var1,var2)", max,
"Returns max value of two variables.\n", Manager::VariableDataType::c_double);
3252 REGISTER_METAVARIABLE(
"min(var1,var2)", min,
"Returns min value of two variables.\n", Manager::VariableDataType::c_double);
3253 REGISTER_METAVARIABLE(
"sin(variable)", sin,
"Returns sine value of the given variable.", Manager::VariableDataType::c_double);
3254 REGISTER_METAVARIABLE(
"asin(variable)", asin,
"Returns arcsine of the given variable. The unit of the asin() is ``rad``", Manager::VariableDataType::c_double);
3255 REGISTER_METAVARIABLE(
"cos(variable)", cos,
"Returns cosine value of the given variable.", Manager::VariableDataType::c_double);
3256 REGISTER_METAVARIABLE(
"acos(variable)", acos,
"Returns arccosine value of the given variable. The unit of the acos() is ``rad``", Manager::VariableDataType::c_double);
3257 REGISTER_METAVARIABLE(
"tan(variable)", tan,
"Returns tangent value of the given variable.", Manager::VariableDataType::c_double);
3258 REGISTER_METAVARIABLE(
"atan(variable)", atan,
"Returns arctangent value of the given variable. The unit of the atan() is ``rad``", Manager::VariableDataType::c_double);
3259 REGISTER_METAVARIABLE(
"exp(variable)", exp,
"Returns exponential evaluated for the given variable.", Manager::VariableDataType::c_double);
3260 REGISTER_METAVARIABLE(
"log(variable)", log,
"Returns natural logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
3261 REGISTER_METAVARIABLE(
"log10(variable)", log10,
"Returns base-10 logarithm evaluated for the given variable.", Manager::VariableDataType::c_double);
3262 REGISTER_METAVARIABLE(
"isNAN(variable)", isNAN,
3263 "Returns true if variable value evaluates to nan (determined via std::isnan(double)).\n"
3264 "Useful for debugging.", Manager::VariableDataType::c_bool);
3265 REGISTER_METAVARIABLE(
"ifNANgiveX(variable, x)", ifNANgiveX,
3266 "Returns x (has to be a number) if variable value is nan (determined via std::isnan(double)).\n"
3267 "Useful for technical purposes while training MVAs.", Manager::VariableDataType::c_double);
3268 REGISTER_METAVARIABLE(
"isInfinity(variable)", isInfinity,
3269 "Returns true if variable value evaluates to infinity (determined via std::isinf(double)).\n"
3270 "Useful for debugging.", Manager::VariableDataType::c_bool);
3271 REGISTER_METAVARIABLE(
"unmask(variable, flag1, flag2, ...)", unmask,
3272 "unmask(variable, flag1, flag2, ...) or unmask(variable, mask) sets certain bits in the variable to zero.\n"
3273 "For example, if you want to set the second, fourth and fifth bits to zero, you could call \n"
3274 "``unmask(variable, 2, 8, 16)`` or ``unmask(variable, 26)``.\n"
3275 "", Manager::VariableDataType::c_double);
3276 REGISTER_METAVARIABLE(
"conditionalVariableSelector(cut, variableIfTrue, variableIfFalse)", conditionalVariableSelector,
3277 "Returns one of the two supplied variables, depending on whether the particle passes the supplied cut.\n"
3278 "The first variable is returned if the particle passes the cut, and the second variable is returned otherwise.", Manager::VariableDataType::c_double);
3279 REGISTER_METAVARIABLE(
"pValueCombination(p1, p2, ...)", pValueCombination,
3280 "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"
3281 "If any of the p-values is invalid, i.e. smaller than zero, -1 is returned.", Manager::VariableDataType::c_double);
3282 REGISTER_METAVARIABLE(
"veto(particleList, cut, pdgCode = 11)", veto,
3283 "Combines current particle with particles from the given particle list and returns 1 if the combination passes the provided cut. \n"
3284 "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"
3285 "around the neutral Pion mass (e.g. ``0.130 < M < 0.140``). \n"
3286 "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);
3287 REGISTER_METAVARIABLE(
"matchedMC(variable)", matchedMC,
3288 "Returns variable output for the matched MCParticle by constructing a temporary Particle from it.\n"
3289 "This may not work too well if your variable requires accessing daughters of the particle.\n"
3290 "E.g. ``matchedMC(p)`` returns the total momentum of the related MCParticle.\n"
3291 "Returns NaN if no matched MCParticle exists.", Manager::VariableDataType::c_double);
3292 REGISTER_METAVARIABLE(
"countInList(particleList, cut='')", countInList,
"[Eventbased] "
3293 "Returns number of particle which pass given in cut in the specified particle list.\n"
3294 "Useful for creating statistics about the number of particles in a list.\n"
3295 "E.g. ``countInList(e+, isSignal == 1)`` returns the number of correctly reconstructed electrons in the event.\n"
3296 "The variable is event-based and does not need a valid particle pointer as input.", Manager::VariableDataType::c_int);
3297 REGISTER_METAVARIABLE(
"getVariableByRank(particleList, rankedVariableName, variableName, rank)", getVariableByRank, R
"DOC(
3298 [Eventbased] Returns the value of ``variableName`` for the candidate in the ``particleList`` with the requested ``rank``.
3301 The `BestCandidateSelection` module available via `rankByHighest` / `rankByLowest` has to be used before.
3304 The first candidate matching the given rank is used.
3305 Thus, it is not recommended to use this variable in conjunction with ``allowMultiRank`` in the `BestCandidateSelection` module.
3307 The suffix ``_rank`` is automatically added to the argument ``rankedVariableName``,
3308 which either has to be the name of the variable used to order the candidates or the selected outputVariable name without the ending ``_rank``.
3309 This means that your selected name for the rank variable has to end with ``_rank``.
3311 An example of this variable's usage is given in the tutorial `B2A602-BestCandidateSelection <https://stash.desy.de/projects/B2/repos/basf2/browse/analysis/examples/tutorials/B2A602-BestCandidateSelection.py>`_
3312 )DOC", Manager::VariableDataType::c_double);
3313 REGISTER_VARIABLE("matchedMCHasPDG(PDGCode)", matchedMCHasPDG,
3314 "Returns if the absolute value of the PDGCode of the MCParticle related to the Particle matches a given PDGCode."
3315 "Returns 0/NAN/1 if PDGCode does not match/is not available/ matches");
3316 REGISTER_METAVARIABLE(
"numberOfNonOverlappingParticles(pList1, pList2, ...)", numberOfNonOverlappingParticles,
3317 "Returns the number of non-overlapping particles in the given particle lists"
3318 "Useful to check if there is additional physics going on in the detector if one reconstructed the Y4S", Manager::VariableDataType::c_int);
3319 REGISTER_METAVARIABLE(
"totalEnergyOfParticlesInList(particleListName)", totalEnergyOfParticlesInList,
3320 "Returns the total energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
3321 REGISTER_METAVARIABLE(
"totalPxOfParticlesInList(particleListName)", totalPxOfParticlesInList,
3322 "Returns the total momentum Px of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3323 REGISTER_METAVARIABLE(
"totalPyOfParticlesInList(particleListName)", totalPyOfParticlesInList,
3324 "Returns the total momentum Py of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3325 REGISTER_METAVARIABLE(
"totalPzOfParticlesInList(particleListName)", totalPzOfParticlesInList,
3326 "Returns the total momentum Pz of particles in the given particle List. The unit of the momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3327 REGISTER_METAVARIABLE(
"invMassInLists(pList1, pList2, ...)", invMassInLists,
3328 "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);
3329 REGISTER_METAVARIABLE(
"totalECLEnergyOfParticlesInList(particleListName)", totalECLEnergyOfParticlesInList,
3330 "Returns the total ECL energy of particles in the given particle List. The unit of the energy is ``GeV``", Manager::VariableDataType::c_double);
3331 REGISTER_METAVARIABLE(
"maxPtInList(particleListName)", maxPtInList,
3332 "Returns maximum transverse momentum Pt in the given particle List. The unit of the transverse momentum is ``GeV/c``", Manager::VariableDataType::c_double);
3333 REGISTER_METAVARIABLE(
"eclClusterSpecialTrackMatched(cut)", eclClusterTrackMatchedWithCondition,
3334 "Returns if at least one Track that satisfies the given condition is related to the ECLCluster of the Particle.", Manager::VariableDataType::c_double);
3335 REGISTER_METAVARIABLE(
"averageValueInList(particleListName, variable)", averageValueInList,
3336 "Returns the arithmetic mean of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3337 REGISTER_METAVARIABLE(
"medianValueInList(particleListName, variable)", medianValueInList,
3338 "Returns the median value of the given variable of the particles in the given particle list.", Manager::VariableDataType::c_double);
3339 REGISTER_METAVARIABLE(
"angleToClosestInList(particleListName)", angleToClosestInList,
3340 "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);
3341 REGISTER_METAVARIABLE(
"closestInList(particleListName, variable)", closestInList,
3342 "Returns `variable` for the closest particle (smallest opening angle) in the list provided.", Manager::VariableDataType::c_double);
3343 REGISTER_METAVARIABLE(
"angleToMostB2BInList(particleListName)", angleToMostB2BInList,
3344 "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);
3345 REGISTER_METAVARIABLE(
"mostB2BInList(particleListName, variable)", mostB2BInList,
3346 "Returns `variable` for the most back-to-back particle (closest opening angle to 180) in the list provided.", Manager::VariableDataType::c_double);
3347 REGISTER_METAVARIABLE(
"maxOpeningAngleInList(particleListName)", maxOpeningAngleInList,
3348 "Returns maximum opening angle in the given particle List. The unit of the angle is ``rad`` ", Manager::VariableDataType::c_double);
3349 REGISTER_METAVARIABLE(
"daughterCombination(variable, daughterIndex_1, daughterIndex_2 ... daughterIndex_n)", daughterCombination,R
"DOC(
3350 Returns a ``variable`` function only of the 4-momentum calculated on an arbitrary set of (grand)daughters.
3353 ``variable`` can only be a function of the daughters' 4-momenta.
3355 Daughters from different generations of the decay tree can be combined using generalized daughter indexes, which are simply colon-separated
3356 the list of daughter indexes, starting from the root particle: for example, ``0:1:3`` identifies the fourth
3357 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle.
3360 ``daughterCombination(M, 0, 3, 4)`` will return the invariant mass of the system made of the first, fourth and fifth daughter of particle.
3361 ``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.
3363 )DOC", Manager::VariableDataType::c_double);
3364 REGISTER_METAVARIABLE("useAlternativeDaughterHypothesis(variable, daughterIndex_1:newMassHyp_1, ..., daughterIndex_n:newMassHyp_n)", useAlternativeDaughterHypothesis,R
"DOC(
3365 Returns a ``variable`` calculated using new mass hypotheses for (some of) the particle's daughters.
3368 ``variable`` can only be a function of the particle 4-momentum, which is re-calculated as the sum of the daughters' 4-momenta.
3369 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.
3370 Also, the track fit is not performed again: the variable only re-calculates the 4-vectors using different mass assumptions. The alternative mass assumption is
3371 used only internally by the variable, and is not stored in the datastore (i.e the daughters are not permanently changed).
3374 Generalized daughter indexes are not supported (yet!): this variable can be used only on first-generation daughters.
3377 ``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.
3378 ``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.
3380 )DOC", Manager::VariableDataType::c_double);
3381 REGISTER_METAVARIABLE("varForFirstMCAncestorOfType(type, variable)",varForFirstMCAncestorOfType,R
"DOC(Returns requested variable of the first ancestor of the given type.
3382 Ancestor type can be set up by PDG code or by particle name (check evt.pdl for valid particle names))DOC", Manager::VariableDataType::c_double)
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
int getPDGCode() const
PDG code.
static const ChargedStable pion
charged pion particle
static const ChargedStable electron
electron particle
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
@ c_nPhotons
CR is split into n photons (N1)
static std::unique_ptr< GeneralCut > compile(const std::string &cut)
Creates an instance of a cut and returns a unique_ptr to it, if you need a copy-able object instead y...
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
static std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
EParticleSourceObject
particle source enumerators
const Particle * getParticleFromGeneralizedIndexString(const std::string &generalizedIndex) const
Explores the decay tree of the particle and returns the (grand^n)daughter identified by a generalized...
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
Class to store variables with their name which were sent to the logging service.
#define MAKE_DEPRECATED(name, make_fatal, version, description)
Registers a variable as deprecated.
B2Vector3< double > B2Vector3D
typedef for common usage with double
bool hasAntiParticle(int pdgCode)
Checks if the particle with given pdg code has an anti-particle or not.
Abstract base class for different kinds of events.