10 #include <analysis/variables/ROEVariables.h>
11 #include <analysis/variables/Variables.h>
12 #include <analysis/utility/PCmsLabTransform.h>
14 #include <analysis/VariableManager/Manager.h>
17 #include <framework/datastore/StoreArray.h>
18 #include <framework/datastore/StoreObjPtr.h>
21 #include <analysis/dataobjects/Particle.h>
22 #include <analysis/dataobjects/ParticleList.h>
24 #include <mdst/dataobjects/ECLCluster.h>
27 #include <framework/logging/Logger.h>
28 #include <framework/gearbox/Const.h>
31 #include <analysis/utility/ReferenceFrame.h>
47 double isInRestOfEvent(
const Particle* particle)
50 StoreObjPtr<RestOfEvent> roeobjptr;
51 if (not roeobjptr.isValid())
54 const RestOfEvent* roe = &(*roeobjptr);
56 return isInThisRestOfEvent(particle, roe);
59 double isCloneOfSignalSide(
const Particle* particle)
62 StoreObjPtr<RestOfEvent> roe;
63 if (not roe.isValid()) {
64 B2WARNING(
"Please use isCloneOfSignalSide variable in for_each ROE loop!");
65 return std::numeric_limits<float>::quiet_NaN();
67 auto* particleMC = particle->getMCParticle();
71 auto* signal = roe->getRelatedFrom<Particle>();
72 auto signalFSPs = signal->getFinalStateDaughters();
73 for (
auto* daughter : signalFSPs) {
74 auto* daughterMC = daughter->getMCParticle();
75 if (daughterMC == particleMC) {
81 double hasAncestorFromSignalSide(
const Particle* particle)
83 StoreObjPtr<RestOfEvent> roe;
85 B2WARNING(
"Please use hasAncestorFromSignalSide variable in for_each ROE loop!");
86 return std::numeric_limits<float>::quiet_NaN();
88 auto* particleMC = particle->getMCParticle();
92 auto* signalReco = roe->getRelatedFrom<Particle>();
93 auto* signalMC = signalReco->getMCParticle();
94 MCParticle* ancestorMC = particleMC->getMother();
96 if (ancestorMC == signalMC) {
99 ancestorMC = ancestorMC->getMother();
106 Manager::FunctionPtr currentROEIsInList(
const std::vector<std::string>& arguments)
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");
129 return std::numeric_limits<float>::quiet_NaN();
131 return particleList->contains(particle) ? 1 : 0;
137 Manager::FunctionPtr particleRelatedToCurrentROE(
const std::vector<std::string>& arguments)
139 if (arguments.size() != 1)
140 B2FATAL(
"Wrong number of arguments (1 required) for meta function particleRelatedToCurrentROE");
142 const Variable::Manager::Var* var = Manager::Instance().getVariable(arguments[0]);
143 auto func = [var](
const Particle*) ->
double {
145 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
147 if (not roe.isValid())
148 return std::numeric_limits<float>::quiet_NaN();
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");
154 return std::numeric_limits<float>::quiet_NaN();
156 return var->function(particle);
162 Manager::FunctionPtr useROERecoilFrame(
const std::vector<std::string>& arguments)
164 if (arguments.size() == 1) {
165 const Variable::Manager::Var* var = Manager::Instance().getVariable(arguments[0]);
166 auto func = [var](
const Particle * particle) ->
double {
168 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
172 StoreObjPtr<RestOfEvent> roeObjPtr(
"RestOfEvent");
173 if (roeObjPtr.isValid()) {
179 B2ERROR(
"Neither relation between particle and ROE doesn't exist nor ROE object has not been found!");
180 return std::numeric_limits<float>::quiet_NaN();
183 TLorentzVector pRecoil = T.getBeamFourMomentum() - roe->get4Vector();
184 Particle tmp(pRecoil, 0);
185 UseReferenceFrame<RestFrame> frame(&tmp);
186 double result = var->function(particle);
191 B2WARNING(
"Wrong number of arguments for meta function useROERecoilFrame");
197 double nRemainingTracksInROE(
const Particle* particle,
const std::string& maskName)
199 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
200 if (not roe.isValid())
202 int n_roe_tracks = roe->getNTracks(maskName);
203 int n_par_tracks = 0;
204 const auto& daughters = particle->getFinalStateDaughters();
205 for (
const auto& daughter : daughters) {
206 if (daughter->getParticleSource() == Particle::EParticleSourceObject::c_Track && roe->hasParticle(daughter, maskName)) {
210 return n_roe_tracks - n_par_tracks;
213 Manager::FunctionPtr nROE_RemainingTracksWithMask(
const std::vector<std::string>& arguments)
215 std::string maskName;
217 if (arguments.size() == 0)
219 else if (arguments.size() == 1)
220 maskName = arguments[0];
222 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROETracks");
224 auto func = [maskName](
const Particle * particle) ->
double {
225 return nRemainingTracksInROE(particle, maskName);
230 double nROE_RemainingTracks(
const Particle* particle)
232 return nRemainingTracksInROE(particle);
235 double nROE_KLMClusters(
const Particle* particle)
238 const RestOfEvent* roe = getRelatedROEObject(particle);
241 B2ERROR(
"Relation between particle and ROE doesn't exist!");
242 return std::numeric_limits<float>::quiet_NaN();
245 return roe->getNKLMClusters();
248 double ROE_MC_E(
const Particle* particle)
250 const MCParticle* mcp = particle->getMCParticle();
253 return std::numeric_limits<float>::quiet_NaN();
256 TLorentzVector boostvec = T.getBeamFourMomentum();
257 auto mcroe4vector = boostvec - mcp->get4Vector();
258 const auto& frame = ReferenceFrame::GetCurrent();
259 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
260 return frameMCRoe4Vector.Energy();
263 double ROE_MC_P(
const Particle* particle)
265 const MCParticle* mcp = particle->getMCParticle();
268 return std::numeric_limits<float>::quiet_NaN();
271 TLorentzVector boostvec = T.getBeamFourMomentum();
272 auto mcroe4vector = boostvec - mcp->get4Vector();
273 const auto& frame = ReferenceFrame::GetCurrent();
274 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
275 return frameMCRoe4Vector.Vect().Mag();
278 double ROE_MC_Px(
const Particle* particle)
280 const MCParticle* mcp = particle->getMCParticle();
283 return std::numeric_limits<float>::quiet_NaN();
286 TLorentzVector boostvec = T.getBeamFourMomentum();
287 auto mcroe4vector = boostvec - mcp->get4Vector();
288 const auto& frame = ReferenceFrame::GetCurrent();
289 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
291 return frameMCRoe4Vector.Vect().X();
294 double ROE_MC_Py(
const Particle* particle)
296 const MCParticle* mcp = particle->getMCParticle();
299 return std::numeric_limits<float>::quiet_NaN();
302 TLorentzVector boostvec = T.getBeamFourMomentum();
303 auto mcroe4vector = boostvec - mcp->get4Vector();
304 const auto& frame = ReferenceFrame::GetCurrent();
305 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
307 return frameMCRoe4Vector.Vect().Y();
310 double ROE_MC_Pz(
const Particle* particle)
312 const MCParticle* mcp = particle->getMCParticle();
315 return std::numeric_limits<float>::quiet_NaN();
318 TLorentzVector boostvec = T.getBeamFourMomentum();
319 auto mcroe4vector = boostvec - mcp->get4Vector();
320 const auto& frame = ReferenceFrame::GetCurrent();
321 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
323 return frameMCRoe4Vector.Vect().Z();
326 double ROE_MC_Pt(
const Particle* particle)
328 const MCParticle* mcp = particle->getMCParticle();
331 return std::numeric_limits<float>::quiet_NaN();
334 TLorentzVector boostvec = T.getBeamFourMomentum();
335 auto mcroe4vector = boostvec - mcp->get4Vector();
336 const auto& frame = ReferenceFrame::GetCurrent();
337 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
339 return frameMCRoe4Vector.Vect().Perp();
342 double ROE_MC_PTheta(
const Particle* particle)
344 const MCParticle* mcp = particle->getMCParticle();
347 return std::numeric_limits<float>::quiet_NaN();
350 TLorentzVector boostvec = T.getBeamFourMomentum();
351 auto mcroe4vector = boostvec - mcp->get4Vector();
352 const auto& frame = ReferenceFrame::GetCurrent();
353 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
355 return frameMCRoe4Vector.Theta();
358 double ROE_MC_M(
const Particle* particle)
360 const MCParticle* mcp = particle->getMCParticle();
363 return std::numeric_limits<float>::quiet_NaN();
366 TLorentzVector boostvec = T.getBeamFourMomentum();
368 return (boostvec - mcp->get4Vector()).Mag();
371 Manager::FunctionPtr ROE_MC_MissingFlags(
const std::vector<std::string>& arguments)
373 std::string maskName;
375 if (arguments.size() == 0)
377 else if (arguments.size() == 1)
378 maskName = arguments[0];
380 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROETracks");
382 auto func = [maskName](
const Particle * particle) ->
double {
384 StoreArray<Particle> particles;
387 const MCParticle* mcParticle = particle->getMCParticle();
390 return std::numeric_limits<float>::quiet_NaN();
393 const MCParticle* mcMother = mcParticle->getMother();
396 return std::numeric_limits<float>::quiet_NaN();
399 std::vector<MCParticle*> mcDaughters = mcMother->getDaughters();
401 if (mcDaughters.size() != 2)
402 return std::numeric_limits<float>::quiet_NaN();
405 MCParticle* mcROE =
nullptr;
406 if (mcDaughters[0]->getArrayIndex() == mcParticle->getArrayIndex())
407 mcROE = mcDaughters[1];
409 mcROE = mcDaughters[0];
412 const RestOfEvent* roe = getRelatedROEObject(particle);
414 std::set<const MCParticle*> mcROEObjects;
416 auto roeParticles = roe->getParticles(maskName);
417 for (
auto* roeParticle : roeParticles)
419 auto* mcroeParticle = roeParticle->getMCParticle();
420 if (mcroeParticle !=
nullptr) {
421 mcROEObjects.insert(mcroeParticle);
425 checkMCParticleMissingFlags(mcROE, mcROEObjects, flags);
432 Manager::FunctionPtr nROE_Tracks(
const std::vector<std::string>& arguments)
434 std::string maskName;
436 if (arguments.size() == 0)
438 else if (arguments.size() == 1)
439 maskName = arguments[0];
441 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROETracks");
443 auto func = [maskName](
const Particle * particle) ->
double {
446 const RestOfEvent* roe = getRelatedROEObject(particle);
450 B2ERROR(
"Relation between particle and ROE doesn't exist!");
451 return std::numeric_limits<float>::quiet_NaN();
454 return roe->getNTracks(maskName);
459 Manager::FunctionPtr nROE_ECLClusters(
const std::vector<std::string>& arguments)
461 std::string maskName;
463 if (arguments.size() == 0)
465 else if (arguments.size() == 1)
466 maskName = arguments[0];
468 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROEECLClusters");
470 auto func = [maskName](
const Particle * particle) ->
double {
473 const RestOfEvent* roe = getRelatedROEObject(particle);
477 B2ERROR(
"Relation between particle and ROE doesn't exist!");
478 return std::numeric_limits<float>::quiet_NaN();
481 return roe->getNECLClusters(maskName);
486 Manager::FunctionPtr nROE_NeutralECLClusters(
const std::vector<std::string>& arguments)
488 std::string maskName;
490 if (arguments.size() == 0)
492 else if (arguments.size() == 1)
493 maskName = arguments[0];
495 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROENeutralECLClusters");
497 auto func = [maskName](
const Particle * particle) ->
double {
500 const RestOfEvent* roe = getRelatedROEObject(particle);
504 B2ERROR(
"Relation between particle and ROE doesn't exist!");
505 return std::numeric_limits<float>::quiet_NaN();
508 return roe->getPhotons(maskName).size();
513 Manager::FunctionPtr nROE_Photons(
const std::vector<std::string>& arguments)
515 std::string maskName =
"";
517 if (arguments.size() == 1) {
518 maskName = arguments[0];
520 if (arguments.size() > 1) {
521 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROE_Photons");
523 auto func = [maskName](
const Particle * particle) ->
double {
526 const RestOfEvent* roe = getRelatedROEObject(particle);
530 B2ERROR(
"Relation between particle and ROE doesn't exist!");
531 return std::numeric_limits<float>::quiet_NaN();
535 auto roeClusters = roe->getPhotons(maskName);
539 for (
auto& roeCluster : roeClusters)
540 if (roeCluster->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons)
547 Manager::FunctionPtr nROE_NeutralHadrons(
const std::vector<std::string>& arguments)
549 std::string maskName =
"";
551 if (arguments.size() == 1) {
552 maskName = arguments[0];
554 if (arguments.size() > 1) {
555 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROE_NeutralHadrons");
557 auto func = [maskName](
const Particle * particle) ->
double {
560 const RestOfEvent* roe = getRelatedROEObject(particle);
564 B2ERROR(
"Relation between particle and ROE doesn't exist!");
565 return std::numeric_limits<float>::quiet_NaN();
568 return roe->getHadrons(maskName).size();
573 Manager::FunctionPtr nROE_ChargedParticles(
const std::vector<std::string>& arguments)
575 std::string maskName =
"";
577 if (arguments.size() == 1) {
578 maskName = arguments[0];
580 if (arguments.size() == 2) {
581 maskName = arguments[0];
583 pdgCode = Belle2::convertString<int>(arguments[1]);
584 }
catch (std::invalid_argument&) {
585 B2ERROR(
"First argument of nROE_ChargedParticles must be a PDG code");
589 if (arguments.size() > 2) {
590 B2FATAL(
"Wrong number of arguments (2 optional) for meta function nROE_ChargedParticles");
592 auto func = [maskName, pdgCode](
const Particle * particle) ->
double {
595 const RestOfEvent* roe = getRelatedROEObject(particle);
599 B2ERROR(
"Relation between particle and ROE doesn't exist!");
600 return std::numeric_limits<float>::quiet_NaN();
603 return roe->getChargedParticles(maskName, abs(pdgCode)).size();
608 Manager::FunctionPtr nROE_Composites(
const std::vector<std::string>& arguments)
610 std::string maskName =
"";
612 if (arguments.size() == 1) {
613 maskName = arguments[0];
615 if (arguments.size() > 1) {
616 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function nROE_Composites");
618 auto func = [maskName](
const Particle * particle) ->
double {
621 const RestOfEvent* roe = getRelatedROEObject(particle);
625 B2ERROR(
"Relation between particle and ROE doesn't exist!");
626 return std::numeric_limits<float>::quiet_NaN();
629 auto particles = roe->getParticles(maskName,
false);
631 for (
auto roeParticle : particles)
633 if (roeParticle->getParticleSource() == Particle::c_Composite or
634 roeParticle->getParticleSource() == Particle::c_V0) {
644 Manager::FunctionPtr nROE_ParticlesInList(
const std::vector<std::string>& arguments)
646 std::string pListName;
647 std::string maskName;
649 if (arguments.size() == 1) {
650 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!");
666 return std::numeric_limits<float>::quiet_NaN();
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))
688 Manager::FunctionPtr ROE_Charge(
const std::vector<std::string>& arguments)
690 std::string maskName;
692 if (arguments.size() == 0)
694 else if (arguments.size() == 1)
695 maskName = arguments[0];
697 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROECharge");
699 auto func = [maskName](
const Particle * particle) ->
double {
702 const RestOfEvent* roe = getRelatedROEObject(particle);
706 B2ERROR(
"Relation between particle and ROE doesn't exist!");
707 return std::numeric_limits<float>::quiet_NaN();
711 auto roeParticles = roe->getParticles(maskName);
714 for (
auto* roeParticle : roeParticles)
716 roeCharge += roeParticle->getCharge();
724 Manager::FunctionPtr ROE_ExtraEnergy(
const std::vector<std::string>& arguments)
726 std::string maskName;
728 if (arguments.size() == 0)
730 else if (arguments.size() == 1)
731 maskName = arguments[0];
733 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function extraEnergy");
735 auto func = [maskName](
const Particle * particle) ->
double {
738 const RestOfEvent* roe = getRelatedROEObject(particle);
742 B2ERROR(
"Relation between particle and ROE doesn't exist!");
743 return std::numeric_limits<float>::quiet_NaN();
748 auto roeClusters = roe->getPhotons(maskName);
750 for (
auto& roeCluster : roeClusters)
751 if (roeCluster->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons)
752 extraE += roeCluster->getECLClusterEnergy();
754 auto roeChargedParticles = roe->getChargedParticles(maskName);
756 for (
auto& roeChargedParticle : roeChargedParticles)
758 if (roeChargedParticle->getECLCluster())
759 extraE += roeChargedParticle->getECLClusterEnergy();
767 Manager::FunctionPtr ROE_NeutralExtraEnergy(
const std::vector<std::string>& arguments)
769 std::string maskName;
771 if (arguments.size() == 0)
773 else if (arguments.size() == 1)
774 maskName = arguments[0];
776 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function extraEnergy");
778 auto func = [maskName](
const Particle * particle) ->
double {
781 const RestOfEvent* roe = getRelatedROEObject(particle);
785 B2ERROR(
"Relation between particle and ROE doesn't exist!");
786 return std::numeric_limits<float>::quiet_NaN();
788 auto roephotons = roe->getPhotons(maskName);
789 TLorentzVector total4vector;
790 for (
auto* photon : roephotons)
792 total4vector += photon->get4Vector();
794 const auto& frame = ReferenceFrame::GetCurrent();
795 auto frameRoe4Vector = frame.getMomentum(total4vector);
796 return frameRoe4Vector.Energy();
801 Manager::FunctionPtr ROE_E(
const std::vector<std::string>& arguments)
803 std::string maskName;
804 if (arguments.size() == 0)
806 else if (arguments.size() == 1)
807 maskName = arguments[0];
809 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_E");
810 auto func = [maskName](
const Particle * particle) ->
double {
811 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
814 B2ERROR(
"Relation between particle and ROE doesn't exist!");
815 return std::numeric_limits<float>::quiet_NaN();
817 const auto& frame = ReferenceFrame::GetCurrent();
818 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
819 return frameRoe4Vector.Energy();
824 Manager::FunctionPtr ROE_M(
const std::vector<std::string>& arguments)
826 std::string maskName;
828 if (arguments.size() == 0)
830 else if (arguments.size() == 1)
831 maskName = arguments[0];
833 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_M");
835 auto func = [maskName](
const Particle * particle) ->
double {
838 const RestOfEvent* roe = getRelatedROEObject(particle);
842 B2ERROR(
"Relation between particle and ROE doesn't exist!");
843 return std::numeric_limits<float>::quiet_NaN();
846 return roe->get4Vector(maskName).Mag();
851 Manager::FunctionPtr ROE_P(
const std::vector<std::string>& arguments)
853 std::string maskName;
855 if (arguments.size() == 0)
857 else if (arguments.size() == 1)
858 maskName = arguments[0];
860 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_P");
862 auto func = [maskName](
const Particle * particle) ->
double {
865 const RestOfEvent* roe = getRelatedROEObject(particle);
869 B2ERROR(
"Relation between particle and ROE doesn't exist!");
870 return std::numeric_limits<float>::quiet_NaN();
873 const auto& frame = ReferenceFrame::GetCurrent();
874 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
875 return frameRoe4Vector.Vect().Mag();
880 Manager::FunctionPtr ROE_Px(
const std::vector<std::string>& arguments)
882 std::string maskName;
884 if (arguments.size() == 0)
886 else if (arguments.size() == 1)
887 maskName = arguments[0];
889 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Px");
891 auto func = [maskName](
const Particle * particle) ->
double {
894 const RestOfEvent* roe = getRelatedROEObject(particle);
898 B2ERROR(
"Relation between particle and ROE doesn't exist!");
899 return std::numeric_limits<float>::quiet_NaN();
902 const auto& frame = ReferenceFrame::GetCurrent();
903 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
904 return frameRoe4Vector.Vect().X();
909 Manager::FunctionPtr ROE_Py(
const std::vector<std::string>& arguments)
911 std::string maskName;
913 if (arguments.size() == 0)
915 else if (arguments.size() == 1)
916 maskName = arguments[0];
918 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Py");
920 auto func = [maskName](
const Particle * particle) ->
double {
923 const RestOfEvent* roe = getRelatedROEObject(particle);
927 B2ERROR(
"Relation between particle and ROE doesn't exist!");
928 return std::numeric_limits<float>::quiet_NaN();
931 const auto& frame = ReferenceFrame::GetCurrent();
932 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
933 return frameRoe4Vector.Vect().Y();
938 Manager::FunctionPtr ROE_Pt(
const std::vector<std::string>& arguments)
940 std::string maskName;
942 if (arguments.size() == 0)
944 else if (arguments.size() == 1)
945 maskName = arguments[0];
947 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Pt");
949 auto func = [maskName](
const Particle * particle) ->
double {
952 const RestOfEvent* roe = getRelatedROEObject(particle);
956 B2ERROR(
"Relation between particle and ROE doesn't exist!");
957 return std::numeric_limits<float>::quiet_NaN();
960 const auto& frame = ReferenceFrame::GetCurrent();
961 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
962 return frameRoe4Vector.Vect().Perp();
967 Manager::FunctionPtr ROE_Pz(
const std::vector<std::string>& arguments)
969 std::string maskName;
971 if (arguments.size() == 0)
973 else if (arguments.size() == 1)
974 maskName = arguments[0];
976 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_Pz");
978 auto func = [maskName](
const Particle * particle) ->
double {
981 const RestOfEvent* roe = getRelatedROEObject(particle);
985 B2ERROR(
"Relation between particle and ROE doesn't exist!");
986 return std::numeric_limits<float>::quiet_NaN();
989 const auto& frame = ReferenceFrame::GetCurrent();
990 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
991 return frameRoe4Vector.Vect().Z();
996 Manager::FunctionPtr ROE_PTheta(
const std::vector<std::string>& arguments)
998 std::string maskName;
1000 if (arguments.size() == 0)
1002 else if (arguments.size() == 1)
1003 maskName = arguments[0];
1005 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_PTheta");
1007 auto func = [maskName](
const Particle * particle) ->
double {
1010 const RestOfEvent* roe = getRelatedROEObject(particle);
1014 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1015 return std::numeric_limits<float>::quiet_NaN();
1018 const auto& frame = ReferenceFrame::GetCurrent();
1019 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
1020 return frameRoe4Vector.Theta();
1025 Manager::FunctionPtr ROE_DeltaE(
const std::vector<std::string>& arguments)
1027 std::string maskName;
1029 if (arguments.size() == 0)
1031 else if (arguments.size() == 1)
1032 maskName = arguments[0];
1034 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_deltae");
1036 auto func = [maskName](
const Particle * particle) ->
double {
1039 const RestOfEvent* roe = getRelatedROEObject(particle);
1043 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1044 return std::numeric_limits<float>::quiet_NaN();
1048 TLorentzVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1049 return vec.E() - T.getCMSEnergy() / 2;
1054 Manager::FunctionPtr ROE_Mbc(
const std::vector<std::string>& arguments)
1056 std::string maskName;
1058 if (arguments.size() == 0)
1060 else if (arguments.size() == 1)
1061 maskName = arguments[0];
1063 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function ROE_mbc");
1065 auto func = [maskName](
const Particle * particle) ->
double {
1068 const RestOfEvent* roe = getRelatedROEObject(particle);
1072 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1073 return std::numeric_limits<float>::quiet_NaN();
1077 TLorentzVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1079 double E = T.getCMSEnergy() / 2;
1080 double m2 = E * E - vec.Vect().Mag2();
1081 double mbc = m2 > 0 ? sqrt(m2) : 0;
1088 Manager::FunctionPtr bssMassDifference(
const std::vector<std::string>& arguments)
1090 std::string maskName;
1092 if (arguments.size() == 0)
1094 else if (arguments.size() == 1)
1095 maskName = arguments[0];
1097 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function bssMassDifference");
1099 auto func = [maskName](
const Particle * particle) ->
double {
1102 TLorentzVector neutrino4vec = missing4Vector(particle->getDaughter(0), maskName,
"6");
1103 TLorentzVector sig4vec = particle->getDaughter(0)->get4Vector();
1105 TLorentzVector bsMom = neutrino4vec + sig4vec;
1106 TLorentzVector bssMom = bsMom + particle->getDaughter(1)->get4Vector();
1108 return bssMom.M() - bsMom.M();
1113 Manager::FunctionPtr WE_DeltaE(
const std::vector<std::string>& arguments)
1115 std::string maskName;
1118 if (arguments.size() == 1) {
1121 }
else if (arguments.size() == 2) {
1122 maskName = arguments[0];
1125 B2FATAL(
"Wrong number of arguments (2 required) for meta function correctedB_deltae");
1127 auto func = [maskName, opt](
const Particle * particle) ->
double {
1130 TLorentzVector boostvec = T.getBeamFourMomentum();
1131 TLorentzVector sig4vec = T.rotateLabToCms() * particle->get4Vector();
1132 TLorentzVector sig4vecLAB = particle->get4Vector();
1133 TLorentzVector neutrino4vec = missing4Vector(particle, maskName,
"1");
1134 TLorentzVector neutrino4vecLAB = missing4Vector(particle, maskName,
"6");
1136 double deltaE = std::numeric_limits<float>::quiet_NaN();
1141 double totalSigEnergy = (sig4vec + neutrino4vec).Energy();
1142 double E = T.getCMSEnergy() / 2;
1143 deltaE = totalSigEnergy - E;
1147 else if (opt ==
"1")
1149 double Ecms = T.getCMSEnergy();
1150 double s = Ecms * Ecms;
1151 deltaE = ((sig4vecLAB + neutrino4vecLAB) * boostvec - s / 2.0) / sqrt(s);
1155 B2FATAL(
"Option for correctedB_deltae variable should only be 0/1 (CMS/LAB)");
1162 Manager::FunctionPtr WE_Mbc(
const std::vector<std::string>& arguments)
1164 std::string maskName;
1167 if (arguments.size() == 1) {
1170 }
else if (arguments.size() == 2) {
1171 maskName = arguments[0];
1174 B2FATAL(
"Wrong number of arguments (2 required) for meta function correctedB_mbc");
1176 auto func = [maskName, opt](
const Particle * particle) ->
double {
1179 TLorentzVector boostvec = T.getBeamFourMomentum();
1180 TLorentzVector sig4vec = T.rotateLabToCms() * particle->get4Vector();
1181 TLorentzVector sig4vecLAB = particle->get4Vector();
1182 TLorentzVector neutrino4vec;
1184 double mbc = std::numeric_limits<float>::quiet_NaN();
1189 neutrino4vec = missing4Vector(particle, maskName,
"1");
1190 TVector3 bmom = (sig4vec + neutrino4vec).Vect();
1191 double E = T.getCMSEnergy() / 2;
1192 double m2 = E * E - bmom.Mag2();
1193 mbc = m2 > 0 ? sqrt(m2) : 0;
1197 else if (opt ==
"1")
1199 neutrino4vec = missing4Vector(particle, maskName,
"6");
1200 TVector3 bmom = (sig4vecLAB + neutrino4vec).Vect();
1201 double Ecms = T.getCMSEnergy();
1202 double s = Ecms * Ecms;
1203 double m2 = pow((s / 2.0 + bmom * boostvec.Vect()) / boostvec.Energy(), 2.0) - bmom.Mag2();
1204 mbc = m2 > 0 ? sqrt(m2) : 0;
1208 else if (opt ==
"2")
1210 neutrino4vec = missing4Vector(particle, maskName,
"7");
1211 TVector3 bmom = (sig4vec + neutrino4vec).Vect();
1212 double E = T.getCMSEnergy() / 2;
1213 double m2 = E * E - bmom.Mag2();
1214 mbc = m2 > 0 ? sqrt(m2) : 0;
1218 B2FATAL(
"Option for correctedB_mbc variable should only be 0/1/2 (CMS/LAB/CMS with factor)");
1225 Manager::FunctionPtr WE_MissM2(
const std::vector<std::string>& arguments)
1227 std::string maskName;
1230 if (arguments.size() == 1) {
1233 }
else if (arguments.size() == 2) {
1234 maskName = arguments[0];
1237 B2FATAL(
"Wrong number of arguments (2 required) for meta function missM2");
1239 auto func = [maskName, opt](
const Particle * particle) ->
double {
1241 return missing4Vector(particle, maskName, opt).Mag2();
1246 Manager::FunctionPtr WE_MissPTheta(
const std::vector<std::string>& arguments)
1248 std::string maskName;
1251 if (arguments.size() == 1) {
1254 }
else if (arguments.size() == 2) {
1255 maskName = arguments[0];
1258 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPTheta");
1260 auto func = [maskName, opt](
const Particle * particle) ->
double {
1263 const RestOfEvent* roe = getRelatedROEObject(particle);
1267 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1268 return std::numeric_limits<float>::quiet_NaN();
1271 return missing4Vector(particle, maskName, opt).Theta();
1276 Manager::FunctionPtr WE_MissP(
const std::vector<std::string>& arguments)
1278 std::string maskName;
1281 if (arguments.size() == 1) {
1284 }
else if (arguments.size() == 2) {
1285 maskName = arguments[0];
1288 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissP");
1290 auto func = [maskName, opt](
const Particle * particle) ->
double {
1293 const RestOfEvent* roe = getRelatedROEObject(particle);
1297 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1298 return std::numeric_limits<float>::quiet_NaN();
1301 return missing4Vector(particle, maskName, opt).Vect().Mag();
1306 Manager::FunctionPtr WE_MissPx(
const std::vector<std::string>& arguments)
1308 std::string maskName;
1311 if (arguments.size() == 1) {
1314 }
else if (arguments.size() == 2) {
1315 maskName = arguments[0];
1318 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPx");
1320 auto func = [maskName, opt](
const Particle * particle) ->
double {
1323 const RestOfEvent* roe = getRelatedROEObject(particle);
1327 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1328 return std::numeric_limits<float>::quiet_NaN();
1331 return missing4Vector(particle, maskName, opt).Vect().Px();
1336 Manager::FunctionPtr WE_MissPy(
const std::vector<std::string>& arguments)
1338 std::string maskName;
1341 if (arguments.size() == 1) {
1344 }
else if (arguments.size() == 2) {
1345 maskName = arguments[0];
1348 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPy");
1350 auto func = [maskName, opt](
const Particle * particle) ->
double {
1353 const RestOfEvent* roe = getRelatedROEObject(particle);
1357 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1358 return std::numeric_limits<float>::quiet_NaN();
1361 return missing4Vector(particle, maskName, opt).Vect().Py();
1366 Manager::FunctionPtr WE_MissPz(
const std::vector<std::string>& arguments)
1368 std::string maskName;
1371 if (arguments.size() == 1) {
1374 }
else if (arguments.size() == 2) {
1375 maskName = arguments[0];
1378 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPz");
1380 auto func = [maskName, opt](
const Particle * particle) ->
double {
1383 const RestOfEvent* roe = getRelatedROEObject(particle);
1387 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1388 return std::numeric_limits<float>::quiet_NaN();
1391 return missing4Vector(particle, maskName, opt).Vect().Pz();
1396 Manager::FunctionPtr WE_MissE(
const std::vector<std::string>& arguments)
1398 std::string maskName;
1401 if (arguments.size() == 1) {
1404 }
else if (arguments.size() == 2) {
1405 maskName = arguments[0];
1408 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissE");
1410 auto func = [maskName, opt](
const Particle * particle) ->
double {
1413 const RestOfEvent* roe = getRelatedROEObject(particle);
1417 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1418 return std::numeric_limits<float>::quiet_NaN();
1421 return missing4Vector(particle, maskName, opt).Energy();
1426 Manager::FunctionPtr WE_xiZ(
const std::vector<std::string>& arguments)
1428 std::string maskName;
1430 if (arguments.size() == 0)
1432 else if (arguments.size() == 1)
1433 maskName = arguments[0];
1435 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function xiZ");
1437 auto func = [maskName](
const Particle * particle) ->
double {
1440 const RestOfEvent* roe = getRelatedROEObject(particle);
1444 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1445 return std::numeric_limits<float>::quiet_NaN();
1452 std::vector<const Particle*> recTrackParticles = particle->getFinalStateDaughters();
1455 for (
auto& recTrackParticle : recTrackParticles)
1457 pz += recTrackParticle->getPz();
1458 energy += recTrackParticle->getEnergy();
1462 auto roeParticles = roe->getChargedParticles(maskName);
1463 for (
auto* roeParticle : roeParticles)
1465 pz += roeParticle->getPz();
1466 energy += roeParticle->getEnergy();
1474 Manager::FunctionPtr WE_MissM2OverMissE(
const std::vector<std::string>& arguments)
1476 std::string maskName;
1478 if (arguments.size() == 0)
1480 else if (arguments.size() == 1)
1481 maskName = arguments[0];
1483 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function WE_MissM2OverMissE");
1485 auto func = [maskName](
const Particle * particle) ->
double {
1488 const RestOfEvent* roe = getRelatedROEObject(particle);
1492 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1493 return std::numeric_limits<float>::quiet_NaN();
1497 TLorentzVector missing4Momentum;
1498 TLorentzVector boostvec = T.getBeamFourMomentum();
1500 return missing4Vector(particle, maskName,
"5").Mag2() / (2.0 * missing4Vector(particle, maskName,
"5").Energy());
1505 Manager::FunctionPtr WE_q2lnuSimple(
const std::vector<std::string>& arguments)
1507 std::string maskName(
"");
1508 std::string option(
"1");
1510 if (arguments.size() == 1) {
1511 maskName = arguments[0];
1512 }
else if (arguments.size() == 2) {
1513 maskName = arguments[0];
1514 option = arguments[1];
1515 }
else if (arguments.size() > 2) {
1516 B2FATAL(
"Too many arguments. At most two arguments are allowed for meta function q2lnuSimple(maskname,option)");
1519 auto func = [maskName, option](
const Particle * particle) ->
double {
1522 const RestOfEvent* roe = getRelatedROEObject(particle);
1526 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1527 return std::numeric_limits<float>::quiet_NaN();
1530 int n = particle->getNDaughters();
1533 return std::numeric_limits<float>::quiet_NaN();
1537 const Particle* lep = particle->getDaughter(n - 1);
1538 TLorentzVector lep4vec = T.rotateLabToCms() * lep->get4Vector();
1539 TLorentzVector nu4vec = missing4Vector(particle, maskName, option);
1541 return (lep4vec + nu4vec).Mag2();
1546 Manager::FunctionPtr WE_q2lnu(
const std::vector<std::string>& arguments)
1548 std::string maskName(
"");
1549 std::string option(
"7");
1551 if (arguments.size() == 1) {
1552 maskName = arguments[0];
1553 }
else if (arguments.size() == 2) {
1554 maskName = arguments[0];
1555 option = arguments[1];
1556 }
else if (arguments.size() > 2) {
1557 B2FATAL(
"Too many arguments. At most two arguments are allowed for meta function q2lnu(maskname, option)");
1560 auto func = [maskName, option](
const Particle * particle) ->
double {
1563 const RestOfEvent* roe = getRelatedROEObject(particle);
1567 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1568 return std::numeric_limits<float>::quiet_NaN();
1571 int n = particle->getNDaughters();
1574 return std::numeric_limits<float>::quiet_NaN();
1577 const Particle* lep = particle->getDaughter(n - 1);
1578 TLorentzVector lep_cm = T.rotateLabToCms() * lep->get4Vector();
1580 TLorentzVector Y_cm = T.rotateLabToCms() * particle->get4Vector();
1581 TLorentzVector neu_cm = missing4Vector(particle, maskName, option);
1583 double e_beam = T.getCMSEnergy() / 2.0;
1586 double bmass = particle->getPDGMass();
1587 double pB2 = e_beam * e_beam - bmass * bmass;
1590 double cos_angle_nu = (pB2 - Y_cm.Vect().Mag2() - neu_cm.Vect().Mag2()) / (2.0 * Y_cm.Vect().Mag() * neu_cm.Vect().Mag());
1591 if (abs(cos_angle_nu) > 1)
1593 return (lep_cm + neu_cm).Mag2();
1596 double angle_nu = TMath::ACos(cos_angle_nu);
1598 TLorentzVector rotated_neu(-1 * Y_cm.Vect(), Y_cm.E());
1600 double nu_theta = rotated_neu.Theta() + (TMath::Pi() - angle_nu);
1601 double nu_phi = rotated_neu.Phi();
1602 rotated_neu.SetTheta(nu_theta);
1603 rotated_neu.SetPhi(nu_phi);
1604 rotated_neu.SetRho(neu_cm.Rho());
1605 rotated_neu.SetE(neu_cm.E());
1607 TVector3 Yneu_norm = Y_cm.Vect().Cross(neu_cm.Vect());
1608 TVector3 Yrot_norm = Y_cm.Vect().Cross(rotated_neu.Vect());
1612 double rot_angle = Yneu_norm.Angle(Yrot_norm);
1614 TLorentzVector rotated_neu2(rotated_neu);
1620 rotated_neu.Rotate(rot_angle, Y_cm.Vect());
1621 rotated_neu2.Rotate(-rot_angle, Y_cm.Vect());
1623 double dot1 = rotated_neu.Vect().Dot(Yneu_norm);
1624 double dot2 = rotated_neu2.Vect().Dot(Yneu_norm);
1626 if (abs(dot2) < abs(dot1)) rotated_neu = rotated_neu2;
1628 return (lep_cm + rotated_neu).Mag2();
1633 Manager::FunctionPtr WE_cosThetaEll(
const std::vector<std::string>& arguments)
1635 std::string maskName;
1637 if (arguments.size() == 0)
1639 else if (arguments.size() == 1)
1640 maskName = arguments[0];
1642 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function cosThetaEll");
1644 auto func = [maskName](
const Particle * particle) ->
double {
1647 TLorentzVector boostvec = T.getBeamFourMomentum();
1648 TLorentzVector pNu = missing4Vector(particle, maskName,
"6");
1650 TLorentzVector pLep;
1652 for (
unsigned i = 0; i < particle->getNDaughters(); i++)
1654 int absPDG = abs(particle->getDaughter(i)->getPDGCode());
1655 if (absPDG == Const::electron.getPDGCode() || absPDG == Const::muon.getPDGCode() || absPDG == 15) {
1656 pLep = particle->getDaughter(i)->get4Vector();
1661 TLorentzVector pW = pNu + pLep;
1662 TLorentzVector pB = particle->get4Vector() + pNu;
1665 TVector3 boost2W = -(pW.BoostVector());
1666 pLep.Boost(boost2W);
1669 TVector3 lep3Vector = pLep.Vect();
1670 TVector3 B3Vector = pB.Vect();
1671 double numerator = lep3Vector.Dot(B3Vector);
1672 double denominator = (lep3Vector.Mag()) * (B3Vector.Mag());
1674 return numerator / denominator;
1679 Manager::FunctionPtr passesROEMask(
const std::vector<std::string>& arguments)
1681 std::string maskName;
1683 if (arguments.size() == 0)
1685 else if (arguments.size() == 1)
1686 maskName = arguments[0];
1688 B2FATAL(
"At most 1 argument (name of mask) accepted for meta function passesROEMask");
1690 auto func = [maskName](
const Particle * particle) ->
double {
1694 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
1695 if (not roe.isValid())
1696 return std::numeric_limits<float>::quiet_NaN();
1698 if (roe->hasParticle(particle, maskName))
1708 double printROE(
const Particle* particle)
1710 const RestOfEvent* roe = getRelatedROEObject(particle);
1713 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1714 }
else roe->print();
1719 Manager::FunctionPtr pi0Prob(
const std::vector<std::string>& arguments)
1721 if (arguments.size() != 1)
1722 B2ERROR(
"Wrong number of arguments (1 required) for pi0Prob");
1725 mode = arguments[0];
1727 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1728 B2ERROR(
"the given argument is not supported in pi0Prob!");
1730 auto func = [mode](
const Particle * particle) ->
double {
1731 if (mode ==
"standard")
1733 if (particle->hasExtraInfo(
"Pi0ProbOrigin")) {
1734 return particle->getExtraInfo(
"Pi0ProbOrigin");
1736 B2WARNING(
"Pi0ProbOrigin is not registerted in extraInfo! \n"
1737 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1738 return std::numeric_limits<float>::quiet_NaN();
1742 else if (mode ==
"tight")
1744 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThreshold")) {
1745 return particle->getExtraInfo(
"Pi0ProbTightEnergyThreshold");
1747 B2WARNING(
"Pi0ProbTightEnergyThreshold is not registerted in extraInfo! \n"
1748 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1749 return std::numeric_limits<float>::quiet_NaN();
1753 else if (mode ==
"cluster")
1755 if (particle->hasExtraInfo(
"Pi0ProbLargeClusterSize")) {
1756 return particle->getExtraInfo(
"Pi0ProbLargeClusterSize");
1758 B2WARNING(
"Pi0ProbLargeClusterSize is not registerted in extraInfo! \n"
1759 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1760 return std::numeric_limits<float>::quiet_NaN();
1764 else if (mode ==
"both")
1766 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize")) {
1767 return particle->getExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize");
1769 B2WARNING(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1770 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1771 return std::numeric_limits<float>::quiet_NaN();
1777 return std::numeric_limits<float>::quiet_NaN();
1783 Manager::FunctionPtr etaProb(
const std::vector<std::string>& arguments)
1785 if (arguments.size() != 1)
1786 B2ERROR(
"Wrong number of arguments (1 required) for etaProb");
1789 mode = arguments[0];
1791 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1792 B2ERROR(
"the given argument is not supported in etaProb!");
1794 auto func = [mode](
const Particle * particle) ->
double {
1795 if (mode ==
"standard")
1797 if (particle->hasExtraInfo(
"EtaProbOrigin")) {
1798 return particle->getExtraInfo(
"EtaProbOrigin");
1800 B2WARNING(
"EtaProbOrigin is not registerted in extraInfo! \n"
1801 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1802 return std::numeric_limits<float>::quiet_NaN();
1806 else if (mode ==
"tight")
1808 if (particle->hasExtraInfo(
"EtaProbTightEnergyThreshold")) {
1809 return particle->getExtraInfo(
"EtaProbTightEnergyThreshold");
1811 B2WARNING(
"EtaProbTightEnergyThreshold is not registerted in extraInfo! \n"
1812 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1813 return std::numeric_limits<float>::quiet_NaN();
1817 else if (mode ==
"cluster")
1819 if (particle->hasExtraInfo(
"EtaProbLargeClusterSize")) {
1820 return particle->getExtraInfo(
"EtaProbLargeClusterSize");
1822 B2WARNING(
"EtaProbLargeClusterSize is not registerted in extraInfo! \n"
1823 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1824 return std::numeric_limits<float>::quiet_NaN();
1828 else if (mode ==
"both")
1830 if (particle->hasExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize")) {
1831 return particle->getExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize");
1833 B2WARNING(
"EtaProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1834 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1835 return std::numeric_limits<float>::quiet_NaN();
1841 return std::numeric_limits<float>::quiet_NaN();
1851 TLorentzVector missing4Vector(
const Particle* particle,
const std::string& maskName,
const std::string& opt)
1854 const RestOfEvent* roe = getRelatedROEObject(particle);
1857 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1858 TLorentzVector empty;
1863 TLorentzVector boostvec = T.getBeamFourMomentum();
1865 TLorentzVector rec4vecLAB = particle->get4Vector();
1866 TLorentzVector roe4vecLAB = roe->get4Vector(maskName);
1868 TLorentzVector rec4vec = T.rotateLabToCms() * rec4vecLAB;
1869 TLorentzVector roe4vec = T.rotateLabToCms() * roe4vecLAB;
1871 TLorentzVector miss4vec;
1872 double E_beam_cms = T.getCMSEnergy() / 2.0;
1876 miss4vec.SetVect(- (rec4vec.Vect() + roe4vec.Vect()));
1877 miss4vec.SetE(2 * E_beam_cms - (rec4vec.E() + roe4vec.E()));
1881 else if (opt ==
"1") {
1882 miss4vec.SetVect(- (rec4vec.Vect() + roe4vec.Vect()));
1883 miss4vec.SetE(miss4vec.Vect().Mag());
1887 else if (opt ==
"2") {
1888 miss4vec.SetVect(- (rec4vec.Vect() + roe4vec.Vect()));
1889 miss4vec.SetE(E_beam_cms - rec4vec.E());
1893 else if (opt ==
"3") {
1894 miss4vec.SetVect(- rec4vec.Vect());
1895 miss4vec.SetE(E_beam_cms - rec4vec.E());
1899 else if (opt ==
"4") {
1900 TVector3 pB = - roe4vec.Vect();
1902 miss4vec.SetVect(pB - rec4vec.Vect());
1903 miss4vec.SetE(E_beam_cms - rec4vec.E());
1907 else if (opt ==
"5") {
1908 miss4vec.SetVect(boostvec.Vect() - (rec4vecLAB.Vect() + roe4vecLAB.Vect()));
1909 miss4vec.SetE(boostvec.E() - (rec4vecLAB.E() + roe4vecLAB.E()));
1913 else if (opt ==
"6") {
1914 miss4vec.SetVect(boostvec.Vect() - (rec4vecLAB.Vect() + roe4vecLAB.Vect()));
1915 miss4vec.SetE(miss4vec.Vect().Mag());
1919 else if (opt ==
"7") {
1920 miss4vec.SetVect(-(rec4vec.Vect() + roe4vec.Vect()));
1921 miss4vec.SetE(miss4vec.Vect().Mag());
1922 double factorAlpha = (E_beam_cms - rec4vec.E()) / miss4vec.E();
1923 miss4vec.SetRho(factorAlpha * miss4vec.Rho());
1924 miss4vec.SetE(miss4vec.Rho());
1930 void checkMCParticleMissingFlags(
const MCParticle* mcp, std::set<const MCParticle*> mcROEObjects,
int& missingFlags)
1932 std::vector<MCParticle*> daughters = mcp->getDaughters();
1933 for (
auto& daughter : daughters) {
1935 if (!daughter->hasStatus(MCParticle::c_PrimaryParticle))
1938 if (mcROEObjects.find(daughter) == mcROEObjects.end()) {
1940 int pdg = abs(daughter->getPDG());
1943 if (pdg == Const::photon.getPDGCode() and (missingFlags & 1) == 0)
1947 else if (pdg == Const::electron.getPDGCode() and (missingFlags & 2) == 0)
1951 else if (pdg == Const::muon.getPDGCode() and (missingFlags & 4) == 0)
1955 else if (pdg == Const::pion.getPDGCode() and (missingFlags & 8) == 0)
1959 else if (pdg == Const::kaon.getPDGCode() and (missingFlags & 16) == 0)
1963 else if (pdg == Const::proton.getPDGCode() and (missingFlags & 32) == 0)
1967 else if (pdg == Const::neutron.getPDGCode() and (missingFlags & 64) == 0)
1971 else if (pdg == Const::Kshort.getPDGCode() and ((missingFlags & 128) == 0 or (missingFlags & 256) == 0)) {
1972 std::vector<MCParticle*> ksDaug = daughter->getDaughters();
1973 if (ksDaug.size() == 2) {
1975 if (abs(ksDaug[0]->getPDG()) == Const::pion.getPDGCode() and abs(ksDaug[1]->getPDG()) == Const::pion.getPDGCode()
1976 and (missingFlags & 128) == 0) {
1977 if (mcROEObjects.find(ksDaug[0]) == mcROEObjects.end() or mcROEObjects.find(ksDaug[1]) == mcROEObjects.end())
1978 missingFlags += 128;
1981 else if (abs(ksDaug[0]->getPDG()) == Const::pi0.getPDGCode() and abs(ksDaug[1]->getPDG()) == Const::pi0.getPDGCode()
1982 and (missingFlags & 256) == 0) {
1983 std::vector<MCParticle*> pi0Daug0 = ksDaug[0]->getDaughters();
1984 std::vector<MCParticle*> pi0Daug1 = ksDaug[1]->getDaughters();
1985 if (mcROEObjects.find(pi0Daug0[0]) == mcROEObjects.end() or
1986 mcROEObjects.find(pi0Daug0[1]) == mcROEObjects.end() or
1987 mcROEObjects.find(pi0Daug1[0]) == mcROEObjects.end() or
1988 mcROEObjects.find(pi0Daug1[1]) == mcROEObjects.end())
1989 missingFlags += 256;
1995 else if (pdg == Const::Klong.getPDGCode() and (missingFlags & 512) == 0)
1996 missingFlags += 512;
1999 else if ((pdg == 12 or pdg == 14 or pdg == 16) and (missingFlags & 1024) == 0)
2000 missingFlags += 1024;
2002 checkMCParticleMissingFlags(daughter, mcROEObjects, missingFlags);
2006 double isInThisRestOfEvent(
const Particle* particle,
const RestOfEvent* roe,
const std::string& maskName)
2008 if (particle->getParticleSource() == Particle::c_Composite or
2009 particle->getParticleSource() == Particle::c_V0) {
2010 std::vector<const Particle*> fspDaug = particle->getFinalStateDaughters();
2011 for (
auto& i : fspDaug) {
2012 if (isInThisRestOfEvent(i, roe, maskName) == 0)
2017 return roe->hasParticle(particle, maskName);
2020 const RestOfEvent* getRelatedROEObject(
const Particle* particle,
bool returnHostOnly)
2023 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
2024 if (!roe && !returnHostOnly) {
2025 roe = particle->getRelatedTo<RestOfEvent>(
"NestedRestOfEvents");
2031 VARIABLE_GROUP(
"Rest Of Event");
2033 REGISTER_VARIABLE(
"useROERecoilFrame(variable)", useROERecoilFrame,
2034 "Returns the value of the variable using the rest frame of the ROE recoil as current reference frame.\n"
2035 "Can be used inside for_each loop or outside of it if the particle has associated Rest of Event.\n"
2036 "E.g. ``useROERecoilFrame(E)`` returns the energy of a particle in the ROE recoil frame.");
2038 REGISTER_VARIABLE(
"isInRestOfEvent", isInRestOfEvent,
2039 "Returns 1 if a track, ecl or klmCluster associated to particle is in the current RestOfEvent object, 0 otherwise."
2040 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2042 REGISTER_VARIABLE(
"isCloneOfSignalSide", isCloneOfSignalSide,
2043 "Returns 1 if a particle is a clone of signal side final state particles, 0 otherwise. "
2044 "Requires generator information and truth-matching. "
2045 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2047 REGISTER_VARIABLE(
"hasAncestorFromSignalSide", hasAncestorFromSignalSide,
2048 "Returns 1 if a particle has ancestor from signal side, 0 otherwise. "
2049 "Requires generator information and truth-matching. "
2050 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2052 REGISTER_VARIABLE(
"currentROEIsInList(particleList)", currentROEIsInList,
2053 "[Eventbased] Returns 1 the associated particle of the current ROE is contained in the given list or its charge-conjugated."
2054 "Useful to restrict the for_each loop over ROEs to ROEs of a certain ParticleList.");
2056 REGISTER_VARIABLE(
"nROE_RemainingTracks", nROE_RemainingTracks,
2057 "Returns number of tracks in ROE - number of tracks of given particle"
2058 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2060 REGISTER_VARIABLE(
"nROE_RemainingTracks(maskName)", nROE_RemainingTracksWithMask,
2061 "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."
2062 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray."
2063 "Is required for the specific FEI. :noindex:");
2068 REGISTER_VARIABLE(
"nROE_KLMClusters", nROE_KLMClusters,
2069 "Returns number of all remaining KLM clusters in the related RestOfEvent object.");
2071 REGISTER_VARIABLE(
"nROE_Charged(maskName, PDGcode = 0)", nROE_ChargedParticles,
2072 "Returns number of all charged particles in the related RestOfEvent object. First optional argument is ROE mask name. "
2073 "Second argument is a PDG code to count only one charged particle species, independently of charge. "
2074 "For example: ``nROE_Charged(cleanMask, 321)`` will output number of kaons in Rest Of Event with ``cleanMask``. "
2075 "PDG code 0 is used to count all charged particles");
2077 REGISTER_VARIABLE(
"nROE_Photons(maskName)", nROE_Photons,
2078 "Returns number of all photons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ");
2080 REGISTER_VARIABLE(
"nROE_NeutralHadrons(maskName)", nROE_NeutralHadrons,
2081 "Returns number of all neutral hadrons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ");
2083 REGISTER_VARIABLE(
"particleRelatedToCurrentROE(var)", particleRelatedToCurrentROE,
2084 "[Eventbased] Returns variable applied to the particle which is related to the current RestOfEvent object"
2085 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2087 REGISTER_VARIABLE(
"roeMC_E", ROE_MC_E,
2088 "Returns true energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2090 REGISTER_VARIABLE(
"roeMC_M", ROE_MC_M,
2091 "Returns true invariant mass of unused tracks and clusters in ROE");
2093 REGISTER_VARIABLE(
"roeMC_P", ROE_MC_P,
2094 "Returns true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2096 REGISTER_VARIABLE(
"roeMC_Px", ROE_MC_Px,
2097 "Returns x component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2099 REGISTER_VARIABLE(
"roeMC_Py", ROE_MC_Py,
2100 "Returns y component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2102 REGISTER_VARIABLE(
"roeMC_Pz", ROE_MC_Pz,
2103 "Returns z component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2105 REGISTER_VARIABLE(
"roeMC_Pt", ROE_MC_Pt,
2106 "Returns transverse component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2108 REGISTER_VARIABLE(
"roeMC_PTheta", ROE_MC_PTheta,
2109 "Returns polar angle of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2111 REGISTER_VARIABLE(
"roeMC_MissFlags(maskName)", ROE_MC_MissingFlags,
2112 "Returns flags corresponding to missing particles on ROE side.");
2114 REGISTER_VARIABLE(
"nROE_Tracks(maskName)", nROE_Tracks,
2115 "Returns number of tracks in the related RestOfEvent object that pass the selection criteria.");
2117 REGISTER_VARIABLE(
"nROE_ECLClusters(maskName)", nROE_ECLClusters,
2118 "Returns number of ECL clusters in the related RestOfEvent object that pass the selection criteria.");
2120 REGISTER_VARIABLE(
"nROE_NeutralECLClusters(maskName)", nROE_NeutralECLClusters,
2121 "Returns number of neutral ECL clusters in the related RestOfEvent object that pass the selection criteria.");
2123 REGISTER_VARIABLE(
"nROE_Composites(maskName)", nROE_Composites,
2124 "Returns number of composite particles or V0s in the related RestOfEvent object that pass the selection criteria.");
2126 REGISTER_VARIABLE(
"nROE_ParticlesInList(pListName)", nROE_ParticlesInList,
2127 "Returns the number of particles in ROE from the given particle list.\n"
2128 "Use of variable aliases is advised.");
2130 REGISTER_VARIABLE(
"roeCharge(maskName)", ROE_Charge,
2131 "Returns total charge of the related RestOfEvent object.");
2133 REGISTER_VARIABLE(
"roeEextra(maskName)", ROE_ExtraEnergy,
2134 "Returns extra energy from ECLClusters in the calorimeter that is not associated to the given Particle");
2136 REGISTER_VARIABLE(
"roeNeextra(maskName)", ROE_NeutralExtraEnergy,
2137 "Returns extra energy from neutral ECLClusters in the calorimeter that is not associated to the given Particle, can be used with ``use***Frame()`` function.");
2139 REGISTER_VARIABLE(
"roeE(maskName)", ROE_E,
2140 "Returns energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2142 REGISTER_VARIABLE(
"roeM(maskName)", ROE_M,
2143 "Returns invariant mass of unused tracks and clusters in ROE");
2145 REGISTER_VARIABLE(
"roeP(maskName)", ROE_P,
2146 "Returns momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2148 REGISTER_VARIABLE(
"roePt(maskName)", ROE_Pt,
2149 "Returns transverse component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2151 REGISTER_VARIABLE(
"roePx(maskName)", ROE_Px,
2152 "Returns x component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2154 REGISTER_VARIABLE(
"roePy(maskName)", ROE_Py,
2155 "Returns y component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2157 REGISTER_VARIABLE(
"roePz(maskName)", ROE_Pz,
2158 "Returns z component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2160 REGISTER_VARIABLE(
"roePTheta(maskName)", ROE_PTheta,
2161 "Returns theta angle of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2163 REGISTER_VARIABLE(
"roeDeltae(maskName)", ROE_DeltaE,
2164 "Returns energy difference of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`.");
2166 REGISTER_VARIABLE(
"roeMbc(maskName)", ROE_Mbc,
2167 "Returns beam constrained mass of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`.");
2169 REGISTER_VARIABLE(
"weDeltae(maskName, opt)", WE_DeltaE,
2170 "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`.");
2172 REGISTER_VARIABLE(
"weMbc(maskName, opt)", WE_Mbc,
2173 "Returns beam constrained mass of B meson, corrected with the missing neutrino momentum (reconstructed side + neutrino) with respect to :math:`E_\\mathrm{cms}/2`.");
2175 REGISTER_VARIABLE(
"weMissM2(maskName, opt)", WE_MissM2,
2176 "Returns the invariant mass squared of the missing momentum (see :b2:var:`weMissE` possible options)");
2178 REGISTER_VARIABLE(
"weMissPTheta(maskName, opt)", WE_MissPTheta,
2179 "Returns the polar angle of the missing momentum (see possible :b2:var:`weMissE` options)");
2181 REGISTER_VARIABLE(
"weMissP(maskName, opt)", WE_MissP,
2182 "Returns the magnitude of the missing momentum (see possible :b2:var:`weMissE` options)");
2184 REGISTER_VARIABLE(
"weMissPx(maskName, opt)", WE_MissPx,
2185 "Returns the x component of the missing momentum (see :b2:var:`weMissE` possible options)");
2187 REGISTER_VARIABLE(
"weMissPy(maskName, opt)", WE_MissPy,
2188 "Returns the y component of the missing momentum (see :b2:var:`weMissE` possible options)");
2190 REGISTER_VARIABLE(
"weMissPz(maskName, opt)", WE_MissPz,
2191 "Returns the z component of the missing momentum (see :b2:var:`weMissE` possible options)");
2193 REGISTER_VARIABLE(
"weMissE(maskName, opt)", WE_MissE,
2194 R
"DOC(Returns the energy of the missing momentum, possible options ``opt`` are the following:
2196 - ``0``: CMS, use energy and momentum of charged particles and photons
2197 - ``1``: CMS, same as ``0``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}`
2198 - ``2``: CMS, same as ``0``, fix :math:`E_\mathrm{roe} = E_\mathrm{cms}/2`
2199 - ``3``: CMS, use only energy and momentum of signal side
2200 - ``4``: CMS, same as ``3``, update with direction of ROE momentum
2201 - ``5``: LAB, use energy and momentum of charged particles and photons from whole event
2202 - ``6``: LAB, same as ``5``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}``
2203 - ``7``: CMS, correct pmiss 3-momentum vector with factor alpha so that :math:`d_E = 0`` (used for :math:`M_\mathrm{bc}` calculation).)DOC");
2205 REGISTER_VARIABLE("weXiZ(maskName)", WE_xiZ,
2206 "Returns Xi_z in event (for Bhabha suppression and two-photon scattering)");
2208 REGISTER_VARIABLE(
"bssMassDifference(maskName)", bssMassDifference,
2209 "Bs* - Bs mass difference");
2211 REGISTER_VARIABLE(
"weCosThetaEll(maskName)", WE_cosThetaEll, R
"DOC(
2213 Returns the angle between :math:`M` and lepton in :math:`W` rest frame in the decays of the type:
2214 :math:`M \to h_1 ... h_n \ell`, where W 4-momentum is given as
2217 p_W = p_\ell + p_\nu.
2219 The neutrino momentum is calculated from ROE taking into account the specified mask, and setting
2222 E_{\nu} = |p_{miss}|.
2226 REGISTER_VARIABLE("weQ2lnuSimple(maskName,option)", WE_q2lnuSimple,
2227 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2228 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2229 "By default, option is set to ``1`` (see :b2:var:`weMissE`). Unless you know what you are doing, keep this default value.");
2231 REGISTER_VARIABLE(
"weQ2lnu(maskName,option)", WE_q2lnu,
2232 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2233 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2234 "This calculation uses constraints from dE = 0 and Mbc = Mb to correct the neutrino direction. \n"
2235 "By default, option is set to ``7`` (see :b2:var:`weMissE`). Unless you know what you are doing, keep this default value.");
2237 REGISTER_VARIABLE(
"weMissM2OverMissE(maskName)", WE_MissM2OverMissE,
2238 "Returns missing mass squared over missing energy");
2240 REGISTER_VARIABLE(
"passesROEMask(maskName)", passesROEMask,
2241 "Returns boolean value if a particle passes a certain mask or not. Only to be used in for_each path, otherwise returns quiet NaN.");
2243 REGISTER_VARIABLE(
"printROE", printROE,
2244 "For debugging, prints indices of all particles in the ROE and all masks. Returns 0.");
2246 REGISTER_VARIABLE(
"pi0Prob(mode)", pi0Prob,
2247 "Returns pi0 probability, where mode is used to specify the selection criteria for soft photon. \n"
2248 "The following strings are available. \n\n"
2249 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2250 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2251 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2252 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2253 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.");
2255 REGISTER_VARIABLE(
"etaProb(mode)", etaProb,
2256 "Returns eta probability, where mode is used to specify the selection criteria for soft photon. \n"
2257 "The following strings are available. \n\n"
2258 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2259 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2260 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2261 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2262 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.");
Abstract base class for different kinds of events.