9 #include <analysis/variables/MetaVariables.h>
10 #include <analysis/VariableManager/Utility.h>
11 #include <analysis/dataobjects/EventExtraInfo.h>
12 #include <analysis/dataobjects/Particle.h>
13 #include <analysis/dataobjects/ParticleList.h>
14 #include <analysis/dataobjects/RestOfEvent.h>
15 #include <analysis/utility/PCmsLabTransform.h>
16 #include <analysis/utility/ReferenceFrame.h>
17 #include <analysis/utility/EvtPDLUtil.h>
18 #include <analysis/ClusterUtility/ClusterUtils.h>
19 #include <analysis/variables/VariableFormulaConstructor.h>
21 #include <framework/logging/Logger.h>
22 #include <framework/datastore/StoreArray.h>
23 #include <framework/datastore/StoreObjPtr.h>
24 #include <framework/utilities/Conversion.h>
25 #include <framework/utilities/MakeROOTCompatible.h>
26 #include <framework/gearbox/Const.h>
28 #include <mdst/dataobjects/Track.h>
29 #include <mdst/dataobjects/MCParticle.h>
30 #include <mdst/dataobjects/ECLCluster.h>
31 #include <mdst/dataobjects/TrackFitResult.h>
33 #include <boost/algorithm/string.hpp>
42 #include <TDatabasePDG.h>
53 if (arguments.size() == 1) {
55 auto func = [var](
const Particle * particle) ->
double {
56 UseReferenceFrame<RestFrame> frame(particle);
57 double result = var->function(particle);
62 B2FATAL(
"Wrong number of arguments for meta function useRestFrame");
68 if (arguments.size() == 1) {
70 auto func = [var](
const Particle * particle) ->
double {
71 UseReferenceFrame<CMSFrame> frame;
72 double result = var->function(particle);
77 B2FATAL(
"Wrong number of arguments for meta function useCMSFrame");
83 if (arguments.size() == 1) {
85 auto func = [var](
const Particle * particle) ->
double {
86 UseReferenceFrame<LabFrame> frame;
87 double result = var->function(particle);
92 B2FATAL(
"Wrong number of arguments for meta function useLabFrame");
98 if (arguments.size() == 2) {
101 int daughterIndexTagB = 0;
103 daughterIndexTagB = Belle2::convertString<int>(arguments[1]);
104 }
catch (std::invalid_argument&) {
105 B2FATAL(
"Second argument of useTagSideRecoilRestFrame meta function must be integer!");
108 auto func = [var, daughterIndexTagB](
const Particle * particle) ->
double {
109 if (particle->getPDGCode() != 300553)
111 B2ERROR(
"Variable should only be used on a Upsilon(4S) Particle List!");
112 return std::numeric_limits<float>::quiet_NaN();
116 TLorentzVector pSigB = T.getBeamFourMomentum() - particle->getDaughter(daughterIndexTagB)->get4Vector();
117 Particle tmp(pSigB, -particle->getDaughter(daughterIndexTagB)->getPDGCode());
119 UseReferenceFrame<RestFrame> frame(&tmp);
120 double result = var->function(particle);
126 B2FATAL(
"Wrong number of arguments for meta function useTagSideRecoilRestFrame");
132 if (arguments.size() == 2) {
134 std::string listName = arguments[1];
135 auto func = [var, listName](
const Particle * particle) ->
double {
136 StoreObjPtr<ParticleList> list(listName);
137 unsigned listSize = list->getListSize();
139 return std::numeric_limits<float>::quiet_NaN();
141 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."
142 <<
LogVar(
"ParticleList", listName)
143 <<
LogVar(
"Number of candidates in the list", listSize));
144 const Particle* p = list->getParticle(0);
145 UseReferenceFrame<RestFrame> frame(p);
146 double result = var->function(particle);
151 B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
157 if (arguments.size() == 2) {
159 std::string listName = arguments[1];
160 auto func = [var, listName](
const Particle * particle) ->
double {
161 StoreObjPtr<ParticleList> list(listName);
162 unsigned listSize = list->getListSize();
164 return std::numeric_limits<float>::quiet_NaN();
166 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."
167 <<
LogVar(
"ParticleList", listName)
168 <<
LogVar(
"Number of candidates in the list", listSize));
169 const Particle* p = list->getParticle(0);
171 TLorentzVector recoil = T.getBeamFourMomentum() - p->get4Vector();
173 Particle pRecoil(recoil, 0);
174 pRecoil.setVertex(particle->getVertex());
175 UseReferenceFrame<RestFrame> frame(&pRecoil);
176 double result = var->function(particle);
181 B2FATAL(
"Wrong number of arguments for meta function useParticleRestFrame.");
187 if (arguments.size() == 1) {
188 auto extraInfoName = arguments[0];
189 auto func = [extraInfoName](
const Particle * particle) ->
double {
190 if (particle ==
nullptr)
192 B2WARNING(
"Returns NaN because the particle is nullptr! If you want EventExtraInfo variables, please use eventExtraInfo() instead");
193 return std::numeric_limits<float>::quiet_NaN();
195 if (particle->hasExtraInfo(extraInfoName))
197 return particle->getExtraInfo(extraInfoName);
199 return std::numeric_limits<float>::quiet_NaN();
204 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
210 if (arguments.size() == 1) {
211 auto extraInfoName = arguments[0];
212 auto func = [extraInfoName](
const Particle*) ->
double {
213 StoreObjPtr<EventExtraInfo> eventExtraInfo;
214 if (not eventExtraInfo.isValid())
215 return std::numeric_limits<float>::quiet_NaN();
216 if (eventExtraInfo->hasExtraInfo(extraInfoName))
218 return eventExtraInfo->getExtraInfo(extraInfoName);
220 return std::numeric_limits<float>::quiet_NaN();
225 B2FATAL(
"Wrong number of arguments for meta function extraInfo");
231 if (arguments.size() == 1) {
234 auto func = [var, key](
const Particle*) ->
double {
236 StoreObjPtr<EventExtraInfo> eventExtraInfo;
237 if (not eventExtraInfo.isValid())
238 eventExtraInfo.create();
239 if (eventExtraInfo->hasExtraInfo(key))
241 return eventExtraInfo->getExtraInfo(key);
243 double value = var->function(
nullptr);
244 eventExtraInfo->addExtraInfo(key, value);
250 B2FATAL(
"Wrong number of arguments for meta function eventCached");
256 if (arguments.size() == 1) {
259 auto func = [var, key](
const Particle * particle) ->
double {
261 if (particle->hasExtraInfo(key))
263 return particle->getExtraInfo(key);
265 double value = var->function(particle);
273 const_cast<Particle*
>(particle)->addExtraInfo(key, value);
279 B2FATAL(
"Wrong number of arguments for meta function particleCached");
288 if (arguments.size() != 1) B2FATAL(
"Wrong number of arguments for meta function formula");
289 FormulaParser<VariableFormulaConstructor> parser;
291 return parser.parse(arguments[0]);
292 }
catch (std::runtime_error& e) {
299 if (arguments.size() <= 1) {
301 std::string cutString;
302 if (arguments.size() == 1)
303 cutString = arguments[0];
305 auto func = [cut](
const Particle*) ->
double {
307 unsigned int number_of_tracks = 0;
308 StoreArray<Track> tracks;
309 for (
const auto& track : tracks)
311 const TrackFitResult* trackFit = track.getTrackFitResultWithClosestMass(
Const::pion);
312 if (trackFit->getChargeSign() == 0) {
316 if (cut->check(&particle))
321 return static_cast<double>(number_of_tracks);
326 B2FATAL(
"Wrong number of arguments for meta function nCleanedTracks");
332 if (arguments.size() <= 1) {
334 std::string cutString;
335 if (arguments.size() == 1)
336 cutString = arguments[0];
338 auto func = [cut](
const Particle*) ->
double {
340 unsigned int number_of_clusters = 0;
341 StoreArray<ECLCluster> clusters;
342 for (
const auto& cluster : clusters)
348 Particle particle(&cluster);
349 if (cut->check(&particle))
350 number_of_clusters++;
353 return static_cast<double>(number_of_clusters);
358 B2FATAL(
"Wrong number of arguments for meta function nCleanedECLClusters");
364 if (arguments.size() == 1) {
365 std::string cutString = arguments[0];
367 auto func = [cut](
const Particle * particle) ->
double {
369 if (particle ==
nullptr)
370 return std::numeric_limits<float>::quiet_NaN();
371 if (cut->check(particle))
379 B2FATAL(
"Wrong number of arguments for meta function passesCut");
385 if (arguments.size() == 1) {
386 std::string cutString = arguments[0];
388 auto func = [cut](
const Particle*) ->
double {
389 if (cut->check(
nullptr))
397 B2FATAL(
"Wrong number of arguments for meta function passesEventCut");
403 if (arguments.size() == 2) {
406 pdgCode = Belle2::convertString<int>(arguments[0]);
407 }
catch (std::invalid_argument&) {
408 B2FATAL(
"The first argument of varFor meta function must be a positive integer!");
411 auto func = [pdgCode, var](
const Particle * particle) ->
double {
413 if (std::abs(particle -> getPDGCode()) == std::abs(pdgCode))
414 return var ->
function(particle);
415 else return std::numeric_limits<float>::quiet_NaN();
419 B2FATAL(
"Wrong number of arguments for meta function varFor");
425 if (arguments.size() == 1) {
427 auto func = [var](
const Particle * particle) ->
double {
429 if (particle -> getMCParticle())
434 return var ->
function(particle);
435 }
else return std::numeric_limits<float>::quiet_NaN();
436 }
else return std::numeric_limits<float>::quiet_NaN();
440 B2FATAL(
"Wrong number of arguments for meta function varForMCGen");
446 if (arguments.size() == 1) {
447 std::string listName = arguments[0];
448 auto func = [listName](
const Particle * particle) ->
double {
451 StoreObjPtr<ParticleList> listOfParticles(listName);
453 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to nParticlesInList");
455 return listOfParticles->getListSize();
460 B2FATAL(
"Wrong number of arguments for meta function nParticlesInList");
467 if (arguments.size() != 1) {
468 B2FATAL(
"Wrong number of arguments for isInList");
470 auto listName = arguments[0];
472 auto func = [listName](
const Particle * particle) ->
double {
475 StoreObjPtr<ParticleList> list(listName);
476 if (!(list.isValid()))
478 B2FATAL(
"Invalid Listname " << listName <<
" given to isInList");
482 bool isIn = list->contains(particle);
492 if (arguments.size() != 1) {
493 B2FATAL(
"Wrong number of arguments for sourceObjectIsInList");
495 auto listName = arguments[0];
497 auto func = [listName](
const Particle * particle) ->
double {
500 StoreObjPtr<ParticleList> list(listName);
501 if (!(list.isValid()))
503 B2FATAL(
"Invalid Listname " << listName <<
" given to sourceObjectIsInList");
509 if (particlesource == Particle::EParticleSourceObject::c_Composite
510 or particlesource == Particle::EParticleSourceObject::c_Undefined)
516 for (
unsigned i = 0; i < list->getListSize(); ++i)
518 Particle* iparticle = list->getParticle(i);
519 if (particlesource == iparticle->getParticleSource())
520 if (particle->getMdstArrayIndex() == iparticle->getMdstArrayIndex())
532 if (arguments.size() != 1) {
533 B2FATAL(
"Wrong number of arguments for mcParticleIsInMCList");
535 auto listName = arguments[0];
537 auto func = [listName](
const Particle * particle) ->
double {
540 StoreObjPtr<ParticleList> list(listName);
541 if (!(list.isValid()))
542 B2FATAL(
"Invalid Listname " << listName <<
" given to mcParticleIsInMCList");
545 const MCParticle* mcp = particle->getMCParticle();
546 if (mcp ==
nullptr)
return 0.0;
549 for (
unsigned i = 0; i < list->getListSize(); ++i)
551 const MCParticle* imcp = list->getParticle(i)->
getMCParticle();
552 if ((imcp !=
nullptr) and (mcp->getArrayIndex() == imcp->getArrayIndex()))
562 B2WARNING(
"isDaughterOfList is outdated and replaced by isDescendantOfList.");
563 std::vector<std::string> new_arguments = arguments;
564 new_arguments.push_back(std::string(
"1"));
565 return isDescendantOfList(new_arguments);
570 B2WARNING(
"isGrandDaughterOfList is outdated and replaced by isDescendantOfList.");
571 std::vector<std::string> new_arguments = arguments;
572 new_arguments.push_back(std::string(
"2"));
573 return isDescendantOfList(new_arguments);
578 if (arguments.size() > 0) {
579 auto listNames = arguments;
580 auto func = [listNames](
const Particle * particle) ->
double {
582 int generation_flag = -1;
584 generation_flag = Belle2::convertString<int>(listNames.back());
585 }
catch (std::exception& e) {}
588 for (
auto& iListName : listNames)
591 Belle2::convertString<int>(iListName);
593 }
catch (std::exception& e) {}
596 auto list_comparison = [](
auto &&
self,
const Particle * m,
const Particle * p,
int flag)->
int {
598 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
600 const Particle* daughter = m->getDaughter(i);
601 if ((flag == 1.) or (flag < 0)) {
602 if (p->isCopyOf(daughter)) {
608 if (daughter->getNDaughters() > 0) {
609 result =
self(
self, daughter, p, flag - 1);
620 StoreObjPtr<ParticleList> listOfParticles(iListName);
622 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isDescendantOfList");
624 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
625 Particle* iParticle = listOfParticles->getParticle(i);
626 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
636 B2FATAL(
"Wrong number of arguments for meta function isDescendantOfList");
642 if (arguments.size() > 0) {
643 auto listNames = arguments;
644 auto func = [listNames](
const Particle * particle) ->
double {
646 int generation_flag = -1;
648 generation_flag = Belle2::convertString<int>(listNames.back());
649 }
catch (std::exception& e) {}
651 if (particle->getMCParticle() ==
nullptr)
656 for (
auto& iListName : listNames)
659 std::stod(iListName);
661 }
catch (std::exception& e) {}
663 auto list_comparison = [](
auto &&
self,
const Particle * m,
const Particle * p,
int flag)->
int {
665 for (
unsigned i = 0; i < m->getNDaughters(); ++i)
667 const Particle* daughter = m->getDaughter(i);
668 if ((flag == 1.) or (flag < 0)) {
669 if (daughter->getMCParticle() !=
nullptr) {
670 if (p->getMCParticle()->getArrayIndex() == daughter->getMCParticle()->getArrayIndex()) {
676 if (daughter->getNDaughters() > 0) {
677 result =
self(
self, daughter, p, flag - 1);
688 StoreObjPtr<ParticleList> listOfParticles(iListName);
690 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << iListName <<
" given to isMCDescendantOfList");
692 for (
unsigned i = 0; i < listOfParticles->getListSize(); ++i) {
693 Particle* iParticle = listOfParticles->getParticle(i);
694 output = list_comparison(list_comparison, iParticle, particle, generation_flag);
704 B2FATAL(
"Wrong number of arguments for meta function isMCDescendantOfList");
710 if (arguments.size() == 1) {
712 auto func = [var](
const Particle * particle) ->
double {
713 double product = 1.0;
714 for (
unsigned j = 0; j < particle->getNDaughters(); ++j)
716 product *= var->function(particle->getDaughter(j));
722 B2FATAL(
"Wrong number of arguments for meta function daughterProductOf");
728 if (arguments.size() == 1) {
730 auto func = [var](
const Particle * particle) ->
double {
732 for (
unsigned j = 0; j < particle->getNDaughters(); ++j)
734 sum += var->function(particle->getDaughter(j));
740 B2FATAL(
"Wrong number of arguments for meta function daughterSumOf");
746 if (arguments.size() == 1) {
748 auto func = [var](
const Particle * particle) ->
double {
749 double min = std::numeric_limits<double>::quiet_NaN();
750 for (
unsigned j = 0; j < particle->getNDaughters(); ++j)
752 double iValue = var->function(particle->getDaughter(j));
753 if (std::isnan(iValue))
continue;
754 if (std::isnan(min)) min = iValue;
755 if (iValue < min) min = iValue;
761 B2FATAL(
"Wrong number of arguments for meta function daughterLowest");
767 if (arguments.size() == 1) {
769 auto func = [var](
const Particle * particle) ->
double {
770 double max = std::numeric_limits<double>::quiet_NaN();
771 for (
unsigned j = 0; j < particle->getNDaughters(); ++j)
773 double iValue = var->function(particle->getDaughter(j));
774 if (std::isnan(iValue))
continue;
775 if (std::isnan(max)) max = iValue;
776 if (iValue > max) max = iValue;
782 B2FATAL(
"Wrong number of arguments for meta function daughterHighest");
788 if (arguments.size() == 3) {
789 int iDaughterNumber = 0;
790 int jDaughterNumber = 0;
792 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
793 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
794 }
catch (std::invalid_argument&) {
795 B2FATAL(
"First two arguments of daughterDiffOf meta function must be integers!");
797 auto variablename = arguments[2];
798 auto func = [variablename, iDaughterNumber, jDaughterNumber](
const Particle * particle) ->
double {
799 if (particle ==
nullptr)
800 return std::numeric_limits<double>::quiet_NaN();
801 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
802 return std::numeric_limits<double>::quiet_NaN();
805 double diff = var->function(particle->getDaughter(jDaughterNumber)) - var->function(particle->getDaughter(iDaughterNumber));
806 if (variablename ==
"phi" or variablename ==
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)")) or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)")))
808 if (fabs(diff) > M_PI) {
810 diff = diff - 2 * M_PI;
812 diff = 2 * M_PI + diff;
821 B2FATAL(
"Wrong number of arguments for meta function daughterDiffOf");
827 if (arguments.size() == 3) {
828 int iDaughterNumber = 0;
829 int jDaughterNumber = 0;
831 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
832 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
833 }
catch (std::invalid_argument&) {
834 B2FATAL(
"First two arguments of mcDaughterDiffOf meta function must be integers!");
836 auto variablename = arguments[2];
837 auto func = [variablename, iDaughterNumber, jDaughterNumber](
const Particle * particle) ->
double {
838 if (particle ==
nullptr)
839 return std::numeric_limits<double>::quiet_NaN();
840 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
841 return std::numeric_limits<double>::quiet_NaN();
842 if (particle->getDaughter(jDaughterNumber)->getMCParticle() ==
nullptr || particle->getDaughter(iDaughterNumber)->getMCParticle() ==
nullptr)
843 return std::numeric_limits<double>::quiet_NaN();
845 const MCParticle* iMcDaughter = particle->getDaughter(iDaughterNumber)->getMCParticle();
846 const MCParticle* jMcDaughter = particle->getDaughter(jDaughterNumber)->getMCParticle();
847 Particle iTmpPart(iMcDaughter);
848 Particle jTmpPart(jMcDaughter);
850 double diff = var->function(&jTmpPart) - var->function(&iTmpPart);
851 if (variablename ==
"phi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)")))
853 if (fabs(diff) > M_PI) {
855 diff = diff - 2 * M_PI;
857 diff = 2 * M_PI + diff;
866 B2FATAL(
"Wrong number of arguments for meta function mcDaughterDiffOf");
872 if (arguments.size() == 5) {
873 int iDaughterNumber = 0, jDaughterNumber = 0, agrandDaughterNumber = 0, bgrandDaughterNumber = 0;
875 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
876 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
877 agrandDaughterNumber = Belle2::convertString<int>(arguments[2]);
878 bgrandDaughterNumber = Belle2::convertString<int>(arguments[3]);
879 }
catch (std::invalid_argument&) {
880 B2FATAL(
"First four arguments of grandDaughterDiffOf meta function must be integers!");
882 auto variablename = arguments[4];
883 auto func = [variablename, iDaughterNumber, jDaughterNumber, agrandDaughterNumber,
884 bgrandDaughterNumber](
const Particle * particle) ->
double {
885 if (particle ==
nullptr)
886 return std::numeric_limits<double>::quiet_NaN();
887 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
888 return std::numeric_limits<double>::quiet_NaN();
889 if (agrandDaughterNumber >=
int((particle->getDaughter(iDaughterNumber))->getNDaughters()) || bgrandDaughterNumber >=
int((particle->getDaughter(jDaughterNumber))->getNDaughters()))
890 return std::numeric_limits<double>::quiet_NaN();
893 double diff = var->function((particle->getDaughter(jDaughterNumber))->getDaughter(bgrandDaughterNumber)) - var->function((particle->getDaughter(iDaughterNumber))->getDaughter(agrandDaughterNumber));
894 if (variablename ==
"phi" or variablename ==
"clusterPhi" or std::regex_match(variablename, std::regex(
"use.*Frame\\(phi\\)")) or std::regex_match(variablename, std::regex(
"use.*Frame\\(clusterPhi\\)")))
896 if (fabs(diff) > M_PI) {
898 diff = diff - 2 * M_PI;
900 diff = 2 * M_PI + diff;
909 B2FATAL(
"Wrong number of arguments for meta function grandDaughterDiffOf");
915 std::vector<std::string> new_arguments = arguments;
916 new_arguments.push_back(std::string(
"phi"));
917 return daughterDiffOf(new_arguments);
922 std::vector<std::string> new_arguments = arguments;
923 new_arguments.push_back(std::string(
"phi"));
924 return mcDaughterDiffOf(new_arguments);
929 std::vector<std::string> new_arguments = arguments;
930 new_arguments.push_back(std::string(
"phi"));
931 return grandDaughterDiffOf(new_arguments);
936 std::vector<std::string> new_arguments = arguments;
937 new_arguments.push_back(std::string(
"clusterPhi"));
938 return daughterDiffOf(new_arguments);
943 std::vector<std::string> new_arguments = arguments;
944 new_arguments.push_back(std::string(
"clusterPhi"));
945 return grandDaughterDiffOf(new_arguments);
950 std::vector<std::string> new_arguments = arguments;
951 new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
952 return daughterDiffOf(new_arguments);
957 std::vector<std::string> new_arguments = arguments;
958 new_arguments.push_back(std::string(
"useCMSFrame(phi)"));
959 return mcDaughterDiffOf(new_arguments);
964 std::vector<std::string> new_arguments = arguments;
965 new_arguments.push_back(std::string(
"useCMSFrame(clusterPhi)"));
966 return daughterDiffOf(new_arguments);
971 if (arguments.size() == 3) {
972 int iDaughterNumber = 0;
973 int jDaughterNumber = 0;
975 iDaughterNumber = Belle2::convertString<int>(arguments[0]);
976 jDaughterNumber = Belle2::convertString<int>(arguments[1]);
977 }
catch (std::invalid_argument&) {
978 B2FATAL(
"First two arguments of daughterDiffOf meta function must be integers!");
981 auto func = [var, iDaughterNumber, jDaughterNumber](
const Particle * particle) ->
double {
982 if (particle ==
nullptr)
983 return std::numeric_limits<double>::quiet_NaN();
984 if (iDaughterNumber >=
int(particle->getNDaughters()) || jDaughterNumber >=
int(particle->getNDaughters()))
985 return std::numeric_limits<double>::quiet_NaN();
987 double iValue = var->function(particle->getDaughter(iDaughterNumber));
988 double jValue = var->function(particle->getDaughter(jDaughterNumber));
989 return (jValue - iValue) / (jValue + iValue);
994 B2FATAL(
"Wrong number of arguments for meta function daughterNormDiffOf");
1000 if (arguments.size() == 2) {
1001 int daughterNumber = 0;
1003 daughterNumber = Belle2::convertString<int>(arguments[0]);
1004 }
catch (std::invalid_argument&) {
1005 B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
1007 auto variablename = arguments[1];
1008 auto func = [variablename, daughterNumber](
const Particle * particle) ->
double {
1009 if (particle ==
nullptr)
1010 return std::numeric_limits<double>::quiet_NaN();
1011 if (daughterNumber >=
int(particle->getNDaughters()))
1012 return std::numeric_limits<double>::quiet_NaN();
1015 double diff = var->function(particle) - var->function(particle->getDaughter(daughterNumber));
1016 if (variablename ==
"phi" or variablename ==
"useCMSFrame(phi)")
1018 if (fabs(diff) > M_PI) {
1020 diff = diff - 2 * M_PI;
1022 diff = 2 * M_PI + diff;
1031 B2FATAL(
"Wrong number of arguments for meta function daughterMotherDiffOf");
1037 if (arguments.size() == 2) {
1038 int daughterNumber = 0;
1040 daughterNumber = Belle2::convertString<int>(arguments[0]);
1041 }
catch (std::invalid_argument&) {
1042 B2FATAL(
"First argument of daughterMotherDiffOf meta function must be integer!");
1045 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1046 if (particle ==
nullptr)
1047 return std::numeric_limits<double>::quiet_NaN();
1048 if (daughterNumber >=
int(particle->getNDaughters()))
1049 return std::numeric_limits<double>::quiet_NaN();
1051 double daughterValue = var->function(particle->getDaughter(daughterNumber));
1052 double motherValue = var->function(particle);
1053 return (motherValue - daughterValue) / (motherValue + daughterValue);
1058 B2FATAL(
"Wrong number of arguments for meta function daughterMotherNormDiffOf");
1064 if (arguments.size() == 2 || arguments.size() == 3) {
1066 auto func = [arguments](
const Particle * particle) ->
double {
1067 if (particle ==
nullptr)
1068 return std::numeric_limits<double>::quiet_NaN();
1070 std::vector<TLorentzVector> pDaus;
1074 for (
auto& generalizedIndex : arguments)
1076 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1078 pDaus.push_back(frame.getMomentum(dauPart));
1080 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
1081 return std::numeric_limits<double>::quiet_NaN();
1086 if (pDaus.size() == 2)
1087 return pDaus[0].Vect().Angle(pDaus[1].Vect());
1089 return pDaus[2].Vect().Angle(pDaus[0].Vect() + pDaus[1].Vect());
1093 B2FATAL(
"Wrong number of arguments for meta function daughterAngle");
1099 if (arguments.size() == 2) {
1101 auto func = [arguments](
const Particle * particle) ->
double {
1103 return std::numeric_limits<double>::quiet_NaN();
1105 unsigned daughterIndex, grandDaughterIndex;
1107 daughterIndex = Belle2::convertString<int>(arguments[0]);
1108 grandDaughterIndex = Belle2::convertString<int>(arguments[1]);
1109 }
catch (std::invalid_argument&)
1111 B2FATAL(
"The arguments of grandDaughterDecayAngle have to be integers!");
1114 if (daughterIndex >= particle->getNDaughters())
1115 return std::numeric_limits<float>::quiet_NaN();
1117 const Particle* daughter = particle->getDaughter(daughterIndex);
1119 if (grandDaughterIndex >= daughter->getNDaughters())
1120 return std::numeric_limits<float>::quiet_NaN();
1122 TVector3 boost = - (daughter->get4Vector().BoostVector());
1124 TLorentzVector motherMomentum = - particle->get4Vector();
1125 motherMomentum.Boost(boost);
1127 TLorentzVector grandDaughterMomentum = daughter->getDaughter(grandDaughterIndex)->get4Vector();
1128 grandDaughterMomentum.Boost(boost);
1130 return motherMomentum.Angle(grandDaughterMomentum.Vect());
1134 B2FATAL(
"The meta variable grandDaughterDecayAngle needs exactly two integers as arguments!");
1140 if (arguments.size() == 2 || arguments.size() == 3) {
1142 auto func = [arguments](
const Particle * particle) ->
double {
1143 if (particle ==
nullptr)
1144 return std::numeric_limits<double>::quiet_NaN();
1146 std::vector<TLorentzVector> pDaus;
1150 for (
auto& generalizedIndex : arguments)
1152 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
1153 if (dauPart ==
nullptr)
1154 return std::numeric_limits<double>::quiet_NaN();
1157 if (dauMcPart ==
nullptr)
1158 return std::numeric_limits<double>::quiet_NaN();
1160 pDaus.push_back(frame.getMomentum(dauMcPart->get4Vector()));
1164 if (pDaus.size() == 2)
1165 return pDaus[0].Vect().Angle(pDaus[1].Vect());
1167 return pDaus[2].Vect().Angle(pDaus[0].Vect() + pDaus[1].Vect());
1171 B2FATAL(
"Wrong number of arguments for meta function mcDaughterAngle");
1177 if (arguments.size() == 2 || arguments.size() == 3) {
1178 std::vector<int> daughterIndices;
1180 for (
auto& argument : arguments) daughterIndices.push_back(Belle2::convertString<int>(argument));
1181 }
catch (std::invalid_argument&) {
1182 B2FATAL(
"The arguments of daughterClusterAngleInBetween meta function must be integers!");
1184 auto func = [daughterIndices](
const Particle * particle) ->
double {
1185 if (particle ==
nullptr)
1186 return std::numeric_limits<double>::quiet_NaN();
1187 if (daughterIndices.size() == 2)
1189 if (daughterIndices[0] >=
int(particle->getNDaughters()) || daughterIndices[1] >=
int(particle->getNDaughters()))
1190 return std::numeric_limits<double>::quiet_NaN();
1193 const ECLCluster* clusteri = (particle->getDaughter(daughterIndices[0]))->getECLCluster();
1194 const ECLCluster* clusterj = (particle->getDaughter(daughterIndices[1]))->getECLCluster();
1197 if (clusteri and clusterj) {
1198 ClusterUtils clusutils;
1199 TVector3 pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
1200 TVector3 pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
1201 return pi.Angle(pj);
1203 return std::numeric_limits<float>::quiet_NaN();
1205 }
else if (daughterIndices.size() == 3)
1207 if (daughterIndices[0] >=
int(particle->getNDaughters()) || daughterIndices[1] >=
int(particle->getNDaughters())
1208 || daughterIndices[2] >=
int(particle->getNDaughters()))
return std::numeric_limits<double>::quiet_NaN();
1211 const ECLCluster* clusteri = (particle->getDaughter(daughterIndices[0]))->getECLCluster();
1212 const ECLCluster* clusterj = (particle->getDaughter(daughterIndices[1]))->getECLCluster();
1213 const ECLCluster* clusterk = (particle->getDaughter(daughterIndices[2]))->getECLCluster();
1218 if (clusteri and clusterj and clusterk) {
1219 ClusterUtils clusutils;
1220 TVector3 pi = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusteri, clusteriBit)).Vect();
1221 TVector3 pj = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterj, clusterjBit)).Vect();
1222 TVector3 pk = frame.getMomentum(clusutils.Get4MomentumFromCluster(clusterk, clusterkBit)).Vect();
1223 return pk.Angle(pi + pj);
1225 return std::numeric_limits<float>::quiet_NaN();
1227 }
else return std::numeric_limits<double>::quiet_NaN();
1232 B2FATAL(
"Wrong number of arguments for meta function daughterClusterAngleInBetween");
1238 if (arguments.size() > 1) {
1239 std::vector<int> daughterIndices;
1241 for (
auto& argument : arguments) daughterIndices.push_back(Belle2::convertString<int>(argument));
1242 }
catch (std::invalid_argument&) {
1243 B2FATAL(
"The arguments of daughterInvM meta function must be integers!");
1245 auto func = [daughterIndices](
const Particle * particle) ->
double {
1246 if (particle ==
nullptr)
1247 return std::numeric_limits<float>::quiet_NaN();
1250 TLorentzVector pSum;
1252 for (
auto& index : daughterIndices)
1254 if (index >=
int(particle->getNDaughters())) {
1255 return std::numeric_limits<float>::quiet_NaN();
1256 }
else pSum += frame.getMomentum(particle->getDaughter(index));
1264 B2FATAL(
"Wrong number of arguments for meta function daughterInvM. At least two integers are needed.");
1270 if (arguments.size() == 2) {
1274 divideBy = Belle2::convertString<int>(arguments[1]);
1275 }
catch (std::invalid_argument&) {
1276 B2FATAL(
"Second argument of modulo meta function must be integer!");
1278 auto func = [var, divideBy](
const Particle * particle) ->
double {
return int(var->function(particle)) % divideBy; };
1281 B2FATAL(
"Wrong number of arguments for meta function modulo");
1287 if (arguments.size() == 1) {
1290 auto func = [var](
const Particle * particle) ->
double {
return std::isnan(var->function(particle)); };
1293 B2FATAL(
"Wrong number of arguments for meta function isNAN");
1299 if (arguments.size() == 2) {
1301 double defaultOutput;
1303 defaultOutput = Belle2::convertString<double>(arguments[1]);
1304 }
catch (std::invalid_argument&) {
1305 B2FATAL(
"The second argument of ifNANgiveX meta function must be a number!");
1307 auto func = [var, defaultOutput](
const Particle * particle) ->
double {
1308 double output = var->function(particle);
1309 if (std::isnan(output))
return defaultOutput;
1314 B2FATAL(
"Wrong number of arguments for meta function ifNANgiveX");
1320 if (arguments.size() == 1) {
1323 auto func = [var](
const Particle * particle) ->
double {
return std::isinf(var->function(particle)); };
1326 B2FATAL(
"Wrong number of arguments for meta function isInfinity");
1332 if (arguments.size() >= 2) {
1338 for (
size_t i = 1; i < arguments.size(); ++i) {
1340 finalMask |= Belle2::convertString<int>(arguments[i]);
1341 }
catch (std::invalid_argument&) {
1342 B2FATAL(
"The input flags to meta function unmask() should be integer!");
1348 auto func = [var, finalMask](
const Particle * particle) ->
double {
1349 int value = int(var->function(particle));
1352 if (std::isnan(value))
1353 return std::numeric_limits<double>::quiet_NaN();
1356 value &= (~finalMask);
1363 B2FATAL(
"Meta function unmask needs at least two arguments!");
1370 if (arguments.size() == 3) {
1372 std::string cutString = arguments[0];
1378 auto func = [cut, variableIfTrue, variableIfFalse](
const Particle * particle) ->
double {
1379 if (particle ==
nullptr)
1380 return std::numeric_limits<float>::quiet_NaN();
1381 if (cut->check(particle))
1382 return variableIfTrue->function(particle);
1384 return variableIfFalse->function(particle);
1389 B2FATAL(
"Wrong number of arguments for meta function conditionalVariableSelector");
1396 if (arguments.size() > 0) {
1397 std::vector<const Variable::Manager::Var*> variables;
1398 for (
auto& argument : arguments)
1401 auto func = [variables, arguments](
const Particle * particle) ->
double {
1402 double pValueProduct = 1.;
1403 for (
auto variable : variables)
1405 double pValue = variable->function(particle);
1409 pValueProduct *= pValue;
1411 double pValueSum = 1.;
1412 double factorial = 1.;
1413 for (
unsigned int i = 1; i < arguments.size(); ++i)
1416 pValueSum += pow(-std::log(pValueProduct), i) / factorial;
1418 return pValueProduct * pValueSum;
1422 B2FATAL(
"Wrong number of arguments for meta function pValueCombination");
1428 if (arguments.size() == 1) {
1430 auto func = [var](
const Particle * particle) ->
double {
return std::abs(var->function(particle)); };
1433 B2FATAL(
"Wrong number of arguments for meta function abs");
1439 if (arguments.size() == 2) {
1444 B2FATAL(
"One or both of the used variables doesn't exist!");
1446 auto func = [var1, var2](
const Particle * particle) ->
double {
1447 double max = var1->function(particle);
1448 if (max < var2->
function(particle))
1449 max = var2->function(particle);
1454 B2FATAL(
"Wrong number of arguments for meta function max");
1460 if (arguments.size() == 2) {
1465 B2FATAL(
"One or both of the used variables doesn't exist!");
1467 auto func = [var1, var2](
const Particle * particle) ->
double {
1468 double min = var1->function(particle);
1469 if (min > var2->function(particle))
1470 min = var2->function(particle);
1475 B2FATAL(
"Wrong number of arguments for meta function min");
1481 if (arguments.size() == 1) {
1483 auto func = [var](
const Particle * particle) ->
double {
return std::sin(var->function(particle)); };
1486 B2FATAL(
"Wrong number of arguments for meta function sin");
1492 if (arguments.size() == 1) {
1494 auto func = [var](
const Particle * particle) ->
double {
return std::asin(var->function(particle)); };
1497 B2FATAL(
"Wrong number of arguments for meta function asin");
1503 if (arguments.size() == 1) {
1505 auto func = [var](
const Particle * particle) ->
double {
return std::cos(var->function(particle)); };
1508 B2FATAL(
"Wrong number of arguments for meta function cos");
1514 if (arguments.size() == 1) {
1516 auto func = [var](
const Particle * particle) ->
double {
return std::acos(var->function(particle)); };
1519 B2FATAL(
"Wrong number of arguments for meta function acos");
1525 if (arguments.size() == 1) {
1527 auto func = [var](
const Particle * particle) ->
double {
return std::tan(var->function(particle)); };
1530 B2FATAL(
"Wrong number of arguments for meta function tan");
1536 if (arguments.size() == 1) {
1538 auto func = [var](
const Particle * particle) ->
double {
return std::atan(var->function(particle)); };
1541 B2FATAL(
"Wrong number of arguments for meta function atan");
1547 if (arguments.size() == 1) {
1549 auto func = [var](
const Particle * particle) ->
double {
return std::exp(var->function(particle)); };
1552 B2FATAL(
"Wrong number of arguments for meta function exp");
1558 if (arguments.size() == 1) {
1560 auto func = [var](
const Particle * particle) ->
double {
return std::log(var->function(particle)); };
1563 B2FATAL(
"Wrong number of arguments for meta function log");
1569 if (arguments.size() == 1) {
1571 auto func = [var](
const Particle * particle) ->
double {
return std::log10(var->function(particle)); };
1574 B2FATAL(
"Wrong number of arguments for meta function log10");
1580 if (arguments.size() == 2) {
1581 int daughterNumber = 0;
1583 daughterNumber = Belle2::convertString<int>(arguments[0]);
1584 }
catch (std::invalid_argument&) {
1585 B2FATAL(
"First argument of daughter meta function must be integer!");
1588 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1589 if (particle ==
nullptr)
1590 return std::numeric_limits<float>::quiet_NaN();
1591 if (daughterNumber >=
int(particle->getNDaughters()))
1592 return std::numeric_limits<float>::quiet_NaN();
1594 return var->function(particle->getDaughter(daughterNumber));
1598 B2FATAL(
"Wrong number of arguments for meta function daughter");
1604 if (arguments.size() == 2) {
1605 int daughterNumber = 0;
1607 daughterNumber = Belle2::convertString<int>(arguments[0]);
1608 }
catch (std::invalid_argument&) {
1609 B2FATAL(
"First argument of mcDaughter meta function must be integer!");
1612 auto func = [var, daughterNumber](
const Particle * particle) ->
double {
1613 if (particle ==
nullptr)
1614 return std::numeric_limits<float>::quiet_NaN();
1615 if (particle->getMCParticle())
1617 if (daughterNumber >=
int(particle->getMCParticle()->getNDaughters())) {
1618 return std::numeric_limits<float>::quiet_NaN();
1620 Particle tempParticle = Particle(particle->getMCParticle()->getDaughters().at(daughterNumber));
1621 return var->function(&tempParticle);
1623 return std::numeric_limits<float>::quiet_NaN();
1628 B2FATAL(
"Wrong number of arguments for meta function mcDaughter");
1634 if (arguments.size() == 1) {
1636 auto func = [var](
const Particle * particle) ->
double {
1637 if (particle ==
nullptr)
1638 return std::numeric_limits<float>::quiet_NaN();
1639 if (particle->getMCParticle())
1641 if (particle->getMCParticle()->getMother() ==
nullptr) {
1642 return std::numeric_limits<float>::quiet_NaN();
1644 Particle tempParticle = Particle(particle->getMCParticle()->getMother());
1645 return var->function(&tempParticle);
1647 return std::numeric_limits<float>::quiet_NaN();
1652 B2FATAL(
"Wrong number of arguments for meta function mcMother");
1658 if (arguments.size() == 2) {
1659 int particleNumber = 0;
1661 particleNumber = Belle2::convertString<int>(arguments[0]);
1662 }
catch (std::invalid_argument&) {
1663 B2FATAL(
"First argument of genParticle meta function must be integer!");
1667 auto func = [var, particleNumber](
const Particle*) ->
double {
1668 StoreArray<MCParticle> mcParticles(
"MCParticles");
1669 if (particleNumber >= mcParticles.getEntries())
1671 return std::numeric_limits<float>::quiet_NaN();
1674 MCParticle* mcParticle = mcParticles[particleNumber];
1675 Particle part = Particle(mcParticle);
1676 return var->function(&part);
1680 B2FATAL(
"Wrong number of arguments for meta function genParticle");
1686 if (arguments.size() == 1) {
1689 auto func = [var](
const Particle*) ->
double {
1690 StoreArray<MCParticle> mcParticles(
"MCParticles");
1691 if (mcParticles.getEntries() == 0)
1693 return std::numeric_limits<float>::quiet_NaN();
1696 MCParticle* mcUpsilon4S = mcParticles[0];
1697 if (mcUpsilon4S->getPDG() != 300553)
1699 return std::numeric_limits<float>::quiet_NaN();
1702 Particle upsilon4S = Particle(mcUpsilon4S);
1703 return var->function(&upsilon4S);
1707 B2FATAL(
"Wrong number of arguments for meta function genUpsilon4S");
1713 if (arguments.size() == 4) {
1714 std::string listName = arguments[0];
1715 std::string rankedVariableName = arguments[1];
1716 std::string returnVariableName = arguments[2];
1717 std::string extraInfoName = rankedVariableName +
"_rank";
1720 rank = Belle2::convertString<int>(arguments[3]);
1721 }
catch (std::invalid_argument&) {
1722 B2ERROR(
"3rd argument of getVariableByRank meta function (Rank) must be an integer!");
1727 auto func = [var, rank, extraInfoName, listName](
const Particle*)->
double {
1728 StoreObjPtr<ParticleList> list(listName);
1730 const unsigned int numParticles = list->getListSize();
1731 for (
unsigned int i = 0; i < numParticles; i++)
1733 const Particle* p = list->getParticle(i);
1734 if (p->getExtraInfo(extraInfoName) == rank)
1735 return var->function(p);
1738 return std::numeric_limits<double>::signaling_NaN();
1742 B2FATAL(
"Wrong number of arguments for meta function getVariableByRank");
1748 if (arguments.size() == 1 or arguments.size() == 2) {
1750 std::string listName = arguments[0];
1751 std::string cutString =
"";
1753 if (arguments.size() == 2) {
1754 cutString = arguments[1];
1759 auto func = [listName, cut](
const Particle*) ->
double {
1761 StoreObjPtr<ParticleList> list(listName);
1763 for (
unsigned int i = 0; i < list->getListSize(); i++)
1765 const Particle* particle = list->getParticle(i);
1766 if (cut->check(particle)) {
1774 B2FATAL(
"Wrong number of arguments for meta function countInList");
1780 if (arguments.size() == 2 or arguments.size() == 3) {
1782 std::string roeListName = arguments[0];
1783 std::string cutString = arguments[1];
1785 if (arguments.size() == 2) {
1786 B2INFO(
"Use pdgCode of electron as default in meta variable veto, other arguments: " << roeListName <<
", " << cutString);
1789 pdgCode = Belle2::convertString<int>(arguments[2]);;
1790 }
catch (std::invalid_argument&) {
1791 B2FATAL(
"Third argument of veto meta function must be integer!");
1798 auto func = [roeListName, cut, pdgCode, flavourType](
const Particle * particle) ->
double {
1799 if (particle ==
nullptr)
1800 return std::numeric_limits<float>::quiet_NaN();
1801 StoreObjPtr<ParticleList> roeList(roeListName);
1802 TLorentzVector vec = particle->get4Vector();
1803 for (
unsigned int i = 0; i < roeList->getListSize(); i++)
1805 const Particle* roeParticle = roeList->getParticle(i);
1806 if (not particle->overlapsWith(roeParticle)) {
1807 TLorentzVector tempCombination = roeParticle->get4Vector() + vec;
1808 std::vector<int> indices = { particle->getArrayIndex(), roeParticle->getArrayIndex() };
1809 Particle tempParticle = Particle(tempCombination, pdgCode, flavourType, indices, particle->getArrayPointer());
1810 if (cut->check(&tempParticle)) {
1819 B2FATAL(
"Wrong number of arguments for meta function veto");
1825 if (arguments.size() == 1) {
1826 std::string cutString = arguments[0];
1828 auto func = [cut](
const Particle * particle) ->
double {
1829 if (particle ==
nullptr)
1830 return std::numeric_limits<float>::quiet_NaN();
1832 for (
auto& daughter : particle->getDaughters())
1834 if (cut->check(daughter))
1841 B2FATAL(
"Wrong number of arguments for meta function countDaughters");
1845 Manager::FunctionPtr numberOfNonOverlappingParticles(
const std::vector<std::string>& arguments)
1848 auto func = [arguments](
const Particle * particle) ->
double {
1850 unsigned _numberOfNonOverlappingParticles = 0;
1851 for (
const auto& listName : arguments)
1853 StoreObjPtr<ParticleList> list(listName);
1854 if (not list.isValid()) {
1855 B2FATAL(
"Invalid list named " << listName <<
" encountered in numberOfNonOverlappingParticles.");
1857 for (
unsigned int i = 0; i < list->getListSize(); i++) {
1858 const Particle* p = list->getParticle(i);
1859 if (not particle->overlapsWith(p)) {
1860 _numberOfNonOverlappingParticles++;
1864 return _numberOfNonOverlappingParticles;
1873 if (arguments.size() == 1) {
1875 auto func = [var](
const Particle * particle) ->
double {
1876 const MCParticle* mcp = particle->getMCParticle();
1879 return std::numeric_limits<float>::quiet_NaN();
1881 Particle tmpPart(mcp);
1882 return var->function(&tmpPart);
1886 B2FATAL(
"Wrong number of arguments for meta function matchedMC");
1892 if (arguments.size() == 1) {
1895 inputPDG = Belle2::convertString<int>(arguments[0]);
1896 }
catch (std::invalid_argument&) {
1897 B2FATAL(
"Argument must be an integer value.");
1900 auto func = [inputPDG](
const Particle * particle) ->
double{
1901 const MCParticle* mcp = particle->getMCParticle();
1905 if (std::abs(mcp->getPDG()) == inputPDG)
1914 B2FATAL(
"Wrong number of arguments for meta function matchedMC");
1919 if (arguments.size() == 1) {
1920 std::string listName = arguments[0];
1921 auto func = [listName](
const Particle * particle) ->
double {
1924 StoreObjPtr<ParticleList> listOfParticles(listName);
1926 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
1927 double totalEnergy = 0;
1928 int nParticles = listOfParticles->getListSize();
1929 for (
int i = 0; i < nParticles; i++)
1931 const Particle* part = listOfParticles->getParticle(i);
1933 totalEnergy += frame.getMomentum(part).E();
1940 B2FATAL(
"Wrong number of arguments for meta function totalEnergyOfParticlesInList");
1946 if (arguments.size() == 1) {
1947 std::string listName = arguments[0];
1948 auto func = [listName](
const Particle*) ->
double {
1949 StoreObjPtr<ParticleList> listOfParticles(listName);
1951 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPxOfParticlesInList");
1953 int nParticles = listOfParticles->getListSize();
1955 for (
int i = 0; i < nParticles; i++)
1957 const Particle* part = listOfParticles->getParticle(i);
1958 totalPx += frame.getMomentum(part).Px();
1964 B2FATAL(
"Wrong number of arguments for meta function totalPxOfParticlesInList");
1970 if (arguments.size() == 1) {
1971 std::string listName = arguments[0];
1972 auto func = [listName](
const Particle*) ->
double {
1973 StoreObjPtr<ParticleList> listOfParticles(listName);
1975 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPyOfParticlesInList");
1977 int nParticles = listOfParticles->getListSize();
1979 for (
int i = 0; i < nParticles; i++)
1981 const Particle* part = listOfParticles->getParticle(i);
1982 totalPy += frame.getMomentum(part).Py();
1988 B2FATAL(
"Wrong number of arguments for meta function totalPyOfParticlesInList");
1994 if (arguments.size() == 1) {
1995 std::string listName = arguments[0];
1996 auto func = [listName](
const Particle*) ->
double {
1997 StoreObjPtr<ParticleList> listOfParticles(listName);
1999 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalPzOfParticlesInList");
2001 int nParticles = listOfParticles->getListSize();
2003 for (
int i = 0; i < nParticles; i++)
2005 const Particle* part = listOfParticles->getParticle(i);
2006 totalPz += frame.getMomentum(part).Pz();
2012 B2FATAL(
"Wrong number of arguments for meta function totalPzOfParticlesInList");
2018 if (arguments.size() > 0) {
2020 auto func = [arguments](
const Particle * particle) ->
double {
2022 TLorentzVector total4Vector;
2024 std::vector<Particle*> particlePool;
2027 for (
const auto& argument : arguments)
2029 StoreObjPtr <ParticleList> listOfParticles(argument);
2031 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << argument <<
" given to invMassInLists");
2032 int nParticles = listOfParticles->getListSize();
2033 for (
int i = 0; i < nParticles; i++) {
2034 bool overlaps =
false;
2035 Particle* part = listOfParticles->getParticle(i);
2036 for (
auto poolPart : particlePool) {
2037 if (part->overlapsWith(poolPart)) {
2043 total4Vector += part->get4Vector();
2044 particlePool.push_back(part);
2048 double invariantMass = total4Vector.M();
2049 return invariantMass;
2054 B2FATAL(
"Wrong number of arguments for meta function invMassInLists");
2058 Manager::FunctionPtr totalECLEnergyOfParticlesInList(
const std::vector<std::string>& arguments)
2060 if (arguments.size() == 1) {
2061 std::string listName = arguments[0];
2062 auto func = [listName](
const Particle * particle) ->
double {
2065 StoreObjPtr<ParticleList> listOfParticles(listName);
2067 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to totalEnergyOfParticlesInList");
2068 double totalEnergy = 0;
2069 int nParticles = listOfParticles->getListSize();
2070 for (
int i = 0; i < nParticles; i++)
2072 const Particle* part = listOfParticles->getParticle(i);
2073 const ECLCluster* cluster = part->getECLCluster();
2075 if (cluster !=
nullptr) {
2076 totalEnergy += cluster->getEnergy(clusterHypothesis);
2084 B2FATAL(
"Wrong number of arguments for meta function totalECLEnergyOfParticlesInList");
2090 if (arguments.size() == 1) {
2091 std::string listName = arguments[0];
2092 auto func = [listName](
const Particle*) ->
double {
2093 StoreObjPtr<ParticleList> listOfParticles(listName);
2095 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxPtInList");
2096 int nParticles = listOfParticles->getListSize();
2099 for (
int i = 0; i < nParticles; i++)
2101 const Particle* part = listOfParticles->getParticle(i);
2102 const double Pt = frame.getMomentum(part).Pt();
2103 if (Pt > maxPt) maxPt = Pt;
2109 B2FATAL(
"Wrong number of arguments for meta function maxPtInList");
2113 Manager::FunctionPtr eclClusterTrackMatchedWithCondition(
const std::vector<std::string>& arguments)
2115 if (arguments.size() <= 1) {
2117 std::string cutString;
2118 if (arguments.size() == 1)
2119 cutString = arguments[0];
2121 auto func = [cut](
const Particle * particle) ->
double {
2123 if (particle ==
nullptr)
2124 return std::numeric_limits<double>::quiet_NaN();
2126 const ECLCluster* cluster = particle->getECLCluster();
2130 auto tracks = cluster->getRelationsFrom<Track>();
2132 for (
const auto& track : tracks) {
2135 if (cut->check(&trackParticle))
2140 return std::numeric_limits<double>::quiet_NaN();
2144 B2FATAL(
"Wrong number of arguments for meta function eclClusterSpecialTrackMatched");
2150 if (arguments.size() == 2) {
2151 std::string listName = arguments[0];
2154 auto func = [listName, var](
const Particle*) ->
double {
2155 StoreObjPtr<ParticleList> listOfParticles(listName);
2157 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to averageValueInList");
2158 int nParticles = listOfParticles->getListSize();
2160 for (
int i = 0; i < nParticles; i++)
2162 const Particle* part = listOfParticles->getParticle(i);
2163 average += var->function(part) / nParticles;
2169 B2FATAL(
"Wrong number of arguments for meta function averageValueInList");
2175 if (arguments.size() == 2) {
2176 std::string listName = arguments[0];
2179 auto func = [listName, var](
const Particle*) ->
double {
2180 StoreObjPtr<ParticleList> listOfParticles(listName);
2182 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid list name " << listName <<
" given to medianValueInList");
2183 int nParticles = listOfParticles->getListSize();
2184 if (nParticles == 0)
2186 return std::numeric_limits<double>::quiet_NaN();
2188 std::vector<double> valuesInList;
2189 for (
int i = 0; i < nParticles; i++)
2191 const Particle* part = listOfParticles->getParticle(i);
2192 valuesInList.push_back(var->function(part));
2194 std::sort(valuesInList.begin(), valuesInList.end());
2195 if (nParticles % 2 != 0)
2197 return valuesInList[nParticles / 2];
2199 return 0.5 * (valuesInList[nParticles / 2] + valuesInList[nParticles / 2 - 1]);
2204 B2FATAL(
"Wrong number of arguments for meta function medianValueInList");
2211 if (arguments.size() != 1)
2212 B2FATAL(
"Wrong number of arguments for meta function angleToClosestInList");
2214 std::string listname = arguments[0];
2216 auto func = [listname](
const Particle * particle) ->
double {
2218 StoreObjPtr<ParticleList> list(listname);
2219 if (not list.isValid())
2220 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToClosestInList");
2223 if (list->getListSize() == 0)
2224 return std::numeric_limits<double>::quiet_NaN();
2228 const auto p_this = frame.getMomentum(particle).Vect();
2231 double minAngle = 2 * M_PI;
2232 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2234 const Particle* compareme = list->getParticle(i);
2235 const auto p_compare = frame.getMomentum(compareme).Vect();
2236 double angle = p_compare.Angle(p_this);
2237 if (minAngle > angle) minAngle = angle;
2247 if (arguments.size() != 2)
2248 B2FATAL(
"Wrong number of arguments for meta function closestInList");
2250 std::string listname = arguments[0];
2255 auto func = [listname, var](
const Particle * particle) ->
double {
2257 StoreObjPtr<ParticleList> list(listname);
2258 if (not list.isValid())
2259 B2FATAL(
"Invalid particle list name " << listname <<
" given to closestInList");
2263 const auto p_this = frame.getMomentum(particle).Vect();
2266 double minAngle = 2 * M_PI;
2268 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2270 const Particle* compareme = list->getParticle(i);
2271 const auto p_compare = frame.getMomentum(compareme).Vect();
2272 double angle = p_compare.Angle(p_this);
2273 if (minAngle > angle) {
2280 if (iClosest == -1)
return std::numeric_limits<double>::quiet_NaN();
2282 return var->function(list->getParticle(iClosest));
2290 if (arguments.size() != 1)
2291 B2FATAL(
"Wrong number of arguments for meta function angleToMostB2BInList");
2293 std::string listname = arguments[0];
2295 auto func = [listname](
const Particle * particle) ->
double {
2297 StoreObjPtr<ParticleList> list(listname);
2298 if (not list.isValid())
2299 B2FATAL(
"Invalid particle list name " << listname <<
" given to angleToMostB2BInList");
2302 if (list->getListSize() == 0)
2303 return std::numeric_limits<double>::quiet_NaN();
2307 const auto p_this = frame.getMomentum(particle).Vect();
2311 double maxAngle = 0;
2312 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2314 const Particle* compareme = list->getParticle(i);
2315 const auto p_compare = frame.getMomentum(compareme).Vect();
2316 double angle = p_compare.Angle(p_this);
2317 if (maxAngle < angle) maxAngle = angle;
2327 if (arguments.size() != 2)
2328 B2FATAL(
"Wrong number of arguments for meta function mostB2BInList");
2330 std::string listname = arguments[0];
2335 auto func = [listname, var](
const Particle * particle) ->
double {
2337 StoreObjPtr<ParticleList> list(listname);
2338 if (not list.isValid())
2339 B2FATAL(
"Invalid particle list name " << listname <<
" given to mostB2BInList");
2343 const auto p_this = frame.getMomentum(particle).Vect();
2347 double maxAngle = -1.0;
2349 for (
unsigned int i = 0; i < list->getListSize(); ++i)
2351 const Particle* compareme = list->getParticle(i);
2352 const auto p_compare = frame.getMomentum(compareme).Vect();
2353 double angle = p_compare.Angle(p_this);
2354 if (maxAngle < angle) {
2361 if (iMostB2B == -1)
return std::numeric_limits<double>::quiet_NaN();
2363 return var->function(list->getParticle(iMostB2B));
2370 if (arguments.size() == 1) {
2371 std::string listName = arguments[0];
2372 auto func = [listName](
const Particle*) ->
double {
2373 StoreObjPtr<ParticleList> listOfParticles(listName);
2375 if (!(listOfParticles.isValid())) B2FATAL(
"Invalid Listname " << listName <<
" given to maxOpeningAngleInList");
2376 int nParticles = listOfParticles->getListSize();
2378 if (nParticles < 2)
return std::numeric_limits<double>::quiet_NaN();
2381 double maxOpeningAngle = -1;
2382 for (
int i = 0; i < nParticles; i++)
2384 TVector3
v1 = frame.getMomentum(listOfParticles->getParticle(i)).Vect();
2385 for (
int j = i + 1; j < nParticles; j++) {
2386 TVector3
v2 = frame.getMomentum(listOfParticles->getParticle(j)).Vect();
2387 const double angle =
v1.Angle(v2);
2388 if (angle > maxOpeningAngle) maxOpeningAngle = angle;
2391 return maxOpeningAngle;
2395 B2FATAL(
"Wrong number of arguments for meta function maxOpeningAngleInList");
2402 if (arguments.size() >= 2) {
2407 auto func = [var, arguments](
const Particle * particle) ->
double {
2408 if (particle ==
nullptr)
2410 B2WARNING(
"Trying to access a daughter that does not exist. Skipping");
2411 return std::numeric_limits<float>::quiet_NaN();
2416 TLorentzVector pSum(0, 0, 0, 0);
2420 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++)
2422 auto generalizedIndex = arguments[iCoord];
2423 const Particle* dauPart = particle->getParticleFromGeneralizedIndexString(generalizedIndex);
2425 pSum += frame.getMomentum(dauPart);
2427 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << generalizedIndex);
2428 return std::numeric_limits<float>::quiet_NaN();
2433 Particle sumOfDaughters(pSum, 100);
2436 return var->function(&sumOfDaughters);
2440 B2FATAL(
"Wrong number of arguments for meta function daughterCombination");
2445 Manager::FunctionPtr useAlternativeDaughterHypothesis(
const std::vector<std::string>& arguments)
2458 if (arguments.size() >= 2) {
2469 std::vector<unsigned int>indexesToBeReplaced = {};
2470 std::vector<double>massesToBeReplaced = {};
2473 for (
unsigned int iCoord = 1; iCoord < arguments.size(); iCoord++) {
2474 auto replacedDauString = arguments[iCoord];
2476 std::vector<std::string> indexAndMass;
2477 boost::split(indexAndMass, replacedDauString, boost::is_any_of(
":"));
2480 if (indexAndMass.size() > 2) {
2481 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 "
2482 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
2486 if (indexAndMass.size() < 2) {
2487 B2WARNING(
"The string indicating which daughter's mass should be replaced contains only one colon-separated element instead of two. The offending string is "
2488 << replacedDauString <<
", while a correct syntax looks like 0:K+.");
2495 dauIndex = Belle2::convertString<int>(indexAndMass[0]);
2496 }
catch (std::invalid_argument&) {
2497 B2FATAL(
"Found the string " << indexAndMass[0] <<
"instead of a daughter index.");
2501 TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(indexAndMass[1].c_str());
2503 B2WARNING(
"Particle not in evt.pdl file! " << indexAndMass[1]);
2508 int pdgCode = particlePDG->PdgCode();
2509 double dauNewMass = TDatabasePDG::Instance()->GetParticle(pdgCode)->Mass() ;
2510 indexesToBeReplaced.push_back(dauIndex);
2511 massesToBeReplaced.push_back(dauNewMass);
2520 auto func = [var, indexesToBeReplaced, massesToBeReplaced](
const Particle * particle) ->
double {
2521 if (particle ==
nullptr)
2523 B2WARNING(
"Trying to access a particle that does not exist. Skipping");
2524 return std::numeric_limits<float>::quiet_NaN();
2530 TLorentzVector pSum(0, 0, 0, 0);
2532 for (
unsigned int iDau = 0; iDau < particle->getNDaughters(); iDau++)
2534 const Particle* dauPart = particle->getDaughter(iDau);
2536 B2WARNING(
"Trying to access a daughter that does not exist. Index = " << iDau);
2537 return std::numeric_limits<float>::quiet_NaN();
2540 TLorentzVector dauMom = frame.getMomentum(dauPart);
2544 for (
unsigned int iReplace = 0; iReplace < indexesToBeReplaced.size(); iReplace++) {
2545 if (indexesToBeReplaced[iReplace] == iDau) {
2546 double p_x = dauMom.Vect().Px();
2547 double p_y = dauMom.Vect().Py();
2548 double p_z = dauMom.Vect().Pz();
2549 dauMom.SetXYZM(p_x, p_y, p_z, massesToBeReplaced[iReplace]);
2553 pSum = pSum + dauMom;
2557 Particle sumOfDaughters(pSum, 100);
2560 return var->function(&sumOfDaughters);
2565 B2FATAL(
"Wrong number of arguments for meta function useAlternativeDaughterHypothesis");
2571 if (arguments.size() == 2) {
2573 std::string arg = arguments[0];
2574 std::string variable_of_interest = arguments[1];
2575 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(arg.c_str());
2577 if (part !=
nullptr) {
2578 pdg_code = std::abs(part->PdgCode());
2581 pdg_code = Belle2::convertString<int>(arg);
2582 }
catch (std::exception& e) {}
2585 if (pdg_code == -1) {
2586 B2FATAL(
"Ancestor " + arg +
" is not recognised. Please provide valid PDG code or particle name.");
2589 auto func = [pdg_code, variable_of_interest](
const Particle * particle) ->
double {
2590 const Particle* p = particle;
2593 if ((ancestor_level <= 0) or (std::isnan(ancestor_level)))
2595 return std::numeric_limits<float>::quiet_NaN();
2598 const MCParticle* i_p = p->getMCParticle();
2600 for (
int a = 0; a < ancestor_level ; a = a + 1)
2602 i_p = i_p->getMother();
2609 B2FATAL(
"Wrong number of arguments for meta function varForFirstMCAncestorOfType (expected 2: type and variable of interest)");
2617 VARIABLE_GROUP(
"MetaFunctions");
2618 REGISTER_VARIABLE(
"nCleanedECLClusters(cut)", nCleanedECLClusters,
2619 "[Eventbased] Returns the number of clean Clusters in the event\n"
2620 "Clean clusters are defined by the clusters which pass the given cut assuming a photon hypothesis.");
2621 REGISTER_VARIABLE(
"nCleanedTracks(cut)", nCleanedTracks,
2622 "[Eventbased] Returns the number of clean Tracks in the event\n"
2623 "Clean tracks are defined by the tracks which pass the given cut assuming a pion hypothesis.");
2624 REGISTER_VARIABLE(
"formula(v1 + v2 * [v3 - v4] / v5^v6)", formula, R
"DOCSTRING(
2625 Returns the result of the given formula, where v1 to vN are variables or floating
2626 point numbers. Currently the only supported operations are addition (``+``),
2627 subtraction (``-``), multiplication (``*``), division (``/``) and power (``^``
2628 or ``**``). Parenthesis can be in the form of square brackets ``[v1 * v2]``
2629 or normal brackets ``(v1 * v2)``. It will work also with variables taking
2630 arguments. Operator precedence is taken into account. For example ::
2632 (daughter(0, E) + daughter(1, E))**2 - p**2 + 0.138
2634 .. versionchanged:: release-03-00-00
2635 now both, ``[]`` and ``()`` can be used for grouping operations, ``**`` can
2636 be used for exponent and float literals are possible directly in the
2639 REGISTER_VARIABLE("useRestFrame(variable)", useRestFrame,
2640 "Returns the value of the variable using the rest frame of the given particle as current reference frame.\n"
2641 "E.g. ``useRestFrame(daughter(0, p))`` returns the total momentum of the first daughter in its mother's rest-frame");
2642 REGISTER_VARIABLE(
"useCMSFrame(variable)", useCMSFrame,
2643 "Returns the value of the variable using the CMS frame as current reference frame.\n"
2644 "E.g. ``useCMSFrame(E)`` returns the energy of a particle in the CMS frame.");
2645 REGISTER_VARIABLE(
"useLabFrame(variable)", useLabFrame, R
"DOC(
2646 Returns the value of ``variable`` in the *lab* frame.
2649 The lab frame is the default reference frame, usually you don't need to use this meta-variable.
2650 E.g. ``useLabFrame(E)`` returns the energy of a particle in the Lab frame, same as just ``E``.
2652 Specifying the lab frame is useful in some corner-cases. For example:
2653 ``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.
2655 REGISTER_VARIABLE("useTagSideRecoilRestFrame(variable, daughterIndexTagB)", useTagSideRecoilRestFrame,
2656 "Returns the value of the variable in the rest frame of the recoiling particle to the tag side B meson.\n"
2657 "The variable should only be applied to an Upsilon(4S) list.\n"
2658 "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.");
2659 REGISTER_VARIABLE(
"useParticleRestFrame(variable, particleList)", useParticleRestFrame,
2660 "Returns the value of the variable in the rest frame of the first Particle contained in the given ParticleList.\n"
2661 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
2662 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
2663 "computing the rest frame and a warning is thrown. If the given ParticleList is empty in an event, it returns NaN.");
2664 REGISTER_VARIABLE(
"useRecoilParticleRestFrame(variable, particleList)", useRecoilParticleRestFrame,
2665 "Returns the value of the variable in the rest frame of recoil system against the first Particle contained in the given ParticleList.\n"
2666 "It is strongly recommended to pass a ParticleList that contains at most only one Particle in each event. "
2667 "When more than one Particle is present in the ParticleList, only the first Particle in the list is used for "
2668 "computing the rest frame and a warning is thrown. If the given ParticleList is empty in an event, it returns NaN.");
2669 REGISTER_VARIABLE(
"passesCut(cut)", passesCut,
2670 "Returns 1 if particle passes the cut otherwise 0.\n"
2671 "Useful if you want to write out if a particle would have passed a cut or not.\n"
2672 "Returns NaN if particle is a nullptr.");
2673 REGISTER_VARIABLE(
"passesEventCut(cut)", passesEventCut,
2674 "[Eventbased] Returns 1 if event passes the cut otherwise 0.\n"
2675 "Useful if you want to select events passing a cut without looping into particles, such as for skimming.\n");
2676 REGISTER_VARIABLE(
"countDaughters(cut)", countDaughters,
2677 "Returns number of direct daughters which satisfy the cut.\n"
2678 "Used by the skimming package (for what exactly?)\n"
2679 "Returns NaN if particle is a nullptr.");
2680 REGISTER_VARIABLE(
"varFor(pdgCode, variable)", varFor,
2681 "Returns the value of the variable for the given particle if its abs(pdgCode) agrees with the given one.\n"
2682 "E.g. ``varFor(11, p)`` returns the momentum if the particle is an electron or a positron.");
2683 REGISTER_VARIABLE(
"varForMCGen(variable)", varForMCGen,
2684 "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"
2685 "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"
2686 "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.");
2687 REGISTER_VARIABLE(
"nParticlesInList(particleListName)", nParticlesInList,
2688 "[Eventbased] Returns number of particles in the given particle List.");
2689 REGISTER_VARIABLE(
"isInList(particleListName)", isInList,
2690 "Returns 1.0 if the particle is in the list provided, 0.0 if not. Note that this only checks the particle given. For daughters of composite particles, please see :b2:var:`isDaughterOfList`.");
2691 REGISTER_VARIABLE(
"isDaughterOfList(particleListNames)", isDaughterOfList,
2692 "Returns 1 if the given particle is a daughter of at least one of the particles in the given particle Lists.");
2693 REGISTER_VARIABLE(
"isDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isDescendantOfList, R
"DOC(
2694 Returns 1 if the given particle appears in the decay chain of the particles in the given ParticleLists.
2696 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
2698 * ``isDescendantOfList(<particle_list>,1)`` returns 1 if particle is a daughter of the list,
2699 * ``isDescendantOfList(<particle_list>,2)`` returns 1 if particle is a granddaughter of the list,
2700 * ``isDescendantOfList(<particle_list>,3)`` returns 1 if particle is a great-granddaughter of the list, etc.
2701 * Default value is ``-1`` that is inclusive for all generations.
2703 REGISTER_VARIABLE("isMCDescendantOfList(particleListName[, anotherParticleListName][, generationFlag = -1])", isMCDescendantOfList, R
"DOC(
2704 Returns 1 if the given particle is linked to the same MC particle as any reconstructed daughter of the decay lists.
2706 Passing an integer as the last argument, allows to check if the particle belongs to the specific generation:
2708 * ``isMCDescendantOfList(<particle_list>,1)`` returns 1 if particle is matched to the same particle as any daughter of the list,
2709 * ``isMCDescendantOfList(<particle_list>,2)`` returns 1 if particle is matched to the same particle as any granddaughter of the list,
2710 * ``isMCDescendantOfList(<particle_list>,3)`` returns 1 if particle is matched to the same particle as any great-granddaughter of the list, etc.
2711 * Default value is ``-1`` that is inclusive for all generations.
2713 It makes only sense for lists created with `fillParticleListFromMC` function with ``addDaughters=True`` argument.
2716 REGISTER_VARIABLE("sourceObjectIsInList(particleListName)", sourceObjectIsInList, R
"DOC(
2717 Returns 1.0 if the underlying mdst object (e.g. track, or cluster) was used to create a particle in ``particleListName``, 0.0 if not.
2720 This only makes sense for particles that are not composite. Returns -1 for composite particles.
2723 REGISTER_VARIABLE("mcParticleIsInMCList(particleListName)", mcParticleIsInMCList, R
"DOC(
2724 Returns 1.0 if the particle's matched MC particle is also matched to a particle in ``particleListName``
2725 (or if either of the lists were filled from generator level `modularAnalysis.fillParticleListFromMC`.)
2727 .. seealso:: :b2:var:`isMCDescendantOfList` to check daughters.
2730 REGISTER_VARIABLE("isGrandDaughterOfList(particleListNames)", isGrandDaughterOfList,
2731 "Returns 1 if the given particle is a grand daughter of at least one of the particles in the given particle Lists.");
2732 REGISTER_VARIABLE(
"daughter(i, variable)", daughter, R
"DOC(
2733 Returns value of variable for the i-th daughter. E.g.
2735 * ``daughter(0, p)`` returns the total momentum of the first daughter.
2736 * ``daughter(0, daughter(1, p)`` returns the total momentum of the second daughter of the first daughter.
2738 Returns NaN if particle is nullptr or if the given daughter-index is out of bound (>= amount of daughters).
2740 REGISTER_VARIABLE("mcDaughter(i, variable)", mcDaughter, R
"DOC(
2741 Returns the value of the requested variable for the i-th Monte Carlo daughter of the particle.
2743 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
2744 or if the i-th MC daughter does not exist.
2746 E.g. ``mcDaughter(0, PDG)`` will return the PDG code of the first MC daughter of the matched MC
2747 particle of the reconstructed particle the function is applied to.
2749 The meta variable can also be nested: ``mcDaughter(0, mcDaughter(1, PDG))``.
2751 REGISTER_VARIABLE("mcMother(variable)", mcMother, R
"DOC(
2752 Returns the value of the requested variable for the Monte Carlo mother of the particle.
2754 Returns NaN if the particle is nullptr, if the particle is not matched to an MC particle,
2755 or if the MC mother does not exist.
2757 E.g. ``mcMother(PDG)`` will return the PDG code of the MC mother of the matched MC
2758 particle of the reconstructed particle the function is applied to.
2760 The meta variable can also be nested: ``mcMother(mcMother(PDG))``.
2762 REGISTER_VARIABLE("genParticle(index, variable)", genParticle, R
"DOC(
2763 [Eventbased] Returns the ``variable`` for the ith generator particle.
2764 The arguments of the function must be the ``index`` of the particle in the MCParticle Array,
2765 and ``variable``, the name of the function or variable for that generator particle.
2766 If ``index`` goes beyond the length of the MCParticles array, NaN will be returned.
2768 E.g. ``genParticle(0, p)`` returns the total momentum of the first MCParticle, which is
2769 the Upsilon(4S) in a generic decay.
2770 ``genParticle(0, mcDaughter(1, p)`` returns the total momentum of the second daughter of
2771 the first MC Particle, which is the momentum of the second B meson in a generic decay.
2773 REGISTER_VARIABLE("genUpsilon4S(variable)", genUpsilon4S, R
"DOC(
2774 [Eventbased] Returns the ``variable`` evaluated for the generator-level :math:`\Upsilon(4S)`.
2775 If no generator level :math:`\Upsilon(4S)` exists for the event, NaN will be returned.
2777 E.g. ``genUpsilon4S(p)`` returns the total momentum of the :math:`\Upsilon(4S)` in a generic decay.
2778 ``genUpsilon4S(mcDaughter(1, p)`` returns the total momentum of the second daughter of the
2779 generator-level :math:`\Upsilon(4S)` (i.e. the momentum of the second B meson in a generic decay.
2781 REGISTER_VARIABLE("daughterProductOf(variable)", daughterProductOf,
2782 "Returns product of a variable over all daughters.\n"
2783 "E.g. ``daughterProductOf(extraInfo(SignalProbability))`` returns the product of the SignalProbabilitys of all daughters.");
2784 REGISTER_VARIABLE(
"daughterSumOf(variable)", daughterSumOf,
2785 "Returns sum of a variable over all daughters.\n"
2786 "E.g. ``daughterSumOf(nDaughters)`` returns the number of grand-daughters.");
2787 REGISTER_VARIABLE(
"daughterLowest(variable)", daughterLowest,
2788 "Returns the lowest value of the given variable among all daughters.\n"
2789 "E.g. ``useCMSFrame(daughterLowest(p))`` returns the lowest momentum in CMS frame.");
2790 REGISTER_VARIABLE(
"daughterHighest(variable)", daughterHighest,
2791 "Returns the highest value of the given variable among all daughters.\n"
2792 "E.g. ``useCMSFrame(daughterHighest(p))`` returns the highest momentum in CMS frame.");
2793 REGISTER_VARIABLE(
"daughterDiffOf(i, j, variable)", daughterDiffOf,
2794 "Returns the difference of a variable between the two given daughters.\n"
2795 "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"
2796 "(That means that it returns :math:`p_j - p_i`)\n"
2797 "Nota Bene: for the particular case 'variable=phi' you should use the :b2:var:`daughterDiffOfPhi` function.");
2798 REGISTER_VARIABLE(
"mcDaughterDiffOf(i, j, variable)", mcDaughterDiffOf,
2799 "MC matched version of the `daughterDiffOf` function.");
2800 REGISTER_VARIABLE(
"grandDaughterDiffOf(i, j, variable)", grandDaughterDiffOf,
2801 "Returns the difference of a variable between the first daughters of the two given daughters.\n"
2802 "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"
2803 "(That means that it returns :math:`p_j - p_i`)\n"
2804 "Nota Bene: for the particular case 'variable=phi' you should use the :b2:var:`grandDaughterDiffOfPhi` function.");
2805 REGISTER_VARIABLE(
"daughterDiffOfPhi(i, j)", daughterDiffOfPhi,
2806 "Returns the difference in :math:`\\phi` between the two given daughters.\n"
2807 "The difference is signed and takes account of the ordering of the given daughters.\n"
2808 "The function returns :math:`\\phi_j - \\phi_i`.");
2809 MAKE_DEPRECATED(
"daughterDiffOfPhi(i, j)",
false,
"release-06-00-00", R
"DOC(
2810 The difference of the azimuthal angle :math:`\\phi` of two daughters can be calculated with the generic variable :b2:var:`daughterDiffOf`.)DOC");
2811 REGISTER_VARIABLE("mcDaughterDiffOfPhi(i, j)", mcDaughterDiffOfPhi,
2812 "MC matched version of the `daughterDiffOfPhi` function.");
2813 MAKE_DEPRECATED(
"mcDaughterDiffOfPhi(i, j)",
false,
"release-06-00-00", R
"DOC(
2814 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");
2815 REGISTER_VARIABLE("grandDaughterDiffOfPhi(i, j)", grandDaughterDiffOfPhi,
2816 "Returns the difference in :math:`\\phi` between the first daughters of the two given daughters.\n"
2817 "The difference is signed and takes account of the ordering of the given daughters.\n"
2818 "The function returns :math:`\\phi_j - \\phi_i`.\n");
2819 MAKE_DEPRECATED(
"grandDaughterDiffOfPhi(i, j)",
false,
"release-06-00-00", R
"DOC(
2820 The difference of the azimuthal angle :math:`\\phi` of two granddaughters can be calculated with the generic variable :b2:var:`grandDaughterDiffOf`.)DOC");
2821 REGISTER_VARIABLE("daughterDiffOfClusterPhi(i, j)", daughterDiffOfClusterPhi,
2822 "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters.\n"
2823 "The difference is signed and takes account of the ordering of the given daughters.\n"
2824 "The function returns :math:`\\phi_j - \\phi_i`.\n"
2825 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.");
2826 MAKE_DEPRECATED(
"daughterDiffOfClusterPhi(i, j)",
false,
"release-06-00-00", R
"DOC(
2827 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");
2828 REGISTER_VARIABLE("grandDaughterDiffOfClusterPhi(i, j)", grandDaughterDiffOfClusterPhi,
2829 "Returns the difference in :math:`\\phi` between the ECLClusters of the daughters of the two given daughters.\n"
2830 "The difference is signed and takes account of the ordering of the given daughters.\n"
2831 "The function returns :math:`\\phi_j - \\phi_i`.\n"
2832 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.\n");
2833 MAKE_DEPRECATED(
"grandDaughterDiffOfClusterPhi(i, j)",
false,
"release-06-00-00", R
"DOC(
2834 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");
2835 REGISTER_VARIABLE("daughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
2836 "Returns the difference in :math:`\\phi` between the two given daughters in the CMS frame.\n"
2837 "The difference is signed and takes account of the ordering of the given daughters.\n"
2838 "The function returns :math:`\\phi_j - \\phi_i`.");
2839 MAKE_DEPRECATED(
"daughterDiffOfPhiCMS(i, j)",
false,
"release-06-00-00", R
"DOC(
2840 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");
2841 REGISTER_VARIABLE("mcDaughterDiffOfPhiCMS(i, j)", daughterDiffOfPhiCMS,
2842 "MC matched version of the `daughterDiffOfPhiCMS` function.");
2843 MAKE_DEPRECATED(
"mcDaughterDiffOfPhiCMS(i, j)",
false,
"release-06-00-00", R
"DOC(
2844 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");
2845 REGISTER_VARIABLE("daughterDiffOfClusterPhiCMS(i, j)", daughterDiffOfClusterPhiCMS,
2846 "Returns the difference in :math:`\\phi` between the ECLClusters of two given daughters in the CMS frame.\n"
2847 "The difference is signed and takes account of the ordering of the given daughters.\n"
2848 "The function returns :math:`\\phi_j - \\phi_i``.\n"
2849 "The function returns NaN if at least one of the daughters is not matched to or not based on an ECLCluster.");
2850 MAKE_DEPRECATED(
"daughterDiffOfClusterPhiCMS(i, j)",
false,
"release-06-00-00", R
"DOC(
2851 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");
2852 REGISTER_VARIABLE("daughterNormDiffOf(i, j, variable)", daughterNormDiffOf,
2853 "Returns the normalized difference of a variable between the two given daughters.\n"
2854 "E.g. ``daughterNormDiffOf(0, 1, p)`` returns the normalized momentum difference between first and second daughter in the lab frame.");
2855 REGISTER_VARIABLE(
"daughterMotherDiffOf(i, variable)", daughterMotherDiffOf,
2856 "Returns the difference of a variable between the given daughter and the mother particle itself.\n"
2857 "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.");
2858 REGISTER_VARIABLE(
"daughterMotherNormDiffOf(i, variable)", daughterMotherNormDiffOf,
2859 "Returns the normalized difference of a variable between the given daughter and the mother particle itself.\n"
2860 "E.g. ``daughterMotherNormDiffOf(1, p)`` returns the normalized momentum difference between the given particle and its second daughter in the lab frame.");
2861 REGISTER_VARIABLE(
"daughterAngle(daughterIndex_1, daughterIndex_2[, daughterIndex_3])", daughterAngle, R
"DOC(
2862 Returns the angle in between any pair of particles belonging to the same decay tree.
2864 The particles are identified via generalized daughter indexes, which are simply colon-separated lists of
2865 daughter indexes, ordered starting from the root particle. For example, ``0:1:3`` identifies the fourth
2866 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle. ``1`` simply
2867 identifies the second daughter of the root particle.
2869 Both two and three generalized indexes can be given to ``daughterAngle``. If two indices are given, the
2870 variable returns the angle between the momenta of the two given particles. If three indices are given, the
2871 variable returns the angle between the momentum of the third particle and a vector which is the sum of the
2872 first two daughter momenta.
2875 ``daughterAngle(0, 3)`` will return the angle between the first and fourth daughter.
2876 ``daughterAngle(0, 1, 3)`` will return the angle between the fourth daughter and the sum of the first and
2878 ``daughterAngle(0:0, 3:0)`` will return the angle between the first daughter of the first daughter, and
2879 the first daughter of the fourth daughter.
2882 REGISTER_VARIABLE("mcDaughterAngle(daughterIndex_1, daughterIndex_2, [daughterIndex_3])", mcDaughterAngle,
"MC matched version of the `daughterAngle` function.");
2883 REGISTER_VARIABLE(
"grandDaughterDecayAngle(i, j)", grandDaughterDecayAngle,
2884 "Returns the decay angle of the granddaughter in the daughter particle's rest frame.\n"
2885 "It is calculated with respect to the reverted momentum vector of the particle.\n"
2886 "Two arguments representing the daughter and granddaughter indices have to be provided as arguments.");
2887 REGISTER_VARIABLE(
"daughterClusterAngleInBetween(i, j)", daughterClusterAngleInBetween,
2888 "Returns function which returns the angle between clusters associated to the two daughters."
2889 "If two indices given: returns the angle between the momenta of the clusters associated to the two given daughters."
2890 "If three indices given: returns the angle between the momentum of the third particle's cluster and a vector "
2891 "which is the sum of the first two daughter's cluster momenta."
2892 "Returns nan if any of the daughters specified don't have an associated cluster."
2893 "The arguments in the argument vector must be integers corresponding to the ith and jth (and kth) daughters.");
2894 REGISTER_VARIABLE(
"daughterInvM(i, j)", daughterInvM,
2895 "Returns the invariant Mass adding the Lorentz vectors of the given daughters.\n"
2896 "E.g. ``daughterInvM(0, 1, 2)`` returns the invariant Mass :math:`m = \\sqrt{(p_0 + p_1 + p_2)^2}`` of first, second and third daughter.");
2897 REGISTER_VARIABLE(
"extraInfo(name)", extraInfo,
2898 "Returns extra info stored under the given name.\n"
2899 "The extraInfo has to be set by a module first.\n"
2900 "E.g. ``extraInfo(SignalProbability)`` returns the SignalProbability calculated by the ``MVAExpert`` module.\n"
2901 "If nothing is set under the given name or if the particle is a nullptr, NaN is returned.\n"
2902 "In the latter case please use `eventExtraInfo` if you want to access an EventExtraInfo variable.");
2903 REGISTER_VARIABLE(
"eventExtraInfo(name)", eventExtraInfo,
2904 "[Eventbased] Returns extra info stored under the given name in the event extra info.\n"
2905 "The extraInfo has to be set first by another module like MVAExpert in event mode.\n"
2906 "If nothing is set under this name, NaN is returned.");
2907 REGISTER_VARIABLE(
"eventCached(variable)", eventCached,
2908 "[Eventbased] Returns value of event-based variable and caches this value in the EventExtraInfo.\n"
2909 "The result of second call to this variable in the same event will be provided from the cache.\n"
2910 "It is recommended to use this variable in order to declare custom aliases as event-based. This is "
2911 "necessary if using the eventwise mode of variablesToNtuple).");
2912 REGISTER_VARIABLE(
"particleCached(variable)", particleCached,
2913 "Returns value of given variable and caches this value in the ParticleExtraInfo of the provided particle.\n"
2914 "The result of second call to this variable on the same particle will be provided from the cache.");
2915 REGISTER_VARIABLE(
"modulo(variable, n)", modulo,
2916 "Returns rest of division of variable by n.");
2917 REGISTER_VARIABLE(
"abs(variable)", abs,
2918 "Returns absolute value of the given variable.\n"
2919 "E.g. abs(mcPDG) returns the absolute value of the mcPDG, which is often useful for cuts.");
2920 REGISTER_VARIABLE(
"max(var1,var2)", max,
"Returns max value of two variables.\n");
2921 REGISTER_VARIABLE(
"min(var1,var2)", min,
"Returns min value of two variables.\n");
2922 REGISTER_VARIABLE(
"sin(variable)", sin,
"Returns sine value of the given variable.");
2923 REGISTER_VARIABLE(
"asin(variable)", asin,
"Returns arcsine of the given variable.");
2924 REGISTER_VARIABLE(
"cos(variable)", cos,
"Returns cosine value of the given variable.");
2925 REGISTER_VARIABLE(
"acos(variable)", acos,
"Returns arccosine value of the given variable.");
2926 REGISTER_VARIABLE(
"tan(variable)", tan,
"Returns tangent value of the given variable.");
2927 REGISTER_VARIABLE(
"atan(variable)", atan,
"Returns arctangent value of the given variable.");
2928 REGISTER_VARIABLE(
"exp(variable)", exp,
"Returns exponential evaluated for the given variable.");
2929 REGISTER_VARIABLE(
"log(variable)", log,
"Returns natural logarithm evaluated for the given variable.");
2930 REGISTER_VARIABLE(
"log10(variable)", log10,
"Returns base-10 logarithm evaluated for the given variable.");
2931 REGISTER_VARIABLE(
"isNAN(variable)", isNAN,
2932 "Returns true if variable value evaluates to nan (determined via std::isnan(double)).\n"
2933 "Useful for debugging.");
2934 REGISTER_VARIABLE(
"ifNANgiveX(variable, x)", ifNANgiveX,
2935 "Returns x (has to be a number) if variable value is nan (determined via std::isnan(double)).\n"
2936 "Useful for technical purposes while training MVAs.");
2937 REGISTER_VARIABLE(
"isInfinity(variable)", isInfinity,
2938 "Returns true if variable value evaluates to infinity (determined via std::isinf(double)).\n"
2939 "Useful for debugging.");
2940 REGISTER_VARIABLE(
"unmask(variable, flag1, flag2, ...)", unmask,
2941 "unmask(variable, flag1, flag2, ...) or unmask(variable, mask) sets certain bits in the variable to zero.\n"
2942 "For example, if you want to set the second, fourth and fifth bits to zero, you could call \n"
2943 "``unmask(variable, 2, 8, 16)`` or ``unmask(variable, 26)``.\n"
2945 REGISTER_VARIABLE(
"conditionalVariableSelector(cut, variableIfTrue, variableIfFalse)", conditionalVariableSelector,
2946 "Returns one of the two supplied variables, depending on whether the particle passes the supplied cut.\n"
2947 "The first variable is returned if the particle passes the cut, and the second variable is returned otherwise.");
2948 REGISTER_VARIABLE(
"pValueCombination(p1, p2, ...)", pValueCombination,
2949 "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"
2950 "If any of the p-values is invalid, i.e. smaller than zero, -1 is returned.");
2951 REGISTER_VARIABLE(
"veto(particleList, cut, pdgCode = 11)", veto,
2952 "Combines current particle with particles from the given particle list and returns 1 if the combination passes the provided cut. \n"
2953 "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"
2954 "around the neutral Pion mass (e.g. ``0.130 < M < 0.140``). \n"
2955 "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");
2956 REGISTER_VARIABLE(
"matchedMC(variable)", matchedMC,
2957 "Returns variable output for the matched MCParticle by constructing a temporary Particle from it.\n"
2958 "This may not work too well if your variable requires accessing daughters of the particle.\n"
2959 "E.g. ``matchedMC(p)`` returns the total momentum of the related MCParticle.\n"
2960 "Returns NaN if no matched MCParticle exists.");
2961 REGISTER_VARIABLE(
"countInList(particleList, cut='')", countInList,
"[Eventbased] "
2962 "Returns number of particle which pass given in cut in the specified particle list.\n"
2963 "Useful for creating statistics about the number of particles in a list.\n"
2964 "E.g. ``countInList(e+, isSignal == 1)`` returns the number of correctly reconstructed electrons in the event.\n"
2965 "The variable is event-based and does not need a valid particle pointer as input.");
2966 REGISTER_VARIABLE(
"getVariableByRank(particleList, rankedVariableName, variableName, rank)", getVariableByRank, R
"DOC(
2967 Returns the value of ``variableName`` for the candidate in the ``particleList`` with the requested ``rank``.
2970 The `BestCandidateSelection` module available via `rankByHighest` / `rankByLowest` has to be used before.
2973 The first candidate matching the given rank is used.
2974 Thus, it is not recommended to use this variable in conjunction with ``allowMultiRank`` in the `BestCandidateSelection` module.
2976 The suffix ``_rank`` is automatically added to the argument ``rankedVariableName``,
2977 which either has to be the name of the variable used to order the candidates or the selected outputVariable name without the ending ``_rank``.
2978 This means that your selected name for the rank variable has to end with ``_rank``.
2980 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>`_
2982 REGISTER_VARIABLE("matchedMCHasPDG(PDGCode)", matchedMCHasPDG,
2983 "Returns if the absolute value of aPDGCode of a MCParticle related to a Particle matches a given PDGCode."
2984 "Returns 0/0.5/1 if PDGCode does not match/is not available/ matches");
2985 REGISTER_VARIABLE(
"numberOfNonOverlappingParticles(pList1, pList2, ...)", numberOfNonOverlappingParticles,
2986 "Returns the number of non-overlapping particles in the given particle lists"
2987 "Useful to check if there is additional physics going on in the detector if one reconstructed the Y4S");
2988 REGISTER_VARIABLE(
"totalEnergyOfParticlesInList(particleListName)", totalEnergyOfParticlesInList,
2989 "Returns the total energy of particles in the given particle List.");
2990 REGISTER_VARIABLE(
"totalPxOfParticlesInList(particleListName)", totalPxOfParticlesInList,
2991 "Returns the total momentum Px of particles in the given particle List.");
2992 REGISTER_VARIABLE(
"totalPyOfParticlesInList(particleListName)", totalPyOfParticlesInList,
2993 "Returns the total momentum Py of particles in the given particle List.");
2994 REGISTER_VARIABLE(
"totalPzOfParticlesInList(particleListName)", totalPzOfParticlesInList,
2995 "Returns the total momentum Pz of particles in the given particle List.");
2996 REGISTER_VARIABLE(
"invMassInLists(pList1, pList2, ...)", invMassInLists,
2997 "Returns the invariant mass of the combination of particles in the given particle lists.");
2998 REGISTER_VARIABLE(
"totalECLEnergyOfParticlesInList(particleListName)", totalECLEnergyOfParticlesInList,
2999 "Returns the total ECL energy of particles in the given particle List.");
3000 REGISTER_VARIABLE(
"maxPtInList(particleListName)", maxPtInList,
3001 "Returns maximum transverse momentum Pt in the given particle List.");
3002 REGISTER_VARIABLE(
"eclClusterSpecialTrackMatched(cut)", eclClusterTrackMatchedWithCondition,
3003 "Returns if at least one Track that satisfies the given condition is related to the ECLCluster of the Particle.");
3004 REGISTER_VARIABLE(
"averageValueInList(particleListName, variable)", averageValueInList,
3005 "Returns the arithmetic mean of the given variable of the particles in the given particle list.");
3006 REGISTER_VARIABLE(
"medianValueInList(particleListName, variable)", medianValueInList,
3007 "Returns the median value of the given variable of the particles in the given particle list.");
3008 REGISTER_VARIABLE(
"angleToClosestInList(particleListName)", angleToClosestInList,
3009 "Returns the angle between this particle and the closest particle (smallest opening angle) in the list provided.");
3010 REGISTER_VARIABLE(
"closestInList(particleListName, variable)", closestInList,
3011 "Returns `variable` for the closest particle (smallest opening angle) in the list provided.");
3012 REGISTER_VARIABLE(
"angleToMostB2BInList(particleListName)", angleToMostB2BInList,
3013 "Returns the angle between this particle and the most back-to-back particle (closest opening angle to 180) in the list provided.");
3014 REGISTER_VARIABLE(
"mostB2BInList(particleListName, variable)", mostB2BInList,
3015 "Returns `variable` for the most back-to-back particle (closest opening angle to 180) in the list provided.");
3016 REGISTER_VARIABLE(
"maxOpeningAngleInList(particleListName)", maxOpeningAngleInList,
3017 "Returns maximum opening angle in the given particle List.");
3018 REGISTER_VARIABLE(
"daughterCombination(variable, daughterIndex_1, daughterIndex_2 ... daughterIndex_n)", daughterCombination,R
"DOC(
3019 Returns a ``variable`` function only of the 4-momentum calculated on an arbitrary set of (grand)daughters.
3022 ``variable`` can only be a function of the daughters' 4-momenta.
3024 Daughters from different generations of the decay tree can be combined using generalized daughter indexes, which are simply colon-separated
3025 the list of daughter indexes, starting from the root particle: for example, ``0:1:3`` identifies the fourth
3026 daughter (3) of the second daughter (1) of the first daughter (0) of the mother particle.
3029 ``daughterCombination(M, 0, 3, 4)`` will return the invariant mass of the system made of the first, fourth and fifth daughter of particle.
3030 ``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.
3033 REGISTER_VARIABLE("useAlternativeDaughterHypothesis(variable, daughterIndex_1:newMassHyp_1, ..., daughterIndex_n:newMassHyp_n)", useAlternativeDaughterHypothesis,R
"DOC(
3034 Returns a ``variable`` calculated using new mass hypotheses for (some of) the particle's daughers.
3037 ``variable`` can only be a function of the particle 4-momentum, which is re-calculated as the sum of the daughters' 4-momenta.
3038 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.
3039 Also, the track fit is not performed again: the variable only re-calculates the 4-vectors using different mass assumptions. The alternative mass assumpion is
3040 used only internally by the variable, and is not stored in the datastore (i.e the daughters are not permanently changed).
3043 Generalized daughter indexes are not supported (yet!): this variable can be used only on first-generation daughters.
3046 ``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.
3047 ``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.
3050 REGISTER_VARIABLE("varForFirstMCAncestorOfType(type, variable)",varForFirstMCAncestorOfType,R
"DOC(Returns requested variable of the first ancestor of the given type.
3051 Ancestor type can be set up by PDG code or by particle name (check evt.pdl for valid particle names))DOC")
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.
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
EParticleSourceObject
particle source enumerators
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
static const ReferenceFrame & GetCurrent()
Get current rest frame.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
std::function< double(const Particle *)> FunctionPtr
NOTE: the python interface is documented manually in analysis/doc/Variables.rst (because we use ROOT ...
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.
std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
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.
const std::vector< double > v2
MATLAB generated random vector.
const std::vector< double > v1
MATLAB generated random vector.
FunctionPtr function
Pointer to function.