10#include <analysis/variables/ROEVariables.h>
12#include <analysis/variables/Variables.h>
15#include <framework/datastore/StoreArray.h>
16#include <framework/datastore/StoreObjPtr.h>
19#include <analysis/dataobjects/Particle.h>
20#include <analysis/dataobjects/ParticleList.h>
21#include <mdst/dataobjects/MCParticle.h>
22#include <mdst/dataobjects/ECLCluster.h>
25#include <framework/logging/Logger.h>
26#include <framework/utilities/Conversion.h>
27#include <framework/gearbox/Const.h>
30#include <analysis/utility/PCmsLabTransform.h>
31#include <analysis/utility/ReferenceFrame.h>
35#include <Math/AxisAngle.h>
48 double isInRestOfEvent(
const Particle* particle)
51 StoreObjPtr<RestOfEvent> roeobjptr;
52 if (not roeobjptr.isValid())
55 const RestOfEvent* roe = &(*roeobjptr);
57 return isInThisRestOfEvent(particle, roe);
60 double isCloneOfSignalSide(
const Particle* particle)
63 StoreObjPtr<RestOfEvent> roe;
64 if (not roe.isValid()) {
65 B2WARNING(
"Please use isCloneOfSignalSide variable in for_each ROE loop!");
68 auto* particleMC = particle->getMCParticle();
72 auto* signal = roe->getRelatedFrom<Particle>();
73 auto signalFSPs = signal->getFinalStateDaughters();
74 for (
auto* daughter : signalFSPs) {
75 auto* daughterMC = daughter->getMCParticle();
76 if (daughterMC == particleMC) {
83 double hasAncestorFromSignalSide(
const Particle* particle)
85 StoreObjPtr<RestOfEvent> roe;
87 B2WARNING(
"Please use hasAncestorFromSignalSide variable in for_each ROE loop!");
90 auto* particleMC = particle->getMCParticle();
94 auto* signalReco = roe->getRelatedFrom<Particle>();
95 auto* signalMC = signalReco->getMCParticle();
96 MCParticle* ancestorMC = particleMC->getMother();
98 if (ancestorMC == signalMC) {
101 ancestorMC = ancestorMC->getMother();
108 if (arguments.size() != 1)
109 B2FATAL(
"Wrong number of arguments (1 required) for meta function currentROEIsInList");
111 std::string listName = arguments[0];
113 auto func = [listName](
const Particle*) ->
double {
115 StoreObjPtr<ParticleList> particleList(listName);
116 if (!(particleList.isValid()))
118 B2FATAL(
"Invalid Listname " << listName <<
" given to currentROEIsInList!");
120 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
122 if (not roe.isValid())
125 auto* particle = roe->getRelatedFrom<Particle>();
126 if (particle ==
nullptr)
128 B2ERROR(
"Relation between particle and ROE doesn't exist! currentROEIsInList() variable has to be called from ROE loop");
131 return particleList->contains(particle) ? 1 : 0;
139 if (arguments.size() != 1)
140 B2FATAL(
"Wrong number of arguments (1 required) for meta function particleRelatedToCurrentROE");
143 auto func = [var](
const Particle*) ->
double {
145 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
147 if (not roe.isValid())
150 auto* particle = roe->getRelatedFrom<Particle>();
151 if (particle ==
nullptr)
153 B2ERROR(
"Relation between particle and ROE doesn't exist! particleRelatedToCurrentROE() variable has to be called from ROE loop");
156 if (std::holds_alternative<double>(var->function(particle)))
158 return std::get<double>(var->function(particle));
159 }
else if (std::holds_alternative<int>(var->function(particle)))
161 return std::get<int>(var->function(particle));
162 }
else if (std::holds_alternative<bool>(var->function(particle)))
164 return std::get<bool>(var->function(particle));
173 if (arguments.size() == 1) {
175 auto func = [var](
const Particle * particle) ->
double {
177 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
181 StoreObjPtr<RestOfEvent> roeObjPtr(
"RestOfEvent");
182 if (roeObjPtr.isValid()) {
188 B2ERROR(
"Neither relation between particle and ROE doesn't exist nor ROE object has not been found!");
192 ROOT::Math::PxPyPzEVector pRecoil = T.getBeamFourMomentum() - roe->get4Vector();
193 Particle tmp(pRecoil, 0);
194 UseReferenceFrame<RestFrame> frame(&tmp);
195 if (std::holds_alternative<double>(var->function(particle)))
197 return std::get<double>(var->function(particle));
198 }
else if (std::holds_alternative<int>(var->function(particle)))
200 return std::get<int>(var->function(particle));
201 }
else if (std::holds_alternative<bool>(var->function(particle)))
203 return std::get<bool>(var->function(particle));
208 B2WARNING(
"Wrong number of arguments for meta function useROERecoilFrame");
214 int nRemainingTracksInROE(
const Particle* particle,
const std::string& maskName)
216 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
217 if (not roe.isValid())
219 int n_roe_tracks = roe->getNTracks(maskName);
220 int n_par_tracks = 0;
221 const auto& daughters = particle->getFinalStateDaughters();
222 for (
const auto& daughter : daughters) {
223 if (daughter->getParticleSource() == Particle::EParticleSourceObject::c_Track && roe->hasParticle(daughter, maskName)) {
227 return n_roe_tracks - n_par_tracks;
234 if (arguments.size() == 1)
235 maskName = arguments[0];
236 else if (arguments.size() > 1)
237 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROETracks");
239 auto func = [maskName](
const Particle * particle) ->
int {
240 return nRemainingTracksInROE(particle, maskName);
245 int nROE_RemainingTracks(
const Particle* particle)
247 return nRemainingTracksInROE(particle);
250 double nROE_KLMClusters(
const Particle* particle)
253 const RestOfEvent* roe = getRelatedROEObject(particle);
256 B2ERROR(
"Relation between particle and ROE doesn't exist!");
260 return roe->getNKLMClusters();
263 double ROE_MC_E(
const Particle* particle)
271 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
272 auto mcroe4vector = boostvec - mcp->get4Vector();
274 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
275 return frameMCRoe4Vector.energy();
278 double ROE_MC_P(
const Particle* particle)
286 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
287 auto mcroe4vector = boostvec - mcp->get4Vector();
289 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
290 return frameMCRoe4Vector.P();
293 double ROE_MC_Px(
const Particle* particle)
301 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
302 auto mcroe4vector = boostvec - mcp->get4Vector();
304 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
306 return frameMCRoe4Vector.px();
309 double ROE_MC_Py(
const Particle* particle)
317 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
318 auto mcroe4vector = boostvec - mcp->get4Vector();
320 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
322 return frameMCRoe4Vector.py();
325 double ROE_MC_Pz(
const Particle* particle)
333 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
334 auto mcroe4vector = boostvec - mcp->get4Vector();
336 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
338 return frameMCRoe4Vector.pz();
341 double ROE_MC_Pt(
const Particle* particle)
349 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
350 auto mcroe4vector = boostvec - mcp->get4Vector();
352 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
354 return frameMCRoe4Vector.pt();
357 double ROE_MC_PTheta(
const Particle* particle)
365 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
366 auto mcroe4vector = boostvec - mcp->get4Vector();
368 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
370 return frameMCRoe4Vector.Theta();
373 double ROE_MC_M(
const Particle* particle)
381 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
383 return (boostvec - mcp->get4Vector()).M();
390 if (arguments.size() == 1)
391 maskName = arguments[0];
392 else if (arguments.size() > 1)
393 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROETracks");
395 auto func = [maskName](
const Particle * particle) ->
double {
397 StoreArray<Particle> particles;
406 const MCParticle* mcMother = mcParticle->getMother();
412 std::vector<MCParticle*> mcDaughters = mcMother->getDaughters();
414 if (mcDaughters.size() != 2)
418 MCParticle* mcROE =
nullptr;
419 if (mcDaughters[0]->getArrayIndex() == mcParticle->getArrayIndex())
420 mcROE = mcDaughters[1];
422 mcROE = mcDaughters[0];
425 const RestOfEvent* roe = getRelatedROEObject(particle);
427 std::set<const MCParticle*> mcROEObjects;
429 auto roeParticles = roe->getParticles(maskName);
430 for (
auto* roeParticle : roeParticles)
432 auto* mcroeParticle = roeParticle->getMCParticle();
433 if (mcroeParticle !=
nullptr) {
434 mcROEObjects.insert(mcroeParticle);
438 checkMCParticleMissingFlags(mcROE, mcROEObjects, flags);
449 if (arguments.size() == 1)
450 maskName = arguments[0];
451 else if (arguments.size() > 1)
452 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROETracks");
454 auto func = [maskName](
const Particle * particle) ->
double {
457 const RestOfEvent* roe = getRelatedROEObject(particle);
461 B2ERROR(
"Relation between particle and ROE doesn't exist!");
465 return roe->getNTracks(maskName);
474 if (arguments.size() == 1)
475 maskName = arguments[0];
476 else if (arguments.size() > 1)
477 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROEECLClusters");
479 auto func = [maskName](
const Particle * particle) ->
double {
482 const RestOfEvent* roe = getRelatedROEObject(particle);
486 B2ERROR(
"Relation between particle and ROE doesn't exist!");
490 return roe->getNECLClusters(maskName);
499 if (arguments.size() == 1)
500 maskName = arguments[0];
501 else if (arguments.size() > 1)
502 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROENeutralECLClusters");
504 auto func = [maskName](
const Particle * particle) ->
double {
507 const RestOfEvent* roe = getRelatedROEObject(particle);
511 B2ERROR(
"Relation between particle and ROE doesn't exist!");
515 return roe->getPhotons(maskName).size();
524 if (arguments.size() == 1) {
525 maskName = arguments[0];
526 }
else if (arguments.size() > 1) {
527 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROE_Photons");
529 auto func = [maskName](
const Particle * particle) ->
double {
532 const RestOfEvent* roe = getRelatedROEObject(particle);
536 B2ERROR(
"Relation between particle and ROE doesn't exist!");
541 auto roeClusters = roe->getPhotons(maskName);
545 for (
auto& roeCluster : roeClusters)
557 if (arguments.size() == 1) {
558 maskName = arguments[0];
559 }
else if (arguments.size() > 1) {
560 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROE_NeutralHadrons");
562 auto func = [maskName](
const Particle * particle) ->
double {
565 const RestOfEvent* roe = getRelatedROEObject(particle);
569 B2ERROR(
"Relation between particle and ROE doesn't exist!");
573 return roe->getHadrons(maskName).size();
582 if (arguments.size() == 1) {
583 maskName = arguments[0];
584 }
else if (arguments.size() == 2) {
585 maskName = arguments[0];
587 pdgCode = Belle2::convertString<int>(arguments[1]);
588 }
catch (std::invalid_argument&) {
589 B2ERROR(
"First argument of nROE_ChargedParticles must be a PDG code");
592 }
else if (arguments.size() > 2) {
593 B2FATAL(
"Wrong number of arguments (2 optional) for meta function nROE_ChargedParticles");
595 auto func = [maskName, pdgCode](
const Particle * particle) ->
double {
598 const RestOfEvent* roe = getRelatedROEObject(particle);
602 B2ERROR(
"Relation between particle and ROE doesn't exist!");
606 return roe->getChargedParticles(maskName, abs(pdgCode)).size();
615 if (arguments.size() == 1) {
616 maskName = arguments[0];
617 }
else if (arguments.size() > 1) {
618 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROE_Composites");
620 auto func = [maskName](
const Particle * particle) ->
double {
623 const RestOfEvent* roe = getRelatedROEObject(particle);
627 B2ERROR(
"Relation between particle and ROE doesn't exist!");
631 auto particles = roe->getParticles(maskName,
false);
633 for (
auto roeParticle : particles)
635 if (roeParticle->getParticleSource() == Particle::c_Composite or
636 roeParticle->getParticleSource() == Particle::c_V0) {
647 std::string pListName;
650 if (arguments.size() == 1) {
651 pListName = arguments[0];
652 }
else if (arguments.size() == 2) {
653 pListName = arguments[0];
654 maskName = arguments[1];
656 B2FATAL(
"Wrong number of arguments (1 or 2 required) for meta function nROE_ParticlesInList");
658 auto func = [pListName, maskName](
const Particle * particle) ->
double {
661 const RestOfEvent* roe = getRelatedROEObject(particle);
665 B2ERROR(
"Relation between particle and ROE doesn't exist!");
672 StoreObjPtr<ParticleList> pList(pListName);
673 if (!pList.isValid())
674 B2FATAL(
"ParticleList " << pListName <<
" could not be found or is not valid!");
676 for (
unsigned int i = 0; i < pList->getListSize(); i++)
678 const Particle* part = pList->getParticle(i);
679 if (isInThisRestOfEvent(part, roe, maskName))
692 if (arguments.size() == 1)
693 maskName = arguments[0];
694 else if (arguments.size() > 1)
695 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROECharge");
697 auto func = [maskName](
const Particle * particle) ->
double {
700 const RestOfEvent* roe = getRelatedROEObject(particle);
704 B2ERROR(
"Relation between particle and ROE doesn't exist!");
709 auto roeParticles = roe->getParticles(maskName);
712 for (
auto* roeParticle : roeParticles)
714 roeCharge += roeParticle->getCharge();
726 if (arguments.size() == 1)
727 maskName = arguments[0];
728 else if (arguments.size() > 1)
729 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function extraEnergy");
731 auto func = [maskName](
const Particle * particle) ->
double {
734 const RestOfEvent* roe = getRelatedROEObject(particle);
738 B2ERROR(
"Relation between particle and ROE doesn't exist!");
744 auto roeClusters = roe->getPhotons(maskName);
746 for (
auto& roeCluster : roeClusters)
748 extraE += roeCluster->getECLClusterEnergy();
750 auto roeChargedParticles = roe->getChargedParticles(maskName);
752 for (
auto& roeChargedParticle : roeChargedParticles)
754 if (roeChargedParticle->getECLCluster())
755 extraE += roeChargedParticle->getECLClusterEnergy();
767 if (arguments.size() == 1)
768 maskName = arguments[0];
769 else if (arguments.size() > 1)
770 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function extraEnergy");
772 auto func = [maskName](
const Particle * particle) ->
double {
775 const RestOfEvent* roe = getRelatedROEObject(particle);
779 B2ERROR(
"Relation between particle and ROE doesn't exist!");
782 auto roephotons = roe->getPhotons(maskName);
783 ROOT::Math::PxPyPzEVector total4vector;
784 for (
auto* photon : roephotons)
786 total4vector += photon->get4Vector();
789 auto frameRoe4Vector = frame.getMomentum(total4vector);
790 return frameRoe4Vector.energy();
799 if (arguments.size() == 1)
800 maskName = arguments[0];
801 else if (arguments.size() > 1)
802 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_E");
804 auto func = [maskName](
const Particle * particle) ->
double {
805 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
808 B2ERROR(
"Relation between particle and ROE doesn't exist!");
812 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
813 return frameRoe4Vector.energy();
822 if (arguments.size() == 1)
823 maskName = arguments[0];
824 else if (arguments.size() > 1)
825 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_M");
827 auto func = [maskName](
const Particle * particle) ->
double {
830 const RestOfEvent* roe = getRelatedROEObject(particle);
834 B2ERROR(
"Relation between particle and ROE doesn't exist!");
838 return roe->get4Vector(maskName).M();
847 if (arguments.size() == 1)
848 maskName = arguments[0];
849 else if (arguments.size() > 1)
850 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_P");
852 auto func = [maskName](
const Particle * particle) ->
double {
855 const RestOfEvent* roe = getRelatedROEObject(particle);
859 B2ERROR(
"Relation between particle and ROE doesn't exist!");
864 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
865 return frameRoe4Vector.P();
874 if (arguments.size() == 1)
875 maskName = arguments[0];
876 else if (arguments.size() > 1)
877 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Px");
879 auto func = [maskName](
const Particle * particle) ->
double {
882 const RestOfEvent* roe = getRelatedROEObject(particle);
886 B2ERROR(
"Relation between particle and ROE doesn't exist!");
891 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
892 return frameRoe4Vector.px();
901 if (arguments.size() == 1)
902 maskName = arguments[0];
903 else if (arguments.size() > 1)
904 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Py");
906 auto func = [maskName](
const Particle * particle) ->
double {
909 const RestOfEvent* roe = getRelatedROEObject(particle);
913 B2ERROR(
"Relation between particle and ROE doesn't exist!");
918 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
919 return frameRoe4Vector.py();
928 if (arguments.size() == 1)
929 maskName = arguments[0];
930 else if (arguments.size() > 1)
931 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Pt");
933 auto func = [maskName](
const Particle * particle) ->
double {
936 const RestOfEvent* roe = getRelatedROEObject(particle);
940 B2ERROR(
"Relation between particle and ROE doesn't exist!");
945 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
946 return frameRoe4Vector.pt();
955 if (arguments.size() == 1)
956 maskName = arguments[0];
957 else if (arguments.size() > 1)
958 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Pz");
960 auto func = [maskName](
const Particle * particle) ->
double {
963 const RestOfEvent* roe = getRelatedROEObject(particle);
967 B2ERROR(
"Relation between particle and ROE doesn't exist!");
972 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
973 return frameRoe4Vector.pz();
982 if (arguments.size() == 1)
983 maskName = arguments[0];
984 else if (arguments.size() > 1)
985 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_PTheta");
987 auto func = [maskName](
const Particle * particle) ->
double {
990 const RestOfEvent* roe = getRelatedROEObject(particle);
994 B2ERROR(
"Relation between particle and ROE doesn't exist!");
999 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
1000 return frameRoe4Vector.Theta();
1009 if (arguments.size() == 1)
1010 maskName = arguments[0];
1011 else if (arguments.size() > 1)
1012 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_deltae");
1014 auto func = [maskName](
const Particle * particle) ->
double {
1017 const RestOfEvent* roe = getRelatedROEObject(particle);
1021 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1026 ROOT::Math::PxPyPzEVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1027 return vec.E() - T.getCMSEnergy() / 2;
1036 if (arguments.size() == 1)
1037 maskName = arguments[0];
1038 else if (arguments.size() > 1)
1039 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_mbc");
1041 auto func = [maskName](
const Particle * particle) ->
double {
1044 const RestOfEvent* roe = getRelatedROEObject(particle);
1048 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1053 ROOT::Math::PxPyPzEVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1055 double E = T.getCMSEnergy() / 2;
1056 double m2 = E * E - vec.P2();
1057 double mbc = m2 > 0 ? sqrt(m2) : 0;
1068 if (arguments.size() == 1)
1069 maskName = arguments[0];
1070 else if (arguments.size() > 1)
1071 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function bssMassDifference");
1073 auto func = [maskName](
const Particle * particle) ->
double {
1076 ROOT::Math::PxPyPzEVector neutrino4vec = missing4Vector(particle->getDaughter(0), maskName,
"6");
1077 ROOT::Math::PxPyPzEVector sig4vec = particle->getDaughter(0)->get4Vector();
1079 ROOT::Math::PxPyPzEVector bsMom = neutrino4vec + sig4vec;
1080 ROOT::Math::PxPyPzEVector bssMom = bsMom + particle->getDaughter(1)->get4Vector();
1082 return bssMom.M() - bsMom.M();
1089 std::string maskName;
1092 if (arguments.size() == 1) {
1095 }
else if (arguments.size() == 2) {
1096 maskName = arguments[0];
1099 B2FATAL(
"Wrong number of arguments (2 required) for meta function correctedB_deltae");
1101 auto func = [maskName, opt](
const Particle * particle) ->
double {
1104 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
1105 ROOT::Math::PxPyPzEVector sig4vec = T.rotateLabToCms() * particle->get4Vector();
1106 ROOT::Math::PxPyPzEVector sig4vecLAB = particle->get4Vector();
1107 ROOT::Math::PxPyPzEVector neutrino4vec = missing4Vector(particle, maskName,
"1");
1108 ROOT::Math::PxPyPzEVector neutrino4vecLAB = missing4Vector(particle, maskName,
"6");
1115 double totalSigEnergy = (sig4vec + neutrino4vec).energy();
1116 double E = T.getCMSEnergy() / 2;
1117 deltaE = totalSigEnergy - E;
1121 else if (opt ==
"1")
1123 double Ecms = T.getCMSEnergy();
1124 double s = Ecms * Ecms;
1125 deltaE = ((sig4vecLAB + neutrino4vecLAB).Dot(boostvec) - s / 2.0) / sqrt(s);
1129 B2FATAL(
"Option for correctedB_deltae variable should only be 0/1 (CMS/LAB)");
1138 std::string maskName;
1141 if (arguments.size() == 1) {
1144 }
else if (arguments.size() == 2) {
1145 maskName = arguments[0];
1148 B2FATAL(
"Wrong number of arguments (2 required) for meta function correctedB_mbc");
1150 auto func = [maskName, opt](
const Particle * particle) ->
double {
1153 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
1154 ROOT::Math::PxPyPzEVector sig4vec = T.rotateLabToCms() * particle->get4Vector();
1155 ROOT::Math::PxPyPzEVector sig4vecLAB = particle->get4Vector();
1156 ROOT::Math::PxPyPzEVector neutrino4vec;
1163 neutrino4vec = missing4Vector(particle, maskName,
"1");
1164 B2Vector3D bmom = (sig4vec + neutrino4vec).Vect();
1165 double E = T.getCMSEnergy() / 2;
1166 double m2 = E * E - bmom.
Mag2();
1167 mbc = m2 > 0 ? sqrt(m2) : 0;
1171 else if (opt ==
"1")
1173 neutrino4vec = missing4Vector(particle, maskName,
"6");
1174 B2Vector3D bmom = (sig4vecLAB + neutrino4vec).Vect();
1175 double Ecms = T.getCMSEnergy();
1176 double s = Ecms * Ecms;
1177 double m2 = pow((s / 2.0 + bmom *
B2Vector3D(boostvec.Vect())) / boostvec.energy(), 2.0) - bmom.
Mag2();
1178 mbc = m2 > 0 ? sqrt(m2) : 0;
1182 else if (opt ==
"2")
1184 neutrino4vec = missing4Vector(particle, maskName,
"7");
1185 B2Vector3D bmom = (sig4vec + neutrino4vec).Vect();
1186 double E = T.getCMSEnergy() / 2;
1187 double m2 = E * E - bmom.
Mag2();
1188 mbc = m2 > 0 ? sqrt(m2) : 0;
1192 B2FATAL(
"Option for correctedB_mbc variable should only be 0/1/2 (CMS/LAB/CMS with factor)");
1201 std::string maskName;
1204 if (arguments.size() == 1) {
1207 }
else if (arguments.size() == 2) {
1208 maskName = arguments[0];
1211 B2FATAL(
"Wrong number of arguments (2 required) for meta function missM2");
1213 auto func = [maskName, opt](
const Particle * particle) ->
double {
1215 return missing4Vector(particle, maskName, opt).M2();
1222 std::string maskName;
1225 if (arguments.size() == 1) {
1228 }
else if (arguments.size() == 2) {
1229 maskName = arguments[0];
1232 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPTheta");
1234 auto func = [maskName, opt](
const Particle * particle) ->
double {
1237 const RestOfEvent* roe = getRelatedROEObject(particle);
1241 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1245 return missing4Vector(particle, maskName, opt).Theta();
1252 std::string maskName;
1255 if (arguments.size() == 1) {
1258 }
else if (arguments.size() == 2) {
1259 maskName = arguments[0];
1262 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissP");
1264 auto func = [maskName, opt](
const Particle * particle) ->
double {
1267 const RestOfEvent* roe = getRelatedROEObject(particle);
1271 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1275 return missing4Vector(particle, maskName, opt).P();
1282 std::string maskName;
1285 if (arguments.size() == 1) {
1288 }
else if (arguments.size() == 2) {
1289 maskName = arguments[0];
1292 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPx");
1294 auto func = [maskName, opt](
const Particle * particle) ->
double {
1297 const RestOfEvent* roe = getRelatedROEObject(particle);
1301 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1305 return missing4Vector(particle, maskName, opt).Px();
1312 std::string maskName;
1315 if (arguments.size() == 1) {
1318 }
else if (arguments.size() == 2) {
1319 maskName = arguments[0];
1322 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPy");
1324 auto func = [maskName, opt](
const Particle * particle) ->
double {
1327 const RestOfEvent* roe = getRelatedROEObject(particle);
1331 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1335 return missing4Vector(particle, maskName, opt).Py();
1342 std::string maskName;
1345 if (arguments.size() == 1) {
1348 }
else if (arguments.size() == 2) {
1349 maskName = arguments[0];
1352 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPz");
1354 auto func = [maskName, opt](
const Particle * particle) ->
double {
1357 const RestOfEvent* roe = getRelatedROEObject(particle);
1361 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1365 return missing4Vector(particle, maskName, opt).Pz();
1372 std::string maskName;
1375 if (arguments.size() == 1) {
1378 }
else if (arguments.size() == 2) {
1379 maskName = arguments[0];
1382 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissE");
1384 auto func = [maskName, opt](
const Particle * particle) ->
double {
1387 const RestOfEvent* roe = getRelatedROEObject(particle);
1391 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1395 return missing4Vector(particle, maskName, opt).energy();
1404 if (arguments.size() == 1)
1405 maskName = arguments[0];
1406 else if (arguments.size() > 1)
1407 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function xiZ");
1409 auto func = [maskName](
const Particle * particle) ->
double {
1412 const RestOfEvent* roe = getRelatedROEObject(particle);
1416 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1424 std::vector<const Particle*> recTrackParticles = particle->getFinalStateDaughters();
1427 for (
auto& recTrackParticle : recTrackParticles)
1429 pz += recTrackParticle->getPz();
1430 energy += recTrackParticle->getEnergy();
1434 auto roeParticles = roe->getChargedParticles(maskName);
1435 for (
auto* roeParticle : roeParticles)
1437 pz += roeParticle->getPz();
1438 energy += roeParticle->getEnergy();
1450 if (arguments.size() == 1)
1451 maskName = arguments[0];
1452 else if (arguments.size() > 1)
1453 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function WE_MissM2OverMissE");
1455 auto func = [maskName](
const Particle * particle) ->
double {
1458 const RestOfEvent* roe = getRelatedROEObject(particle);
1462 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1466 return missing4Vector(particle, maskName,
"5").M2() / (2.0 * missing4Vector(particle, maskName,
"5").energy());
1474 std::string option(
"1");
1476 if (arguments.size() == 1) {
1477 maskName = arguments[0];
1478 }
else if (arguments.size() == 2) {
1479 maskName = arguments[0];
1480 option = arguments[1];
1481 }
else if (arguments.size() > 2) {
1482 B2FATAL(
"Too many arguments. At most two arguments are allowed for meta function q2lnuSimple(maskname,option)");
1485 auto func = [maskName, option](
const Particle * particle) ->
double {
1488 const RestOfEvent* roe = getRelatedROEObject(particle);
1492 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1496 int n = particle->getNDaughters();
1503 const Particle* lep = particle->getDaughter(n - 1);
1504 ROOT::Math::PxPyPzEVector lep4vec = T.rotateLabToCms() * lep->get4Vector();
1505 ROOT::Math::PxPyPzEVector nu4vec = missing4Vector(particle, maskName, option);
1507 return (lep4vec + nu4vec).M2();
1515 std::string option(
"7");
1517 if (arguments.size() == 1) {
1518 maskName = arguments[0];
1519 }
else if (arguments.size() == 2) {
1520 maskName = arguments[0];
1521 option = arguments[1];
1522 }
else if (arguments.size() > 2) {
1523 B2FATAL(
"Too many arguments. At most two arguments are allowed for meta function q2lnu(maskname, option)");
1526 auto func = [maskName, option](
const Particle * particle) ->
double {
1529 const RestOfEvent* roe = getRelatedROEObject(particle);
1533 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1537 int n = particle->getNDaughters();
1543 const Particle* lep = particle->getDaughter(n - 1);
1544 ROOT::Math::PxPyPzEVector lep_cm = T.rotateLabToCms() * lep->get4Vector();
1546 ROOT::Math::PxPyPzEVector Y_cm = T.rotateLabToCms() * particle->get4Vector();
1547 ROOT::Math::PxPyPzEVector neu_cm = missing4Vector(particle, maskName, option);
1549 double e_beam = T.getCMSEnergy() / 2.0;
1552 double bmass = particle->getPDGMass();
1553 double pB2 = e_beam * e_beam - bmass * bmass;
1556 double cos_angle_nu = (pB2 - Y_cm.P2() - neu_cm.P2()) / (2.0 * Y_cm.P() * neu_cm.P());
1557 if (abs(cos_angle_nu) > 1)
1559 return (lep_cm + neu_cm).M2();
1562 double angle_nu = TMath::ACos(cos_angle_nu);
1564 ROOT::Math::PtEtaPhiEVector rotated_neu(-Y_cm);
1565 rotated_neu.SetE(Y_cm.E());
1567 double nu_eta = -log(tan((rotated_neu.Theta() + (TMath::Pi() - angle_nu)) / 2.));
1568 rotated_neu.SetEta(nu_eta);
1569 rotated_neu.SetPt(neu_cm.pt());
1570 rotated_neu.SetE(neu_cm.E());
1577 double rot_angle = Yneu_norm.
Angle(Yrot_norm);
1579 ROOT::Math::PxPyPzEVector rotated_neu2(rotated_neu);
1585 ROOT::Math::AxisAngle rotation(Y_cm.Vect(), rot_angle);
1586 rotation(rotated_neu);
1588 rotation(rotated_neu2);
1590 double dot1 = rotated_neu.Vect().Dot(Yneu_norm);
1591 double dot2 = rotated_neu2.Vect().Dot(Yneu_norm);
1593 if (abs(dot2) < abs(dot1)) rotated_neu = rotated_neu2;
1595 return (lep_cm + rotated_neu).M2();
1604 if (arguments.size() == 1)
1605 maskName = arguments[0];
1606 else if (arguments.size() > 1)
1607 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function cosThetaEll");
1609 auto func = [maskName](
const Particle * particle) ->
double {
1611 ROOT::Math::PxPyPzEVector pNu = missing4Vector(particle, maskName,
"6");
1613 ROOT::Math::PxPyPzEVector pLep;
1615 for (
unsigned i = 0; i < particle->getNDaughters(); i++)
1617 int absPDG = abs(particle->getDaughter(i)->getPDGCode());
1619 pLep = particle->getDaughter(i)->get4Vector();
1624 ROOT::Math::PxPyPzEVector pW = pNu + pLep;
1625 ROOT::Math::PxPyPzEVector pB = particle->get4Vector() + pNu;
1629 pLep = ROOT::Math::Boost(boost2W) * pLep;
1630 pB = ROOT::Math::Boost(boost2W) * pB;
1634 double numerator = lep3Vector.Dot(B3Vector);
1635 double denominator = (lep3Vector.Mag()) * (B3Vector.Mag());
1637 return numerator / denominator;
1646 if (arguments.size() == 1)
1647 maskName = arguments[0];
1648 else if (arguments.size() > 1)
1649 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function passesROEMask");
1651 auto func = [maskName](
const Particle * particle) ->
double {
1655 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
1656 if (not roe.isValid())
1659 if (roe->hasParticle(particle, maskName))
1669 double printROE(
const Particle* particle)
1671 const RestOfEvent* roe = getRelatedROEObject(particle);
1674 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1675 }
else roe->print();
1679 double hasCorrectROECombination(
const Particle* particle)
1681 unsigned nDaughters = particle->getNDaughters();
1682 if (nDaughters < 2) {
1683 B2ERROR(
"The particle must have at least two daughters.");
1687 for (
unsigned i = 0; i < particle->getNDaughters(); i++) {
1690 auto daughter = particle->getDaughter(i);
1691 auto roe = daughter->getRelatedFrom<RestOfEvent>();
1695 auto sourceParticle = roe->getRelatedFrom<Particle>();
1696 for (
unsigned j = 0; j < particle->getNDaughters(); j++) {
1697 if (i == j)
continue;
1698 const auto anotherDaughter = particle->getDaughter(j);
1700 if (anotherDaughter == sourceParticle)
1706 B2ERROR(
"There is no daughter particle loaded from the ROE object.");
1712 if (arguments.size() != 1)
1713 B2ERROR(
"Wrong number of arguments (1 required) for pi0Prob");
1716 mode = arguments[0];
1718 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both" and mode !=
"standardMC15rd"
1719 and mode !=
"tightMC15rd")
1720 B2ERROR(
"the given argument is not supported in pi0Prob!");
1722 auto func = [mode](
const Particle * particle) ->
double {
1723 if (mode ==
"standard")
1725 if (particle->hasExtraInfo(
"Pi0ProbOrigin")) {
1726 return particle->getExtraInfo(
"Pi0ProbOrigin");
1728 B2WARNING(
"Pi0ProbOrigin is not registerted in extraInfo! \n"
1729 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1732 }
else if (mode ==
"tight")
1734 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThreshold")) {
1735 return particle->getExtraInfo(
"Pi0ProbTightEnergyThreshold");
1737 B2WARNING(
"Pi0ProbTightEnergyThreshold is not registerted in extraInfo! \n"
1738 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1741 }
else if (mode ==
"cluster")
1743 if (particle->hasExtraInfo(
"Pi0ProbLargeClusterSize")) {
1744 return particle->getExtraInfo(
"Pi0ProbLargeClusterSize");
1746 B2WARNING(
"Pi0ProbLargeClusterSize is not registerted in extraInfo! \n"
1747 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1750 }
else if (mode ==
"both")
1752 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize")) {
1753 return particle->getExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize");
1755 B2WARNING(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1756 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1759 }
else if (mode ==
"standardMC15rd")
1761 if (particle->hasExtraInfo(
"Pi0ProbOriginMC15rd")) {
1762 return particle->getExtraInfo(
"Pi0ProbOriginMC15rd");
1764 B2WARNING(
"Pi0ProbOriginMC15rd is not registerted in extraInfo! \n"
1765 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1768 }
else if (mode ==
"tightMC15rd")
1770 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThresholdMC15rd")) {
1771 return particle->getExtraInfo(
"Pi0ProbTightEnergyThresholdMC15rd");
1773 B2WARNING(
"Pi0ProbTightEnergyThresholdMC15rd is not registerted in extraInfo! \n"
1774 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1787 if (arguments.size() != 1)
1788 B2ERROR(
"Wrong number of arguments (1 required) for etaProb");
1791 mode = arguments[0];
1793 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both" and mode !=
"standardMC15rd"
1794 and mode !=
"tightMC15rd")
1795 B2ERROR(
"the given argument is not supported in etaProb!");
1797 auto func = [mode](
const Particle * particle) ->
double {
1798 if (mode ==
"standard")
1800 if (particle->hasExtraInfo(
"EtaProbOrigin")) {
1801 return particle->getExtraInfo(
"EtaProbOrigin");
1803 B2WARNING(
"EtaProbOrigin is not registerted in extraInfo! \n"
1804 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1807 }
else if (mode ==
"tight")
1809 if (particle->hasExtraInfo(
"EtaProbTightEnergyThreshold")) {
1810 return particle->getExtraInfo(
"EtaProbTightEnergyThreshold");
1812 B2WARNING(
"EtaProbTightEnergyThreshold is not registerted in extraInfo! \n"
1813 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1816 }
else if (mode ==
"cluster")
1818 if (particle->hasExtraInfo(
"EtaProbLargeClusterSize")) {
1819 return particle->getExtraInfo(
"EtaProbLargeClusterSize");
1821 B2WARNING(
"EtaProbLargeClusterSize is not registerted in extraInfo! \n"
1822 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1825 }
else if (mode ==
"both")
1827 if (particle->hasExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize")) {
1828 return particle->getExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize");
1830 B2WARNING(
"EtaProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1831 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1834 }
else if (mode ==
"standardMC15rd")
1836 if (particle->hasExtraInfo(
"EtaProbOriginMC15rd")) {
1837 return particle->getExtraInfo(
"EtaProbOriginMC15rd");
1839 B2WARNING(
"EtaProbOriginMC15rd is not registerted in extraInfo! \n"
1840 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1843 }
else if (mode ==
"tightMC15rd")
1845 if (particle->hasExtraInfo(
"EtaProbTightEnergyThresholdMC15rd")) {
1846 return particle->getExtraInfo(
"EtaProbTightEnergyThresholdMC15rd");
1848 B2WARNING(
"EtaProbTightEnergyThresholdMC15rd is not registerted in extraInfo! \n"
1849 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1864 ROOT::Math::PxPyPzEVector missing4Vector(
const Particle* particle,
const std::string& maskName,
const std::string& opt)
1867 const RestOfEvent* roe = getRelatedROEObject(particle);
1870 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1871 ROOT::Math::PxPyPzEVector empty;
1876 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
1878 ROOT::Math::PxPyPzEVector rec4vecLAB = particle->get4Vector();
1879 ROOT::Math::PxPyPzEVector roe4vecLAB = roe->get4Vector(maskName);
1881 ROOT::Math::PxPyPzEVector rec4vec = T.rotateLabToCms() * rec4vecLAB;
1882 ROOT::Math::PxPyPzEVector roe4vec = T.rotateLabToCms() * roe4vecLAB;
1884 ROOT::Math::PxPyPzEVector miss4vec;
1885 double E_beam_cms = T.getCMSEnergy() / 2.0;
1889 miss4vec = - (rec4vec + roe4vec);
1890 miss4vec.SetE(2 * E_beam_cms - (rec4vec.E() + roe4vec.E()));
1894 else if (opt ==
"1") {
1895 miss4vec = - (rec4vec + roe4vec);
1896 miss4vec.SetE(miss4vec.P());
1900 else if (opt ==
"2") {
1901 miss4vec = - (rec4vec + roe4vec);
1902 miss4vec.SetE(E_beam_cms - rec4vec.E());
1906 else if (opt ==
"3") {
1907 miss4vec = - rec4vec;
1908 miss4vec.SetE(E_beam_cms - rec4vec.E());
1912 else if (opt ==
"4") {
1915 pB -= rec4vec.Vect();
1916 miss4vec.SetPxPyPzE(pB.X(), pB.Y(), pB.Z(), E_beam_cms - rec4vec.E());
1920 else if (opt ==
"5") {
1921 miss4vec = boostvec - (rec4vecLAB + roe4vecLAB);
1925 else if (opt ==
"6") {
1926 miss4vec = boostvec - (rec4vecLAB + roe4vecLAB);
1927 miss4vec.SetE(miss4vec.P());
1931 else if (opt ==
"7") {
1932 miss4vec = - (rec4vec + roe4vec);
1933 miss4vec.SetE(miss4vec.P());
1934 double factorAlpha = (E_beam_cms - rec4vec.E()) / miss4vec.E();
1935 miss4vec *= factorAlpha;
1936 miss4vec.SetE(miss4vec.P());
1942 void checkMCParticleMissingFlags(
const MCParticle* mcp, std::set<const MCParticle*> mcROEObjects,
int& missingFlags)
1944 std::vector<MCParticle*> daughters = mcp->getDaughters();
1945 for (
auto& daughter : daughters) {
1950 if (mcROEObjects.find(daughter) == mcROEObjects.end()) {
1952 int pdg = abs(daughter->getPDG());
1955 if (pdg ==
Const::photon.getPDGCode() and (missingFlags & 1) == 0)
1959 else if (pdg ==
Const::electron.getPDGCode() and (missingFlags & 2) == 0)
1963 else if (pdg ==
Const::muon.getPDGCode() and (missingFlags & 4) == 0)
1967 else if (pdg ==
Const::pion.getPDGCode() and (missingFlags & 8) == 0)
1971 else if (pdg ==
Const::kaon.getPDGCode() and (missingFlags & 16) == 0)
1975 else if (pdg ==
Const::proton.getPDGCode() and (missingFlags & 32) == 0)
1979 else if (pdg ==
Const::neutron.getPDGCode() and (missingFlags & 64) == 0)
1983 else if (pdg ==
Const::Kshort.getPDGCode() and ((missingFlags & 128) == 0 or (missingFlags & 256) == 0)) {
1984 std::vector<MCParticle*> ksDaug = daughter->getDaughters();
1985 if (ksDaug.size() == 2) {
1987 if (abs(ksDaug[0]->getPDG()) ==
Const::pion.getPDGCode() and abs(ksDaug[1]->getPDG()) ==
Const::pion.getPDGCode()
1988 and (missingFlags & 128) == 0) {
1989 if (mcROEObjects.find(ksDaug[0]) == mcROEObjects.end() or mcROEObjects.find(ksDaug[1]) == mcROEObjects.end())
1990 missingFlags += 128;
1993 else if (abs(ksDaug[0]->getPDG()) ==
Const::pi0.getPDGCode() and abs(ksDaug[1]->getPDG()) ==
Const::pi0.getPDGCode()
1994 and (missingFlags & 256) == 0) {
1995 std::vector<MCParticle*> pi0Daug0 = ksDaug[0]->getDaughters();
1996 std::vector<MCParticle*> pi0Daug1 = ksDaug[1]->getDaughters();
1997 if (mcROEObjects.find(pi0Daug0[0]) == mcROEObjects.end() or
1998 mcROEObjects.find(pi0Daug0[1]) == mcROEObjects.end() or
1999 mcROEObjects.find(pi0Daug1[0]) == mcROEObjects.end() or
2000 mcROEObjects.find(pi0Daug1[1]) == mcROEObjects.end())
2001 missingFlags += 256;
2007 else if (pdg ==
Const::Klong.getPDGCode() and (missingFlags & 512) == 0)
2008 missingFlags += 512;
2011 else if ((pdg == 12 or pdg == 14 or pdg == 16) and (missingFlags & 1024) == 0)
2012 missingFlags += 1024;
2014 checkMCParticleMissingFlags(daughter, mcROEObjects, missingFlags);
2018 double isInThisRestOfEvent(
const Particle* particle,
const RestOfEvent* roe,
const std::string& maskName)
2020 if (particle->getParticleSource() == Particle::c_Composite or
2021 particle->getParticleSource() == Particle::c_V0) {
2022 std::vector<const Particle*> fspDaug = particle->getFinalStateDaughters();
2023 for (
auto& i : fspDaug) {
2024 if (isInThisRestOfEvent(i, roe, maskName) == 0)
2029 return roe->hasParticle(particle, maskName);
2032 const RestOfEvent* getRelatedROEObject(
const Particle* particle,
bool returnHostOnly)
2035 const RestOfEvent* roe = particle->
getRelatedTo<RestOfEvent>();
2036 if (!roe && !returnHostOnly) {
2037 roe = particle->getRelatedTo<RestOfEvent>(
"NestedRestOfEvents");
2043 VARIABLE_GROUP(
"Rest Of Event");
2045 REGISTER_METAVARIABLE(
"useROERecoilFrame(variable)", useROERecoilFrame,
2046 "Returns the value of the variable using the rest frame of the ROE recoil as current reference frame.\n"
2047 "Can be used inside for_each loop or outside of it if the particle has associated Rest of Event.\n"
2048 "E.g. ``useROERecoilFrame(E)`` returns the energy of a particle in the ROE recoil frame.", Manager::VariableDataType::c_double);
2050 REGISTER_VARIABLE(
"isInRestOfEvent", isInRestOfEvent,
2051 "Returns 1 if a track, ecl or klmCluster associated to particle is in the current RestOfEvent object, 0 otherwise."
2052 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2054 REGISTER_VARIABLE(
"isCloneOfSignalSide", isCloneOfSignalSide,
2055 "Returns 1 if a particle is a clone of signal side final state particles, 0 otherwise. "
2056 "Requires generator information and truth-matching. "
2057 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2059 REGISTER_VARIABLE(
"hasAncestorFromSignalSide", hasAncestorFromSignalSide,
2060 "Returns 1 if a particle has ancestor from signal side, 0 otherwise. "
2061 "Requires generator information and truth-matching. "
2062 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2064 REGISTER_METAVARIABLE(
"currentROEIsInList(particleList)", currentROEIsInList,
2065 "[Eventbased] Returns 1 the associated particle of the current ROE is contained in the given list or its charge-conjugated."
2066 "Useful to restrict the for_each loop over ROEs to ROEs of a certain ParticleList.", Manager::VariableDataType::c_double);
2068 REGISTER_VARIABLE(
"nROE_RemainingTracks", nROE_RemainingTracks,
2069 "Returns number of tracks in ROE - number of tracks of given particle"
2070 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2072 REGISTER_METAVARIABLE(
"nROE_RemainingTracks(maskName)", nROE_RemainingTracksWithMask,
2073 "Returns number of remaining tracks between the ROE (specified via a mask) and the given particle. For the given particle only tracks are counted which are in the RoE."
2074 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray."
2075 "Is required for the specific FEI. :noindex:", Manager::VariableDataType::c_int);
2080 REGISTER_VARIABLE(
"nROE_KLMClusters", nROE_KLMClusters,
2081 "Returns number of all remaining KLM clusters in the related RestOfEvent object.");
2083 REGISTER_METAVARIABLE(
"nROE_Charged(maskName, PDGcode = 0)", nROE_ChargedParticles,
2084 "Returns number of all charged particles in the related RestOfEvent object. First optional argument is ROE mask name. "
2085 "Second argument is a PDG code to count only one charged particle species, independently of charge. "
2086 "For example: ``nROE_Charged(cleanMask, 321)`` will output number of kaons in Rest Of Event with ``cleanMask``. "
2087 "PDG code 0 is used to count all charged particles", Manager::VariableDataType::c_double);
2089 REGISTER_METAVARIABLE(
"nROE_Photons(maskName)", nROE_Photons,
2090 "Returns number of all photons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ",
2091 Manager::VariableDataType::c_double);
2093 REGISTER_METAVARIABLE(
"nROE_NeutralHadrons(maskName)", nROE_NeutralHadrons,
2094 "Returns number of all neutral hadrons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ",
2095 Manager::VariableDataType::c_double);
2097 REGISTER_METAVARIABLE(
"particleRelatedToCurrentROE(var)", particleRelatedToCurrentROE,
2098 "[Eventbased] Returns variable applied to the particle which is related to the current RestOfEvent object"
2099 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.", Manager::VariableDataType::c_double);
2101 REGISTER_VARIABLE(
"roeMC_E", ROE_MC_E,
2102 "Returns true energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
"GeV");
2104 REGISTER_VARIABLE(
"roeMC_M", ROE_MC_M,
2105 "Returns true invariant mass of unused tracks and clusters in ROE\n\n",
"GeV/:math:`\\text{c}^2`");
2107 REGISTER_VARIABLE(
"roeMC_P", ROE_MC_P,
2108 "Returns true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
"GeV/c");
2110 REGISTER_VARIABLE(
"roeMC_Px", ROE_MC_Px,
2111 "Returns x component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2114 REGISTER_VARIABLE(
"roeMC_Py", ROE_MC_Py,
2115 "Returns y component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2118 REGISTER_VARIABLE(
"roeMC_Pz", ROE_MC_Pz,
2119 "Returns z component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2122 REGISTER_VARIABLE(
"roeMC_Pt", ROE_MC_Pt,
2123 "Returns transverse component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2126 REGISTER_VARIABLE(
"roeMC_PTheta", ROE_MC_PTheta,
2127 "Returns polar angle of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2130 REGISTER_METAVARIABLE(
"roeMC_MissFlags(maskName)", ROE_MC_MissingFlags,
2131 "Returns flags corresponding to missing particles on ROE side.", Manager::VariableDataType::c_double);
2133 REGISTER_METAVARIABLE(
"nROE_Tracks(maskName)", nROE_Tracks,
2134 "Returns number of tracks in the related RestOfEvent object that pass the selection criteria.",
2135 Manager::VariableDataType::c_double);
2137 REGISTER_METAVARIABLE(
"nROE_ECLClusters(maskName)", nROE_ECLClusters,
2138 "Returns number of ECL clusters in the related RestOfEvent object that pass the selection criteria.",
2139 Manager::VariableDataType::c_double);
2141 REGISTER_METAVARIABLE(
"nROE_NeutralECLClusters(maskName)", nROE_NeutralECLClusters,
2142 "Returns number of neutral ECL clusters in the related RestOfEvent object that pass the selection criteria.",
2143 Manager::VariableDataType::c_double);
2145 REGISTER_METAVARIABLE(
"nROE_Composites(maskName)", nROE_Composites,
2146 "Returns number of composite particles or V0s in the related RestOfEvent object that pass the selection criteria.",
2147 Manager::VariableDataType::c_double);
2149 REGISTER_METAVARIABLE(
"nROE_ParticlesInList(pListName[, maskName])", nROE_ParticlesInList,
2150 "Returns the number of particles in ROE from the given particle list. If a mask name is provided the selection criteria are applied.\n"
2151 "Use of variable aliases is advised.", Manager::VariableDataType::c_double);
2153 REGISTER_METAVARIABLE(
"roeCharge(maskName)", ROE_Charge,
2154 "Returns total charge of the related RestOfEvent object. The unit of the charge is ``e`` ", Manager::VariableDataType::c_double);
2156 REGISTER_METAVARIABLE(
"roeEextra(maskName)", ROE_ExtraEnergy,
2157 "Returns extra energy from ECLClusters in the calorimeter that is not associated to the given Particle. The unit of the energy is ``GeV`` ",
2158 Manager::VariableDataType::c_double);
2160 REGISTER_METAVARIABLE(
"roeNeextra(maskName)", ROE_NeutralExtraEnergy,
2161 "Returns extra energy from neutral ECLClusters in the calorimeter that is not associated to the given Particle, can be used with ``use***Frame()`` function. The unit of the energy is ``GeV`` ",
2162 Manager::VariableDataType::c_double);
2164 REGISTER_METAVARIABLE(
"roeE(maskName)", ROE_E,
2165 "Returns energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the energy is ``GeV`` ",
2166 Manager::VariableDataType::c_double);
2168 REGISTER_METAVARIABLE(
"roeM(maskName)", ROE_M,
2169 "Returns invariant mass of unused tracks and clusters in ROE. The unit of the invariant mass is :math:`\\text{GeV/c}^2`",
2170 Manager::VariableDataType::c_double);
2172 REGISTER_METAVARIABLE(
"roeP(maskName)", ROE_P,
2173 "Returns momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2174 Manager::VariableDataType::c_double);
2176 REGISTER_METAVARIABLE(
"roePt(maskName)", ROE_Pt,
2177 "Returns transverse component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2178 Manager::VariableDataType::c_double);
2180 REGISTER_METAVARIABLE(
"roePx(maskName)", ROE_Px,
2181 "Returns x component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2182 Manager::VariableDataType::c_double);
2184 REGISTER_METAVARIABLE(
"roePy(maskName)", ROE_Py,
2185 "Returns y component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2186 Manager::VariableDataType::c_double);
2188 REGISTER_METAVARIABLE(
"roePz(maskName)", ROE_Pz,
2189 "Returns z component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2190 Manager::VariableDataType::c_double);
2192 REGISTER_METAVARIABLE(
"roePTheta(maskName)", ROE_PTheta,
2193 "Returns theta angle of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the angle is ``rad`` ",
2194 Manager::VariableDataType::c_double);
2196 REGISTER_METAVARIABLE(
"roeDeltae(maskName)", ROE_DeltaE,
2197 "Returns energy difference of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`. The unit of the energy is ``GeV`` ",
2198 Manager::VariableDataType::c_double);
2200 REGISTER_METAVARIABLE(
"roeMbc(maskName)", ROE_Mbc,
2201 "Returns beam constrained mass of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`. The unit of the beam constrained mass is :math:`\\text{GeV/c}^2`.",
2202 Manager::VariableDataType::c_double);
2204 REGISTER_METAVARIABLE(
"weDeltae(maskName, opt)", WE_DeltaE,
2205 "Returns the energy difference of the B meson, corrected with the missing neutrino momentum (reconstructed side + neutrino) with respect to :math:`E_\\mathrm{cms}/2`. The unit of the energy is ``GeV`` ",
2206 Manager::VariableDataType::c_double);
2208 REGISTER_METAVARIABLE(
"weMbc(maskName, opt)", WE_Mbc,
2209 "Returns beam constrained mass of B meson, corrected with the missing neutrino momentum (reconstructed side + neutrino) with respect to :math:`E_\\mathrm{cms}/2`. The unit of the beam constrained mass is :math:`\\text{GeV/c}^2`.",
2210 Manager::VariableDataType::c_double);
2212 REGISTER_METAVARIABLE(
"weMissM2(maskName, opt)", WE_MissM2,
2213 "Returns the invariant mass squared of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the invariant mass squared is :math:`[\\text{GeV}/\\text{c}^2]^2`.",
2214 Manager::VariableDataType::c_double);
2216 REGISTER_METAVARIABLE(
"weMissPTheta(maskName, opt)", WE_MissPTheta,
2217 "Returns the polar angle of the missing momentum (see possible :b2:var:`weMissE` options). The unit of the polar angle is ``rad`` ",
2218 Manager::VariableDataType::c_double);
2220 REGISTER_METAVARIABLE(
"weMissP(maskName, opt)", WE_MissP,
2221 "Returns the magnitude of the missing momentum (see possible :b2:var:`weMissE` options). The unit of the magnitude of missing momentum is ``GeV/c`` ",
2222 Manager::VariableDataType::c_double);
2224 REGISTER_METAVARIABLE(
"weMissPx(maskName, opt)", WE_MissPx,
2225 "Returns the x component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2226 Manager::VariableDataType::c_double);
2228 REGISTER_METAVARIABLE(
"weMissPy(maskName, opt)", WE_MissPy,
2229 "Returns the y component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2230 Manager::VariableDataType::c_double);
2232 REGISTER_METAVARIABLE(
"weMissPz(maskName, opt)", WE_MissPz,
2233 "Returns the z component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2234 Manager::VariableDataType::c_double);
2236 REGISTER_METAVARIABLE(
"weMissE(maskName, opt)", WE_MissE,
2237 R
"DOC(Returns the energy of the missing momentum. The unit of the Energy is ``GeV`` . Possible options ``opt`` are the following:
2239- ``0``: CMS, use energy and momentum of charged particles and photons
2240- ``1``: CMS, same as ``0``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}`
2241- ``2``: CMS, same as ``0``, fix :math:`E_\mathrm{roe} = E_\mathrm{cms}/2`
2242- ``3``: CMS, use only energy and momentum of signal side
2243- ``4``: CMS, same as ``3``, update with direction of ROE momentum
2244- ``5``: LAB, use energy and momentum of charged particles and photons from whole event
2245- ``6``: LAB, same as ``5``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}``
2246- ``7``: CMS, correct pmiss 3-momentum vector with factor alpha so that :math:`d_E = 0`` (used for :math:`M_\mathrm{bc}` calculation).)DOC",
2247 Manager::VariableDataType::c_double);
2249 REGISTER_METAVARIABLE("weXiZ(maskName)", WE_xiZ,
2250 "Returns Xi_z in event (for Bhabha suppression and two-photon scattering). The unit of this variable is ``1/c`` ",
2251 Manager::VariableDataType::c_double);
2253 REGISTER_METAVARIABLE(
"bssMassDifference(maskName)", bssMassDifference,
2254 "Bs* - Bs mass difference. The unit of the mass is :math:`\\text{GeV/c}^2`.", Manager::VariableDataType::c_double);
2256 REGISTER_METAVARIABLE(
"weCosThetaEll(maskName)", WE_cosThetaEll, R
"DOC(
2258Returns the cosine of the angle between :math:`M` and lepton in :math:`W` rest frame in the decays of the type:
2259:math:`M \to h_1 ... h_n \ell`, where W 4-momentum is given as
2262 p_W = p_\ell + p_\nu.
2264The neutrino momentum is calculated from ROE taking into account the specified mask, and setting
2267 E_{\nu} = |p_{miss}|.
2269)DOC", Manager::VariableDataType::c_double);
2271 REGISTER_METAVARIABLE("weQ2lnuSimple(maskName,option)", WE_q2lnuSimple,
2272 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2273 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2274 "By default, option is set to ``1`` (see :b2:var:`weMissE`). Unless you know what you are doing, keep this default value. The unit of the momentum transfer squared is :math:`[\\text{GeV}/\\text{c}]^2`.", Manager::VariableDataType::c_double);
2276 REGISTER_METAVARIABLE(
"weQ2lnu(maskName,option)", WE_q2lnu,
2277 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2278 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2279 "This calculation uses constraints from dE = 0 and Mbc = Mb to correct the neutrino direction. \n"
2280 "By default, option is set to ``7`` (see :b2:var:`weMissE`). Unless you know what you are doing, keep this default value. The unit of the momentum transfer squared is :math:`[\\text{GeV}/\\text{c}]^2`.", Manager::VariableDataType::c_double);
2282 REGISTER_METAVARIABLE(
"weMissM2OverMissE(maskName)", WE_MissM2OverMissE,
2283 "Returns missing mass squared over missing energy. The unit of the missing mass squared is :math:`\\text{GeV/c}^4`.", Manager::VariableDataType::c_double);
2285 REGISTER_METAVARIABLE(
"passesROEMask(maskName)", passesROEMask,
2286 "Returns boolean value if a particle passes a certain mask or not. Only to be used in for_each path, otherwise returns quiet NaN.", Manager::VariableDataType::c_double);
2288 REGISTER_VARIABLE(
"printROE", printROE,
2289 "For debugging, prints indices of all particles in the ROE and all masks. Returns 0.");
2291 REGISTER_VARIABLE(
"hasCorrectROECombination", hasCorrectROECombination,
2292 "Returns 1 if there is correct combination of daughter particles between the particle that is the basis of the ROE and the particle loaded from the ROE. "
2293 "Returns 0 if there is not correct combination. "
2294 "If there is no daughter particle loaded from the ROE, returns quiet NaN.");
2296 REGISTER_METAVARIABLE(
"pi0Prob(mode)", pi0Prob,
2297 "Returns pi0 probability, where mode is used to specify the selection criteria for soft photon. \n"
2298 "The following strings are available. \n\n"
2299 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2300 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2301 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2302 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n"
2303 "- ``standardMC15rd``: loose energy cut is applied to soft photon and the weight files are trained using MC15rd \n"
2304 "- ``tightMC15rd``: tight energy cut is applied to soft photon and the weight files are trained using MC15rd \n\n"
2305 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.", Manager::VariableDataType::c_double);
2307 REGISTER_METAVARIABLE(
"etaProb(mode)", etaProb,
2308 "Returns eta probability, where mode is used to specify the selection criteria for soft photon. \n"
2309 "The following strings are available. \n\n"
2310 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2311 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2312 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2313 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n"
2314 "- ``standardMC15rd``: loose energy cut is applied to soft photon and the weight files are trained using MC15rd \n"
2315 "- ``tightMC15rd``: tight energy cut is applied to soft photon and the weight files are trained using MC15rd \n\n"
2316 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.", Manager::VariableDataType::c_double);
void SetMag(DataType mag)
Set magnitude keeping theta and phi constant.
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
DataType Mag2() const
The magnitude squared (rho^2 in spherical coordinate system).
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
static const ParticleType neutron
neutron particle
static const ParticleType pi0
neutral pion particle
static const ChargedStable muon
muon particle
static const ChargedStable pion
charged pion particle
static const ParticleType Klong
K^0_L particle.
static const ChargedStable proton
proton particle
static const ParticleType Kshort
K^0_S particle.
static const double doubleNaN
quiet_NaN
static const ChargedStable kaon
charged kaon particle
static const ParticleType photon
photon particle
static const ChargedStable electron
electron particle
@ c_nPhotons
CR is split into n photons (N1)
@ c_PrimaryParticle
bit 0: Particle is primary particle.
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
static const ReferenceFrame & GetCurrent()
Get current rest frame.
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
static constexpr const char * c_defaultMaskName
Default mask name.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Abstract base class for different kinds of events.