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")
1719 B2ERROR(
"the given argument is not supported in pi0Prob!");
1721 auto func = [mode](
const Particle * particle) ->
double {
1722 if (mode ==
"standard")
1724 if (particle->hasExtraInfo(
"Pi0ProbOrigin")) {
1725 return particle->getExtraInfo(
"Pi0ProbOrigin");
1727 B2WARNING(
"Pi0ProbOrigin is not registerted in extraInfo! \n"
1728 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1731 }
else if (mode ==
"tight")
1733 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThreshold")) {
1734 return particle->getExtraInfo(
"Pi0ProbTightEnergyThreshold");
1736 B2WARNING(
"Pi0ProbTightEnergyThreshold is not registerted in extraInfo! \n"
1737 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1740 }
else if (mode ==
"cluster")
1742 if (particle->hasExtraInfo(
"Pi0ProbLargeClusterSize")) {
1743 return particle->getExtraInfo(
"Pi0ProbLargeClusterSize");
1745 B2WARNING(
"Pi0ProbLargeClusterSize is not registerted in extraInfo! \n"
1746 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1749 }
else if (mode ==
"both")
1751 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize")) {
1752 return particle->getExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize");
1754 B2WARNING(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1755 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1768 if (arguments.size() != 1)
1769 B2ERROR(
"Wrong number of arguments (1 required) for etaProb");
1772 mode = arguments[0];
1774 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1775 B2ERROR(
"the given argument is not supported in etaProb!");
1777 auto func = [mode](
const Particle * particle) ->
double {
1778 if (mode ==
"standard")
1780 if (particle->hasExtraInfo(
"EtaProbOrigin")) {
1781 return particle->getExtraInfo(
"EtaProbOrigin");
1783 B2WARNING(
"EtaProbOrigin is not registerted in extraInfo! \n"
1784 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1787 }
else if (mode ==
"tight")
1789 if (particle->hasExtraInfo(
"EtaProbTightEnergyThreshold")) {
1790 return particle->getExtraInfo(
"EtaProbTightEnergyThreshold");
1792 B2WARNING(
"EtaProbTightEnergyThreshold is not registerted in extraInfo! \n"
1793 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1796 }
else if (mode ==
"cluster")
1798 if (particle->hasExtraInfo(
"EtaProbLargeClusterSize")) {
1799 return particle->getExtraInfo(
"EtaProbLargeClusterSize");
1801 B2WARNING(
"EtaProbLargeClusterSize is not registerted in extraInfo! \n"
1802 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1805 }
else if (mode ==
"both")
1807 if (particle->hasExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize")) {
1808 return particle->getExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize");
1810 B2WARNING(
"EtaProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1811 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1826 ROOT::Math::PxPyPzEVector missing4Vector(
const Particle* particle,
const std::string& maskName,
const std::string& opt)
1829 const RestOfEvent* roe = getRelatedROEObject(particle);
1832 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1833 ROOT::Math::PxPyPzEVector empty;
1838 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
1840 ROOT::Math::PxPyPzEVector rec4vecLAB = particle->get4Vector();
1841 ROOT::Math::PxPyPzEVector roe4vecLAB = roe->get4Vector(maskName);
1843 ROOT::Math::PxPyPzEVector rec4vec = T.rotateLabToCms() * rec4vecLAB;
1844 ROOT::Math::PxPyPzEVector roe4vec = T.rotateLabToCms() * roe4vecLAB;
1846 ROOT::Math::PxPyPzEVector miss4vec;
1847 double E_beam_cms = T.getCMSEnergy() / 2.0;
1851 miss4vec = - (rec4vec + roe4vec);
1852 miss4vec.SetE(2 * E_beam_cms - (rec4vec.E() + roe4vec.E()));
1856 else if (opt ==
"1") {
1857 miss4vec = - (rec4vec + roe4vec);
1858 miss4vec.SetE(miss4vec.P());
1862 else if (opt ==
"2") {
1863 miss4vec = - (rec4vec + roe4vec);
1864 miss4vec.SetE(E_beam_cms - rec4vec.E());
1868 else if (opt ==
"3") {
1869 miss4vec = - rec4vec;
1870 miss4vec.SetE(E_beam_cms - rec4vec.E());
1874 else if (opt ==
"4") {
1877 pB -= rec4vec.Vect();
1878 miss4vec.SetPxPyPzE(pB.X(), pB.Y(), pB.Z(), E_beam_cms - rec4vec.E());
1882 else if (opt ==
"5") {
1883 miss4vec = boostvec - (rec4vecLAB + roe4vecLAB);
1887 else if (opt ==
"6") {
1888 miss4vec = boostvec - (rec4vecLAB + roe4vecLAB);
1889 miss4vec.SetE(miss4vec.P());
1893 else if (opt ==
"7") {
1894 miss4vec = - (rec4vec + roe4vec);
1895 miss4vec.SetE(miss4vec.P());
1896 double factorAlpha = (E_beam_cms - rec4vec.E()) / miss4vec.E();
1897 miss4vec *= factorAlpha;
1898 miss4vec.SetE(miss4vec.P());
1904 void checkMCParticleMissingFlags(
const MCParticle* mcp, std::set<const MCParticle*> mcROEObjects,
int& missingFlags)
1906 std::vector<MCParticle*> daughters = mcp->getDaughters();
1907 for (
auto& daughter : daughters) {
1912 if (mcROEObjects.find(daughter) == mcROEObjects.end()) {
1914 int pdg = abs(daughter->getPDG());
1917 if (pdg ==
Const::photon.getPDGCode() and (missingFlags & 1) == 0)
1921 else if (pdg ==
Const::electron.getPDGCode() and (missingFlags & 2) == 0)
1925 else if (pdg ==
Const::muon.getPDGCode() and (missingFlags & 4) == 0)
1929 else if (pdg ==
Const::pion.getPDGCode() and (missingFlags & 8) == 0)
1933 else if (pdg ==
Const::kaon.getPDGCode() and (missingFlags & 16) == 0)
1937 else if (pdg ==
Const::proton.getPDGCode() and (missingFlags & 32) == 0)
1941 else if (pdg ==
Const::neutron.getPDGCode() and (missingFlags & 64) == 0)
1945 else if (pdg ==
Const::Kshort.getPDGCode() and ((missingFlags & 128) == 0 or (missingFlags & 256) == 0)) {
1946 std::vector<MCParticle*> ksDaug = daughter->getDaughters();
1947 if (ksDaug.size() == 2) {
1949 if (abs(ksDaug[0]->getPDG()) ==
Const::pion.getPDGCode() and abs(ksDaug[1]->getPDG()) ==
Const::pion.getPDGCode()
1950 and (missingFlags & 128) == 0) {
1951 if (mcROEObjects.find(ksDaug[0]) == mcROEObjects.end() or mcROEObjects.find(ksDaug[1]) == mcROEObjects.end())
1952 missingFlags += 128;
1955 else if (abs(ksDaug[0]->getPDG()) ==
Const::pi0.getPDGCode() and abs(ksDaug[1]->getPDG()) ==
Const::pi0.getPDGCode()
1956 and (missingFlags & 256) == 0) {
1957 std::vector<MCParticle*> pi0Daug0 = ksDaug[0]->getDaughters();
1958 std::vector<MCParticle*> pi0Daug1 = ksDaug[1]->getDaughters();
1959 if (mcROEObjects.find(pi0Daug0[0]) == mcROEObjects.end() or
1960 mcROEObjects.find(pi0Daug0[1]) == mcROEObjects.end() or
1961 mcROEObjects.find(pi0Daug1[0]) == mcROEObjects.end() or
1962 mcROEObjects.find(pi0Daug1[1]) == mcROEObjects.end())
1963 missingFlags += 256;
1969 else if (pdg ==
Const::Klong.getPDGCode() and (missingFlags & 512) == 0)
1970 missingFlags += 512;
1973 else if ((pdg == 12 or pdg == 14 or pdg == 16) and (missingFlags & 1024) == 0)
1974 missingFlags += 1024;
1976 checkMCParticleMissingFlags(daughter, mcROEObjects, missingFlags);
1980 double isInThisRestOfEvent(
const Particle* particle,
const RestOfEvent* roe,
const std::string& maskName)
1982 if (particle->getParticleSource() == Particle::c_Composite or
1983 particle->getParticleSource() == Particle::c_V0) {
1984 std::vector<const Particle*> fspDaug = particle->getFinalStateDaughters();
1985 for (
auto& i : fspDaug) {
1986 if (isInThisRestOfEvent(i, roe, maskName) == 0)
1991 return roe->hasParticle(particle, maskName);
1994 const RestOfEvent* getRelatedROEObject(
const Particle* particle,
bool returnHostOnly)
1997 const RestOfEvent* roe = particle->
getRelatedTo<RestOfEvent>();
1998 if (!roe && !returnHostOnly) {
1999 roe = particle->getRelatedTo<RestOfEvent>(
"NestedRestOfEvents");
2005 VARIABLE_GROUP(
"Rest Of Event");
2007 REGISTER_METAVARIABLE(
"useROERecoilFrame(variable)", useROERecoilFrame,
2008 "Returns the value of the variable using the rest frame of the ROE recoil as current reference frame.\n"
2009 "Can be used inside for_each loop or outside of it if the particle has associated Rest of Event.\n"
2010 "E.g. ``useROERecoilFrame(E)`` returns the energy of a particle in the ROE recoil frame.", Manager::VariableDataType::c_double);
2012 REGISTER_VARIABLE(
"isInRestOfEvent", isInRestOfEvent,
2013 "Returns 1 if a track, ecl or klmCluster associated to particle is in the current RestOfEvent object, 0 otherwise."
2014 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2016 REGISTER_VARIABLE(
"isCloneOfSignalSide", isCloneOfSignalSide,
2017 "Returns 1 if a particle is a clone of signal side final state particles, 0 otherwise. "
2018 "Requires generator information and truth-matching. "
2019 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2021 REGISTER_VARIABLE(
"hasAncestorFromSignalSide", hasAncestorFromSignalSide,
2022 "Returns 1 if a particle has ancestor from signal side, 0 otherwise. "
2023 "Requires generator information and truth-matching. "
2024 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2026 REGISTER_METAVARIABLE(
"currentROEIsInList(particleList)", currentROEIsInList,
2027 "[Eventbased] Returns 1 the associated particle of the current ROE is contained in the given list or its charge-conjugated."
2028 "Useful to restrict the for_each loop over ROEs to ROEs of a certain ParticleList.", Manager::VariableDataType::c_double);
2030 REGISTER_VARIABLE(
"nROE_RemainingTracks", nROE_RemainingTracks,
2031 "Returns number of tracks in ROE - number of tracks of given particle"
2032 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2034 REGISTER_METAVARIABLE(
"nROE_RemainingTracks(maskName)", nROE_RemainingTracksWithMask,
2035 "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."
2036 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray."
2037 "Is required for the specific FEI. :noindex:", Manager::VariableDataType::c_int);
2042 REGISTER_VARIABLE(
"nROE_KLMClusters", nROE_KLMClusters,
2043 "Returns number of all remaining KLM clusters in the related RestOfEvent object.");
2045 REGISTER_METAVARIABLE(
"nROE_Charged(maskName, PDGcode = 0)", nROE_ChargedParticles,
2046 "Returns number of all charged particles in the related RestOfEvent object. First optional argument is ROE mask name. "
2047 "Second argument is a PDG code to count only one charged particle species, independently of charge. "
2048 "For example: ``nROE_Charged(cleanMask, 321)`` will output number of kaons in Rest Of Event with ``cleanMask``. "
2049 "PDG code 0 is used to count all charged particles", Manager::VariableDataType::c_double);
2051 REGISTER_METAVARIABLE(
"nROE_Photons(maskName)", nROE_Photons,
2052 "Returns number of all photons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ",
2053 Manager::VariableDataType::c_double);
2055 REGISTER_METAVARIABLE(
"nROE_NeutralHadrons(maskName)", nROE_NeutralHadrons,
2056 "Returns number of all neutral hadrons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ",
2057 Manager::VariableDataType::c_double);
2059 REGISTER_METAVARIABLE(
"particleRelatedToCurrentROE(var)", particleRelatedToCurrentROE,
2060 "[Eventbased] Returns variable applied to the particle which is related to the current RestOfEvent object"
2061 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.", Manager::VariableDataType::c_double);
2063 REGISTER_VARIABLE(
"roeMC_E", ROE_MC_E,
2064 "Returns true energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
"GeV");
2066 REGISTER_VARIABLE(
"roeMC_M", ROE_MC_M,
2067 "Returns true invariant mass of unused tracks and clusters in ROE\n\n",
"GeV/:math:`\\text{c}^2`");
2069 REGISTER_VARIABLE(
"roeMC_P", ROE_MC_P,
2070 "Returns true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
"GeV/c");
2072 REGISTER_VARIABLE(
"roeMC_Px", ROE_MC_Px,
2073 "Returns x component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2076 REGISTER_VARIABLE(
"roeMC_Py", ROE_MC_Py,
2077 "Returns y component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2080 REGISTER_VARIABLE(
"roeMC_Pz", ROE_MC_Pz,
2081 "Returns z component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2084 REGISTER_VARIABLE(
"roeMC_Pt", ROE_MC_Pt,
2085 "Returns transverse component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2088 REGISTER_VARIABLE(
"roeMC_PTheta", ROE_MC_PTheta,
2089 "Returns polar angle of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.\n\n",
2092 REGISTER_METAVARIABLE(
"roeMC_MissFlags(maskName)", ROE_MC_MissingFlags,
2093 "Returns flags corresponding to missing particles on ROE side.", Manager::VariableDataType::c_double);
2095 REGISTER_METAVARIABLE(
"nROE_Tracks(maskName)", nROE_Tracks,
2096 "Returns number of tracks in the related RestOfEvent object that pass the selection criteria.",
2097 Manager::VariableDataType::c_double);
2099 REGISTER_METAVARIABLE(
"nROE_ECLClusters(maskName)", nROE_ECLClusters,
2100 "Returns number of ECL clusters in the related RestOfEvent object that pass the selection criteria.",
2101 Manager::VariableDataType::c_double);
2103 REGISTER_METAVARIABLE(
"nROE_NeutralECLClusters(maskName)", nROE_NeutralECLClusters,
2104 "Returns number of neutral ECL clusters in the related RestOfEvent object that pass the selection criteria.",
2105 Manager::VariableDataType::c_double);
2107 REGISTER_METAVARIABLE(
"nROE_Composites(maskName)", nROE_Composites,
2108 "Returns number of composite particles or V0s in the related RestOfEvent object that pass the selection criteria.",
2109 Manager::VariableDataType::c_double);
2111 REGISTER_METAVARIABLE(
"nROE_ParticlesInList(pListName[, maskName])", nROE_ParticlesInList,
2112 "Returns the number of particles in ROE from the given particle list. If a mask name is provided the selection criteria are applied.\n"
2113 "Use of variable aliases is advised.", Manager::VariableDataType::c_double);
2115 REGISTER_METAVARIABLE(
"roeCharge(maskName)", ROE_Charge,
2116 "Returns total charge of the related RestOfEvent object. The unit of the charge is ``e`` ", Manager::VariableDataType::c_double);
2118 REGISTER_METAVARIABLE(
"roeEextra(maskName)", ROE_ExtraEnergy,
2119 "Returns extra energy from ECLClusters in the calorimeter that is not associated to the given Particle. The unit of the energy is ``GeV`` ",
2120 Manager::VariableDataType::c_double);
2122 REGISTER_METAVARIABLE(
"roeNeextra(maskName)", ROE_NeutralExtraEnergy,
2123 "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`` ",
2124 Manager::VariableDataType::c_double);
2126 REGISTER_METAVARIABLE(
"roeE(maskName)", ROE_E,
2127 "Returns energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the energy is ``GeV`` ",
2128 Manager::VariableDataType::c_double);
2130 REGISTER_METAVARIABLE(
"roeM(maskName)", ROE_M,
2131 "Returns invariant mass of unused tracks and clusters in ROE. The unit of the invariant mass is :math:`\\text{GeV/c}^2`",
2132 Manager::VariableDataType::c_double);
2134 REGISTER_METAVARIABLE(
"roeP(maskName)", ROE_P,
2135 "Returns momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2136 Manager::VariableDataType::c_double);
2138 REGISTER_METAVARIABLE(
"roePt(maskName)", ROE_Pt,
2139 "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`` ",
2140 Manager::VariableDataType::c_double);
2142 REGISTER_METAVARIABLE(
"roePx(maskName)", ROE_Px,
2143 "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`` ",
2144 Manager::VariableDataType::c_double);
2146 REGISTER_METAVARIABLE(
"roePy(maskName)", ROE_Py,
2147 "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`` ",
2148 Manager::VariableDataType::c_double);
2150 REGISTER_METAVARIABLE(
"roePz(maskName)", ROE_Pz,
2151 "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`` ",
2152 Manager::VariableDataType::c_double);
2154 REGISTER_METAVARIABLE(
"roePTheta(maskName)", ROE_PTheta,
2155 "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`` ",
2156 Manager::VariableDataType::c_double);
2158 REGISTER_METAVARIABLE(
"roeDeltae(maskName)", ROE_DeltaE,
2159 "Returns energy difference of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`. The unit of the energy is ``GeV`` ",
2160 Manager::VariableDataType::c_double);
2162 REGISTER_METAVARIABLE(
"roeMbc(maskName)", ROE_Mbc,
2163 "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`.",
2164 Manager::VariableDataType::c_double);
2166 REGISTER_METAVARIABLE(
"weDeltae(maskName, opt)", WE_DeltaE,
2167 "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`` ",
2168 Manager::VariableDataType::c_double);
2170 REGISTER_METAVARIABLE(
"weMbc(maskName, opt)", WE_Mbc,
2171 "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`.",
2172 Manager::VariableDataType::c_double);
2174 REGISTER_METAVARIABLE(
"weMissM2(maskName, opt)", WE_MissM2,
2175 "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`.",
2176 Manager::VariableDataType::c_double);
2178 REGISTER_METAVARIABLE(
"weMissPTheta(maskName, opt)", WE_MissPTheta,
2179 "Returns the polar angle of the missing momentum (see possible :b2:var:`weMissE` options). The unit of the polar angle is ``rad`` ",
2180 Manager::VariableDataType::c_double);
2182 REGISTER_METAVARIABLE(
"weMissP(maskName, opt)", WE_MissP,
2183 "Returns the magnitude of the missing momentum (see possible :b2:var:`weMissE` options). The unit of the magnitude of missing momentum is ``GeV/c`` ",
2184 Manager::VariableDataType::c_double);
2186 REGISTER_METAVARIABLE(
"weMissPx(maskName, opt)", WE_MissPx,
2187 "Returns the x component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2188 Manager::VariableDataType::c_double);
2190 REGISTER_METAVARIABLE(
"weMissPy(maskName, opt)", WE_MissPy,
2191 "Returns the y component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2192 Manager::VariableDataType::c_double);
2194 REGISTER_METAVARIABLE(
"weMissPz(maskName, opt)", WE_MissPz,
2195 "Returns the z component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2196 Manager::VariableDataType::c_double);
2198 REGISTER_METAVARIABLE(
"weMissE(maskName, opt)", WE_MissE,
2199 R
"DOC(Returns the energy of the missing momentum. The unit of the Energy is ``GeV`` . Possible options ``opt`` are the following:
2201- ``0``: CMS, use energy and momentum of charged particles and photons
2202- ``1``: CMS, same as ``0``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}`
2203- ``2``: CMS, same as ``0``, fix :math:`E_\mathrm{roe} = E_\mathrm{cms}/2`
2204- ``3``: CMS, use only energy and momentum of signal side
2205- ``4``: CMS, same as ``3``, update with direction of ROE momentum
2206- ``5``: LAB, use energy and momentum of charged particles and photons from whole event
2207- ``6``: LAB, same as ``5``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}``
2208- ``7``: CMS, correct pmiss 3-momentum vector with factor alpha so that :math:`d_E = 0`` (used for :math:`M_\mathrm{bc}` calculation).)DOC",
2209 Manager::VariableDataType::c_double);
2211 REGISTER_METAVARIABLE("weXiZ(maskName)", WE_xiZ,
2212 "Returns Xi_z in event (for Bhabha suppression and two-photon scattering). The unit of this variable is ``1/c`` ",
2213 Manager::VariableDataType::c_double);
2215 REGISTER_METAVARIABLE(
"bssMassDifference(maskName)", bssMassDifference,
2216 "Bs* - Bs mass difference. The unit of the mass is :math:`\\text{GeV/c}^2`.", Manager::VariableDataType::c_double);
2218 REGISTER_METAVARIABLE(
"weCosThetaEll(maskName)", WE_cosThetaEll, R
"DOC(
2220Returns the cosine of the angle between :math:`M` and lepton in :math:`W` rest frame in the decays of the type:
2221:math:`M \to h_1 ... h_n \ell`, where W 4-momentum is given as
2224 p_W = p_\ell + p_\nu.
2226The neutrino momentum is calculated from ROE taking into account the specified mask, and setting
2229 E_{\nu} = |p_{miss}|.
2231)DOC", Manager::VariableDataType::c_double);
2233 REGISTER_METAVARIABLE("weQ2lnuSimple(maskName,option)", WE_q2lnuSimple,
2234 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2235 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2236 "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);
2238 REGISTER_METAVARIABLE(
"weQ2lnu(maskName,option)", WE_q2lnu,
2239 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2240 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2241 "This calculation uses constraints from dE = 0 and Mbc = Mb to correct the neutrino direction. \n"
2242 "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);
2244 REGISTER_METAVARIABLE(
"weMissM2OverMissE(maskName)", WE_MissM2OverMissE,
2245 "Returns missing mass squared over missing energy. The unit of the missing mass squared is :math:`\\text{GeV/c}^4`.", Manager::VariableDataType::c_double);
2247 REGISTER_METAVARIABLE(
"passesROEMask(maskName)", passesROEMask,
2248 "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);
2250 REGISTER_VARIABLE(
"printROE", printROE,
2251 "For debugging, prints indices of all particles in the ROE and all masks. Returns 0.");
2253 REGISTER_VARIABLE(
"hasCorrectROECombination", hasCorrectROECombination,
2254 "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. "
2255 "Returns 0 if there is not correct combination. "
2256 "If there is no daughter particle loaded from the ROE, returns quiet NaN.");
2258 REGISTER_METAVARIABLE(
"pi0Prob(mode)", pi0Prob,
2259 "Returns pi0 probability, where mode is used to specify the selection criteria for soft photon. \n"
2260 "The following strings are available. \n\n"
2261 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2262 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2263 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2264 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2265 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.", Manager::VariableDataType::c_double);
2267 REGISTER_METAVARIABLE(
"etaProb(mode)", etaProb,
2268 "Returns eta probability, where mode is used to specify the selection criteria for soft photon. \n"
2269 "The following strings are available. \n\n"
2270 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2271 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2272 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2273 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2274 "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.