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!");
66 return std::numeric_limits<float>::quiet_NaN();
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!");
88 return std::numeric_limits<float>::quiet_NaN();
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();
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 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));
165 }
else return std::numeric_limits<double>::quiet_NaN();
171 Manager::FunctionPtr useROERecoilFrame(
const std::vector<std::string>& arguments)
173 if (arguments.size() == 1) {
174 const Variable::Manager::Var* var = Manager::Instance().getVariable(arguments[0]);
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!");
189 return std::numeric_limits<float>::quiet_NaN();
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));
204 }
else return std::numeric_limits<double>::quiet_NaN();
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;
230 Manager::FunctionPtr nROE_RemainingTracksWithMask(
const std::vector<std::string>& arguments)
232 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
257 return std::numeric_limits<float>::quiet_NaN();
260 return roe->getNKLMClusters();
263 double ROE_MC_E(
const Particle* particle)
268 return std::numeric_limits<float>::quiet_NaN();
271 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
272 auto mcroe4vector = boostvec - mcp->get4Vector();
273 const auto& frame = ReferenceFrame::GetCurrent();
274 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
275 return frameMCRoe4Vector.energy();
278 double ROE_MC_P(
const Particle* particle)
283 return std::numeric_limits<float>::quiet_NaN();
286 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
287 auto mcroe4vector = boostvec - mcp->get4Vector();
288 const auto& frame = ReferenceFrame::GetCurrent();
289 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
290 return frameMCRoe4Vector.P();
293 double ROE_MC_Px(
const Particle* particle)
298 return std::numeric_limits<float>::quiet_NaN();
301 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
302 auto mcroe4vector = boostvec - mcp->get4Vector();
303 const auto& frame = ReferenceFrame::GetCurrent();
304 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
306 return frameMCRoe4Vector.px();
309 double ROE_MC_Py(
const Particle* particle)
314 return std::numeric_limits<float>::quiet_NaN();
317 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
318 auto mcroe4vector = boostvec - mcp->get4Vector();
319 const auto& frame = ReferenceFrame::GetCurrent();
320 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
322 return frameMCRoe4Vector.py();
325 double ROE_MC_Pz(
const Particle* particle)
330 return std::numeric_limits<float>::quiet_NaN();
333 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
334 auto mcroe4vector = boostvec - mcp->get4Vector();
335 const auto& frame = ReferenceFrame::GetCurrent();
336 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
338 return frameMCRoe4Vector.pz();
341 double ROE_MC_Pt(
const Particle* particle)
346 return std::numeric_limits<float>::quiet_NaN();
349 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
350 auto mcroe4vector = boostvec - mcp->get4Vector();
351 const auto& frame = ReferenceFrame::GetCurrent();
352 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
354 return frameMCRoe4Vector.pt();
357 double ROE_MC_PTheta(
const Particle* particle)
362 return std::numeric_limits<float>::quiet_NaN();
365 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
366 auto mcroe4vector = boostvec - mcp->get4Vector();
367 const auto& frame = ReferenceFrame::GetCurrent();
368 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
370 return frameMCRoe4Vector.Theta();
373 double ROE_MC_M(
const Particle* particle)
378 return std::numeric_limits<float>::quiet_NaN();
381 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
383 return (boostvec - mcp->get4Vector()).M();
386 Manager::FunctionPtr ROE_MC_MissingFlags(
const std::vector<std::string>& arguments)
388 std::string maskName = RestOfEvent::c_defaultMaskName;
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;
403 return std::numeric_limits<float>::quiet_NaN();
406 const MCParticle* mcMother = mcParticle->getMother();
409 return std::numeric_limits<float>::quiet_NaN();
412 std::vector<MCParticle*> mcDaughters = mcMother->getDaughters();
414 if (mcDaughters.size() != 2)
415 return std::numeric_limits<float>::quiet_NaN();
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);
445 Manager::FunctionPtr nROE_Tracks(
const std::vector<std::string>& arguments)
447 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
462 return std::numeric_limits<float>::quiet_NaN();
465 return roe->getNTracks(maskName);
470 Manager::FunctionPtr nROE_ECLClusters(
const std::vector<std::string>& arguments)
472 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
487 return std::numeric_limits<float>::quiet_NaN();
490 return roe->getNECLClusters(maskName);
495 Manager::FunctionPtr nROE_NeutralECLClusters(
const std::vector<std::string>& arguments)
497 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
512 return std::numeric_limits<float>::quiet_NaN();
515 return roe->getPhotons(maskName).size();
520 Manager::FunctionPtr nROE_Photons(
const std::vector<std::string>& arguments)
522 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
537 return std::numeric_limits<float>::quiet_NaN();
541 auto roeClusters = roe->getPhotons(maskName);
545 for (
auto& roeCluster : roeClusters)
546 if (roeCluster->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons)
553 Manager::FunctionPtr nROE_NeutralHadrons(
const std::vector<std::string>& arguments)
555 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
570 return std::numeric_limits<float>::quiet_NaN();
573 return roe->getHadrons(maskName).size();
578 Manager::FunctionPtr nROE_ChargedParticles(
const std::vector<std::string>& arguments)
580 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
603 return std::numeric_limits<float>::quiet_NaN();
606 return roe->getChargedParticles(maskName, abs(pdgCode)).size();
611 Manager::FunctionPtr nROE_Composites(
const std::vector<std::string>& arguments)
613 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
628 return std::numeric_limits<float>::quiet_NaN();
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) {
645 Manager::FunctionPtr nROE_ParticlesInList(
const std::vector<std::string>& arguments)
647 std::string pListName;
648 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
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 = RestOfEvent::c_defaultMaskName;
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!");
705 return std::numeric_limits<float>::quiet_NaN();
709 auto roeParticles = roe->getParticles(maskName);
712 for (
auto* roeParticle : roeParticles)
714 roeCharge += roeParticle->getCharge();
722 Manager::FunctionPtr ROE_ExtraEnergy(
const std::vector<std::string>& arguments)
724 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
739 return std::numeric_limits<float>::quiet_NaN();
744 auto roeClusters = roe->getPhotons(maskName);
746 for (
auto& roeCluster : roeClusters)
747 if (roeCluster->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons)
748 extraE += roeCluster->getECLClusterEnergy();
750 auto roeChargedParticles = roe->getChargedParticles(maskName);
752 for (
auto& roeChargedParticle : roeChargedParticles)
754 if (roeChargedParticle->getECLCluster())
755 extraE += roeChargedParticle->getECLClusterEnergy();
763 Manager::FunctionPtr ROE_NeutralExtraEnergy(
const std::vector<std::string>& arguments)
765 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
780 return std::numeric_limits<float>::quiet_NaN();
782 auto roephotons = roe->getPhotons(maskName);
783 ROOT::Math::PxPyPzEVector total4vector;
784 for (
auto* photon : roephotons)
786 total4vector += photon->get4Vector();
788 const auto& frame = ReferenceFrame::GetCurrent();
789 auto frameRoe4Vector = frame.getMomentum(total4vector);
790 return frameRoe4Vector.energy();
795 Manager::FunctionPtr ROE_E(
const std::vector<std::string>& arguments)
797 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
809 return std::numeric_limits<float>::quiet_NaN();
811 const auto& frame = ReferenceFrame::GetCurrent();
812 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
813 return frameRoe4Vector.energy();
818 Manager::FunctionPtr ROE_M(
const std::vector<std::string>& arguments)
820 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
835 return std::numeric_limits<float>::quiet_NaN();
838 return roe->get4Vector(maskName).M();
843 Manager::FunctionPtr ROE_P(
const std::vector<std::string>& arguments)
845 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
860 return std::numeric_limits<float>::quiet_NaN();
863 const auto& frame = ReferenceFrame::GetCurrent();
864 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
865 return frameRoe4Vector.P();
870 Manager::FunctionPtr ROE_Px(
const std::vector<std::string>& arguments)
872 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
887 return std::numeric_limits<float>::quiet_NaN();
890 const auto& frame = ReferenceFrame::GetCurrent();
891 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
892 return frameRoe4Vector.px();
897 Manager::FunctionPtr ROE_Py(
const std::vector<std::string>& arguments)
899 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
914 return std::numeric_limits<float>::quiet_NaN();
917 const auto& frame = ReferenceFrame::GetCurrent();
918 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
919 return frameRoe4Vector.py();
924 Manager::FunctionPtr ROE_Pt(
const std::vector<std::string>& arguments)
926 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
941 return std::numeric_limits<float>::quiet_NaN();
944 const auto& frame = ReferenceFrame::GetCurrent();
945 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
946 return frameRoe4Vector.pt();
951 Manager::FunctionPtr ROE_Pz(
const std::vector<std::string>& arguments)
953 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
968 return std::numeric_limits<float>::quiet_NaN();
971 const auto& frame = ReferenceFrame::GetCurrent();
972 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
973 return frameRoe4Vector.pz();
978 Manager::FunctionPtr ROE_PTheta(
const std::vector<std::string>& arguments)
980 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
995 return std::numeric_limits<float>::quiet_NaN();
998 const auto& frame = ReferenceFrame::GetCurrent();
999 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
1000 return frameRoe4Vector.Theta();
1005 Manager::FunctionPtr ROE_DeltaE(
const std::vector<std::string>& arguments)
1007 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
1022 return std::numeric_limits<float>::quiet_NaN();
1026 ROOT::Math::PxPyPzEVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1027 return vec.E() - T.getCMSEnergy() / 2;
1032 Manager::FunctionPtr ROE_Mbc(
const std::vector<std::string>& arguments)
1034 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
1049 return std::numeric_limits<float>::quiet_NaN();
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;
1064 Manager::FunctionPtr bssMassDifference(
const std::vector<std::string>& arguments)
1066 std::string maskName = RestOfEvent::c_defaultMaskName;
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();
1087 Manager::FunctionPtr WE_DeltaE(
const std::vector<std::string>& arguments)
1089 std::string maskName;
1092 if (arguments.size() == 1) {
1093 maskName = RestOfEvent::c_defaultMaskName;
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");
1110 double deltaE = std::numeric_limits<float>::quiet_NaN();
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)");
1136 Manager::FunctionPtr WE_Mbc(
const std::vector<std::string>& arguments)
1138 std::string maskName;
1141 if (arguments.size() == 1) {
1142 maskName = RestOfEvent::c_defaultMaskName;
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;
1158 double mbc = std::numeric_limits<float>::quiet_NaN();
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)");
1199 Manager::FunctionPtr WE_MissM2(
const std::vector<std::string>& arguments)
1201 std::string maskName;
1204 if (arguments.size() == 1) {
1205 maskName = RestOfEvent::c_defaultMaskName;
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();
1220 Manager::FunctionPtr WE_MissPTheta(
const std::vector<std::string>& arguments)
1222 std::string maskName;
1225 if (arguments.size() == 1) {
1226 maskName = RestOfEvent::c_defaultMaskName;
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!");
1242 return std::numeric_limits<float>::quiet_NaN();
1245 return missing4Vector(particle, maskName, opt).Theta();
1250 Manager::FunctionPtr WE_MissP(
const std::vector<std::string>& arguments)
1252 std::string maskName;
1255 if (arguments.size() == 1) {
1256 maskName = RestOfEvent::c_defaultMaskName;
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!");
1272 return std::numeric_limits<float>::quiet_NaN();
1275 return missing4Vector(particle, maskName, opt).P();
1280 Manager::FunctionPtr WE_MissPx(
const std::vector<std::string>& arguments)
1282 std::string maskName;
1285 if (arguments.size() == 1) {
1286 maskName = RestOfEvent::c_defaultMaskName;
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!");
1302 return std::numeric_limits<float>::quiet_NaN();
1305 return missing4Vector(particle, maskName, opt).Px();
1310 Manager::FunctionPtr WE_MissPy(
const std::vector<std::string>& arguments)
1312 std::string maskName;
1315 if (arguments.size() == 1) {
1316 maskName = RestOfEvent::c_defaultMaskName;
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!");
1332 return std::numeric_limits<float>::quiet_NaN();
1335 return missing4Vector(particle, maskName, opt).Py();
1340 Manager::FunctionPtr WE_MissPz(
const std::vector<std::string>& arguments)
1342 std::string maskName;
1345 if (arguments.size() == 1) {
1346 maskName = RestOfEvent::c_defaultMaskName;
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!");
1362 return std::numeric_limits<float>::quiet_NaN();
1365 return missing4Vector(particle, maskName, opt).Pz();
1370 Manager::FunctionPtr WE_MissE(
const std::vector<std::string>& arguments)
1372 std::string maskName;
1375 if (arguments.size() == 1) {
1376 maskName = RestOfEvent::c_defaultMaskName;
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!");
1392 return std::numeric_limits<float>::quiet_NaN();
1395 return missing4Vector(particle, maskName, opt).energy();
1400 Manager::FunctionPtr WE_xiZ(
const std::vector<std::string>& arguments)
1402 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
1417 return std::numeric_limits<float>::quiet_NaN();
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();
1446 Manager::FunctionPtr WE_MissM2OverMissE(
const std::vector<std::string>& arguments)
1448 std::string maskName = RestOfEvent::c_defaultMaskName;
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!");
1463 return std::numeric_limits<float>::quiet_NaN();
1466 return missing4Vector(particle, maskName,
"5").M2() / (2.0 * missing4Vector(particle, maskName,
"5").energy());
1471 Manager::FunctionPtr WE_q2lnuSimple(
const std::vector<std::string>& arguments)
1473 std::string maskName(RestOfEvent::c_defaultMaskName);
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!");
1493 return std::numeric_limits<float>::quiet_NaN();
1496 int n = particle->getNDaughters();
1499 return std::numeric_limits<float>::quiet_NaN();
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();
1512 Manager::FunctionPtr WE_q2lnu(
const std::vector<std::string>& arguments)
1514 std::string maskName(RestOfEvent::c_defaultMaskName);
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!");
1534 return std::numeric_limits<float>::quiet_NaN();
1537 int n = particle->getNDaughters();
1540 return std::numeric_limits<float>::quiet_NaN();
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();
1600 Manager::FunctionPtr WE_cosThetaEll(
const std::vector<std::string>& arguments)
1602 std::string maskName = RestOfEvent::c_defaultMaskName;
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());
1618 if (absPDG == Const::electron.getPDGCode() || absPDG == Const::muon.getPDGCode() || absPDG == 15) {
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;
1642 Manager::FunctionPtr passesROEMask(
const std::vector<std::string>& arguments)
1644 std::string maskName = RestOfEvent::c_defaultMaskName;
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())
1657 return std::numeric_limits<float>::quiet_NaN();
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 Manager::FunctionPtr pi0Prob(
const std::vector<std::string>& arguments)
1681 if (arguments.size() != 1)
1682 B2ERROR(
"Wrong number of arguments (1 required) for pi0Prob");
1685 mode = arguments[0];
1687 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1688 B2ERROR(
"the given argument is not supported in pi0Prob!");
1690 auto func = [mode](
const Particle * particle) ->
double {
1691 if (mode ==
"standard")
1693 if (particle->hasExtraInfo(
"Pi0ProbOrigin")) {
1694 return particle->getExtraInfo(
"Pi0ProbOrigin");
1696 B2WARNING(
"Pi0ProbOrigin is not registerted in extraInfo! \n"
1697 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1698 return std::numeric_limits<float>::quiet_NaN();
1700 }
else if (mode ==
"tight")
1702 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThreshold")) {
1703 return particle->getExtraInfo(
"Pi0ProbTightEnergyThreshold");
1705 B2WARNING(
"Pi0ProbTightEnergyThreshold is not registerted in extraInfo! \n"
1706 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1707 return std::numeric_limits<float>::quiet_NaN();
1709 }
else if (mode ==
"cluster")
1711 if (particle->hasExtraInfo(
"Pi0ProbLargeClusterSize")) {
1712 return particle->getExtraInfo(
"Pi0ProbLargeClusterSize");
1714 B2WARNING(
"Pi0ProbLargeClusterSize is not registerted in extraInfo! \n"
1715 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1716 return std::numeric_limits<float>::quiet_NaN();
1718 }
else if (mode ==
"both")
1720 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize")) {
1721 return particle->getExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize");
1723 B2WARNING(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1724 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1725 return std::numeric_limits<float>::quiet_NaN();
1729 return std::numeric_limits<float>::quiet_NaN();
1735 Manager::FunctionPtr etaProb(
const std::vector<std::string>& arguments)
1737 if (arguments.size() != 1)
1738 B2ERROR(
"Wrong number of arguments (1 required) for etaProb");
1741 mode = arguments[0];
1743 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1744 B2ERROR(
"the given argument is not supported in etaProb!");
1746 auto func = [mode](
const Particle * particle) ->
double {
1747 if (mode ==
"standard")
1749 if (particle->hasExtraInfo(
"EtaProbOrigin")) {
1750 return particle->getExtraInfo(
"EtaProbOrigin");
1752 B2WARNING(
"EtaProbOrigin is not registerted in extraInfo! \n"
1753 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1754 return std::numeric_limits<float>::quiet_NaN();
1756 }
else if (mode ==
"tight")
1758 if (particle->hasExtraInfo(
"EtaProbTightEnergyThreshold")) {
1759 return particle->getExtraInfo(
"EtaProbTightEnergyThreshold");
1761 B2WARNING(
"EtaProbTightEnergyThreshold is not registerted in extraInfo! \n"
1762 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1763 return std::numeric_limits<float>::quiet_NaN();
1765 }
else if (mode ==
"cluster")
1767 if (particle->hasExtraInfo(
"EtaProbLargeClusterSize")) {
1768 return particle->getExtraInfo(
"EtaProbLargeClusterSize");
1770 B2WARNING(
"EtaProbLargeClusterSize is not registerted in extraInfo! \n"
1771 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1772 return std::numeric_limits<float>::quiet_NaN();
1774 }
else if (mode ==
"both")
1776 if (particle->hasExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize")) {
1777 return particle->getExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize");
1779 B2WARNING(
"EtaProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1780 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1781 return std::numeric_limits<float>::quiet_NaN();
1785 return std::numeric_limits<float>::quiet_NaN();
1795 ROOT::Math::PxPyPzEVector missing4Vector(
const Particle* particle,
const std::string& maskName,
const std::string& opt)
1798 const RestOfEvent* roe = getRelatedROEObject(particle);
1801 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1802 ROOT::Math::PxPyPzEVector empty;
1807 ROOT::Math::PxPyPzEVector boostvec = T.getBeamFourMomentum();
1809 ROOT::Math::PxPyPzEVector rec4vecLAB = particle->get4Vector();
1810 ROOT::Math::PxPyPzEVector roe4vecLAB = roe->get4Vector(maskName);
1812 ROOT::Math::PxPyPzEVector rec4vec = T.rotateLabToCms() * rec4vecLAB;
1813 ROOT::Math::PxPyPzEVector roe4vec = T.rotateLabToCms() * roe4vecLAB;
1815 ROOT::Math::PxPyPzEVector miss4vec;
1816 double E_beam_cms = T.getCMSEnergy() / 2.0;
1820 miss4vec = - (rec4vec + roe4vec);
1821 miss4vec.SetE(2 * E_beam_cms - (rec4vec.E() + roe4vec.E()));
1825 else if (opt ==
"1") {
1826 miss4vec = - (rec4vec + roe4vec);
1827 miss4vec.SetE(miss4vec.P());
1831 else if (opt ==
"2") {
1832 miss4vec = - (rec4vec + roe4vec);
1833 miss4vec.SetE(E_beam_cms - rec4vec.E());
1837 else if (opt ==
"3") {
1838 miss4vec = - rec4vec;
1839 miss4vec.SetE(E_beam_cms - rec4vec.E());
1843 else if (opt ==
"4") {
1846 pB -= rec4vec.Vect();
1847 miss4vec.SetPxPyPzE(pB.x(), pB.y(), pB.z(), E_beam_cms - rec4vec.E());
1851 else if (opt ==
"5") {
1852 miss4vec = boostvec - (rec4vecLAB + roe4vecLAB);
1856 else if (opt ==
"6") {
1857 miss4vec = boostvec - (rec4vecLAB + roe4vecLAB);
1858 miss4vec.SetE(miss4vec.P());
1862 else if (opt ==
"7") {
1863 miss4vec = - (rec4vec + roe4vec);
1864 miss4vec.SetE(miss4vec.P());
1865 double factorAlpha = (E_beam_cms - rec4vec.E()) / miss4vec.E();
1866 miss4vec *= factorAlpha;
1867 miss4vec.SetE(miss4vec.P());
1873 void checkMCParticleMissingFlags(
const MCParticle* mcp, std::set<const MCParticle*> mcROEObjects,
int& missingFlags)
1875 std::vector<MCParticle*> daughters = mcp->getDaughters();
1876 for (
auto& daughter : daughters) {
1878 if (!daughter->hasStatus(MCParticle::c_PrimaryParticle))
1881 if (mcROEObjects.find(daughter) == mcROEObjects.end()) {
1883 int pdg = abs(daughter->getPDG());
1886 if (pdg == Const::photon.getPDGCode() and (missingFlags & 1) == 0)
1890 else if (pdg == Const::electron.getPDGCode() and (missingFlags & 2) == 0)
1894 else if (pdg == Const::muon.getPDGCode() and (missingFlags & 4) == 0)
1898 else if (pdg == Const::pion.getPDGCode() and (missingFlags & 8) == 0)
1902 else if (pdg == Const::kaon.getPDGCode() and (missingFlags & 16) == 0)
1906 else if (pdg == Const::proton.getPDGCode() and (missingFlags & 32) == 0)
1910 else if (pdg == Const::neutron.getPDGCode() and (missingFlags & 64) == 0)
1914 else if (pdg == Const::Kshort.getPDGCode() and ((missingFlags & 128) == 0 or (missingFlags & 256) == 0)) {
1915 std::vector<MCParticle*> ksDaug = daughter->getDaughters();
1916 if (ksDaug.size() == 2) {
1918 if (abs(ksDaug[0]->getPDG()) == Const::pion.getPDGCode() and abs(ksDaug[1]->getPDG()) == Const::pion.getPDGCode()
1919 and (missingFlags & 128) == 0) {
1920 if (mcROEObjects.find(ksDaug[0]) == mcROEObjects.end() or mcROEObjects.find(ksDaug[1]) == mcROEObjects.end())
1921 missingFlags += 128;
1924 else if (abs(ksDaug[0]->getPDG()) == Const::pi0.getPDGCode() and abs(ksDaug[1]->getPDG()) == Const::pi0.getPDGCode()
1925 and (missingFlags & 256) == 0) {
1926 std::vector<MCParticle*> pi0Daug0 = ksDaug[0]->getDaughters();
1927 std::vector<MCParticle*> pi0Daug1 = ksDaug[1]->getDaughters();
1928 if (mcROEObjects.find(pi0Daug0[0]) == mcROEObjects.end() or
1929 mcROEObjects.find(pi0Daug0[1]) == mcROEObjects.end() or
1930 mcROEObjects.find(pi0Daug1[0]) == mcROEObjects.end() or
1931 mcROEObjects.find(pi0Daug1[1]) == mcROEObjects.end())
1932 missingFlags += 256;
1938 else if (pdg == Const::Klong.getPDGCode() and (missingFlags & 512) == 0)
1939 missingFlags += 512;
1942 else if ((pdg == 12 or pdg == 14 or pdg == 16) and (missingFlags & 1024) == 0)
1943 missingFlags += 1024;
1945 checkMCParticleMissingFlags(daughter, mcROEObjects, missingFlags);
1949 double isInThisRestOfEvent(
const Particle* particle,
const RestOfEvent* roe,
const std::string& maskName)
1951 if (particle->getParticleSource() == Particle::c_Composite or
1952 particle->getParticleSource() == Particle::c_V0) {
1953 std::vector<const Particle*> fspDaug = particle->getFinalStateDaughters();
1954 for (
auto& i : fspDaug) {
1955 if (isInThisRestOfEvent(i, roe, maskName) == 0)
1960 return roe->hasParticle(particle, maskName);
1963 const RestOfEvent* getRelatedROEObject(
const Particle* particle,
bool returnHostOnly)
1966 const RestOfEvent* roe = particle->
getRelatedTo<RestOfEvent>();
1967 if (!roe && !returnHostOnly) {
1968 roe = particle->getRelatedTo<RestOfEvent>(
"NestedRestOfEvents");
1974 VARIABLE_GROUP(
"Rest Of Event");
1976 REGISTER_METAVARIABLE(
"useROERecoilFrame(variable)", useROERecoilFrame,
1977 "Returns the value of the variable using the rest frame of the ROE recoil as current reference frame.\n"
1978 "Can be used inside for_each loop or outside of it if the particle has associated Rest of Event.\n"
1979 "E.g. ``useROERecoilFrame(E)`` returns the energy of a particle in the ROE recoil frame.", Manager::VariableDataType::c_double);
1981 REGISTER_VARIABLE(
"isInRestOfEvent", isInRestOfEvent,
1982 "Returns 1 if a track, ecl or klmCluster associated to particle is in the current RestOfEvent object, 0 otherwise."
1983 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
1985 REGISTER_VARIABLE(
"isCloneOfSignalSide", isCloneOfSignalSide,
1986 "Returns 1 if a particle is a clone of signal side final state particles, 0 otherwise. "
1987 "Requires generator information and truth-matching. "
1988 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
1990 REGISTER_VARIABLE(
"hasAncestorFromSignalSide", hasAncestorFromSignalSide,
1991 "Returns 1 if a particle has ancestor from signal side, 0 otherwise. "
1992 "Requires generator information and truth-matching. "
1993 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
1995 REGISTER_METAVARIABLE(
"currentROEIsInList(particleList)", currentROEIsInList,
1996 "[Eventbased] Returns 1 the associated particle of the current ROE is contained in the given list or its charge-conjugated."
1997 "Useful to restrict the for_each loop over ROEs to ROEs of a certain ParticleList.", Manager::VariableDataType::c_double);
1999 REGISTER_VARIABLE(
"nROE_RemainingTracks", nROE_RemainingTracks,
2000 "Returns number of tracks in ROE - number of tracks of given particle"
2001 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2003 REGISTER_METAVARIABLE(
"nROE_RemainingTracks(maskName)", nROE_RemainingTracksWithMask,
2004 "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."
2005 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray."
2006 "Is required for the specific FEI. :noindex:", Manager::VariableDataType::c_int);
2011 REGISTER_VARIABLE(
"nROE_KLMClusters", nROE_KLMClusters,
2012 "Returns number of all remaining KLM clusters in the related RestOfEvent object.");
2014 REGISTER_METAVARIABLE(
"nROE_Charged(maskName, PDGcode = 0)", nROE_ChargedParticles,
2015 "Returns number of all charged particles in the related RestOfEvent object. First optional argument is ROE mask name. "
2016 "Second argument is a PDG code to count only one charged particle species, independently of charge. "
2017 "For example: ``nROE_Charged(cleanMask, 321)`` will output number of kaons in Rest Of Event with ``cleanMask``. "
2018 "PDG code 0 is used to count all charged particles", Manager::VariableDataType::c_double);
2020 REGISTER_METAVARIABLE(
"nROE_Photons(maskName)", nROE_Photons,
2021 "Returns number of all photons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ",
2022 Manager::VariableDataType::c_double);
2024 REGISTER_METAVARIABLE(
"nROE_NeutralHadrons(maskName)", nROE_NeutralHadrons,
2025 "Returns number of all neutral hadrons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ",
2026 Manager::VariableDataType::c_double);
2028 REGISTER_METAVARIABLE(
"particleRelatedToCurrentROE(var)", particleRelatedToCurrentROE,
2029 "[Eventbased] Returns variable applied to the particle which is related to the current RestOfEvent object"
2030 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.", Manager::VariableDataType::c_double);
2032 REGISTER_VARIABLE(
"roeMC_E", ROE_MC_E,
2033 "Returns true energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
"GeV");
2035 REGISTER_VARIABLE(
"roeMC_M", ROE_MC_M,
2036 "Returns true invariant mass of unused tracks and clusters in ROE",
"GeV/:math:`\\text{c}^2`");
2038 REGISTER_VARIABLE(
"roeMC_P", ROE_MC_P,
2039 "Returns true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
"GeV/c");
2041 REGISTER_VARIABLE(
"roeMC_Px", ROE_MC_Px,
2042 "Returns x component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
"GeV/c");
2044 REGISTER_VARIABLE(
"roeMC_Py", ROE_MC_Py,
2045 "Returns y component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
"GeV/c");
2047 REGISTER_VARIABLE(
"roeMC_Pz", ROE_MC_Pz,
2048 "Returns z component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
"GeV/c");
2050 REGISTER_VARIABLE(
"roeMC_Pt", ROE_MC_Pt,
2051 "Returns transverse component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
2054 REGISTER_VARIABLE(
"roeMC_PTheta", ROE_MC_PTheta,
2055 "Returns polar angle of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.",
"rad");
2057 REGISTER_METAVARIABLE(
"roeMC_MissFlags(maskName)", ROE_MC_MissingFlags,
2058 "Returns flags corresponding to missing particles on ROE side.", Manager::VariableDataType::c_double);
2060 REGISTER_METAVARIABLE(
"nROE_Tracks(maskName)", nROE_Tracks,
2061 "Returns number of tracks in the related RestOfEvent object that pass the selection criteria.",
2062 Manager::VariableDataType::c_double);
2064 REGISTER_METAVARIABLE(
"nROE_ECLClusters(maskName)", nROE_ECLClusters,
2065 "Returns number of ECL clusters in the related RestOfEvent object that pass the selection criteria.",
2066 Manager::VariableDataType::c_double);
2068 REGISTER_METAVARIABLE(
"nROE_NeutralECLClusters(maskName)", nROE_NeutralECLClusters,
2069 "Returns number of neutral ECL clusters in the related RestOfEvent object that pass the selection criteria.",
2070 Manager::VariableDataType::c_double);
2072 REGISTER_METAVARIABLE(
"nROE_Composites(maskName)", nROE_Composites,
2073 "Returns number of composite particles or V0s in the related RestOfEvent object that pass the selection criteria.",
2074 Manager::VariableDataType::c_double);
2076 REGISTER_METAVARIABLE(
"nROE_ParticlesInList(pListName[, maskName])", nROE_ParticlesInList,
2077 "Returns the number of particles in ROE from the given particle list. If a mask name is provided the selection criteria are applied.\n"
2078 "Use of variable aliases is advised.", Manager::VariableDataType::c_double);
2080 REGISTER_METAVARIABLE(
"roeCharge(maskName)", ROE_Charge,
2081 "Returns total charge of the related RestOfEvent object. The unit of the charge is ``e`` ", Manager::VariableDataType::c_double);
2083 REGISTER_METAVARIABLE(
"roeEextra(maskName)", ROE_ExtraEnergy,
2084 "Returns extra energy from ECLClusters in the calorimeter that is not associated to the given Particle. The unit of the energy is ``GeV`` ",
2085 Manager::VariableDataType::c_double);
2087 REGISTER_METAVARIABLE(
"roeNeextra(maskName)", ROE_NeutralExtraEnergy,
2088 "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`` ",
2089 Manager::VariableDataType::c_double);
2091 REGISTER_METAVARIABLE(
"roeE(maskName)", ROE_E,
2092 "Returns energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the energy is ``GeV`` ",
2093 Manager::VariableDataType::c_double);
2095 REGISTER_METAVARIABLE(
"roeM(maskName)", ROE_M,
2096 "Returns invariant mass of unused tracks and clusters in ROE. The unit of the invariant mass is :math:`\\text{GeV/c}^2`",
2097 Manager::VariableDataType::c_double);
2099 REGISTER_METAVARIABLE(
"roeP(maskName)", ROE_P,
2100 "Returns momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function. The unit of the momentum is ``GeV/c`` ",
2101 Manager::VariableDataType::c_double);
2103 REGISTER_METAVARIABLE(
"roePt(maskName)", ROE_Pt,
2104 "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`` ",
2105 Manager::VariableDataType::c_double);
2107 REGISTER_METAVARIABLE(
"roePx(maskName)", ROE_Px,
2108 "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`` ",
2109 Manager::VariableDataType::c_double);
2111 REGISTER_METAVARIABLE(
"roePy(maskName)", ROE_Py,
2112 "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`` ",
2113 Manager::VariableDataType::c_double);
2115 REGISTER_METAVARIABLE(
"roePz(maskName)", ROE_Pz,
2116 "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`` ",
2117 Manager::VariableDataType::c_double);
2119 REGISTER_METAVARIABLE(
"roePTheta(maskName)", ROE_PTheta,
2120 "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`` ",
2121 Manager::VariableDataType::c_double);
2123 REGISTER_METAVARIABLE(
"roeDeltae(maskName)", ROE_DeltaE,
2124 "Returns energy difference of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`. The unit of the energy is ``GeV`` ",
2125 Manager::VariableDataType::c_double);
2127 REGISTER_METAVARIABLE(
"roeMbc(maskName)", ROE_Mbc,
2128 "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`.",
2129 Manager::VariableDataType::c_double);
2131 REGISTER_METAVARIABLE(
"weDeltae(maskName, opt)", WE_DeltaE,
2132 "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`` ",
2133 Manager::VariableDataType::c_double);
2135 REGISTER_METAVARIABLE(
"weMbc(maskName, opt)", WE_Mbc,
2136 "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`.",
2137 Manager::VariableDataType::c_double);
2139 REGISTER_METAVARIABLE(
"weMissM2(maskName, opt)", WE_MissM2,
2140 "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`.",
2141 Manager::VariableDataType::c_double);
2143 REGISTER_METAVARIABLE(
"weMissPTheta(maskName, opt)", WE_MissPTheta,
2144 "Returns the polar angle of the missing momentum (see possible :b2:var:`weMissE` options). The unit of the polar angle is ``rad`` ",
2145 Manager::VariableDataType::c_double);
2147 REGISTER_METAVARIABLE(
"weMissP(maskName, opt)", WE_MissP,
2148 "Returns the magnitude of the missing momentum (see possible :b2:var:`weMissE` options). The unit of the magnitude of missing momentum is ``GeV/c`` ",
2149 Manager::VariableDataType::c_double);
2151 REGISTER_METAVARIABLE(
"weMissPx(maskName, opt)", WE_MissPx,
2152 "Returns the x component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2153 Manager::VariableDataType::c_double);
2155 REGISTER_METAVARIABLE(
"weMissPy(maskName, opt)", WE_MissPy,
2156 "Returns the y component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2157 Manager::VariableDataType::c_double);
2159 REGISTER_METAVARIABLE(
"weMissPz(maskName, opt)", WE_MissPz,
2160 "Returns the z component of the missing momentum (see :b2:var:`weMissE` possible options). The unit of the missing momentum is ``GeV/c`` ",
2161 Manager::VariableDataType::c_double);
2163 REGISTER_METAVARIABLE(
"weMissE(maskName, opt)", WE_MissE,
2164 R
"DOC(Returns the energy of the missing momentum. The unit of the Energy is ``GeV`` . Possible options ``opt`` are the following:
2166 - ``0``: CMS, use energy and momentum of charged particles and photons
2167 - ``1``: CMS, same as ``0``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}`
2168 - ``2``: CMS, same as ``0``, fix :math:`E_\mathrm{roe} = E_\mathrm{cms}/2`
2169 - ``3``: CMS, use only energy and momentum of signal side
2170 - ``4``: CMS, same as ``3``, update with direction of ROE momentum
2171 - ``5``: LAB, use energy and momentum of charged particles and photons from whole event
2172 - ``6``: LAB, same as ``5``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}``
2173 - ``7``: CMS, correct pmiss 3-momentum vector with factor alpha so that :math:`d_E = 0`` (used for :math:`M_\mathrm{bc}` calculation).)DOC",
2174 Manager::VariableDataType::c_double);
2176 REGISTER_METAVARIABLE("weXiZ(maskName)", WE_xiZ,
2177 "Returns Xi_z in event (for Bhabha suppression and two-photon scattering). The unit of this variable is ``1/c`` ",
2178 Manager::VariableDataType::c_double);
2180 REGISTER_METAVARIABLE(
"bssMassDifference(maskName)", bssMassDifference,
2181 "Bs* - Bs mass difference. The unit of the mass is :math:`\\text{GeV/c}^2`.", Manager::VariableDataType::c_double);
2183 REGISTER_METAVARIABLE(
"weCosThetaEll(maskName)", WE_cosThetaEll, R
"DOC(
2185 Returns the cosine of the angle between :math:`M` and lepton in :math:`W` rest frame in the decays of the type:
2186 :math:`M \to h_1 ... h_n \ell`, where W 4-momentum is given as
2189 p_W = p_\ell + p_\nu.
2191 The neutrino momentum is calculated from ROE taking into account the specified mask, and setting
2194 E_{\nu} = |p_{miss}|.
2196 )DOC", Manager::VariableDataType::c_double);
2198 REGISTER_METAVARIABLE("weQ2lnuSimple(maskName,option)", WE_q2lnuSimple,
2199 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2200 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2201 "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);
2203 REGISTER_METAVARIABLE(
"weQ2lnu(maskName,option)", WE_q2lnu,
2204 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2205 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2206 "This calculation uses constraints from dE = 0 and Mbc = Mb to correct the neutrino direction. \n"
2207 "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);
2209 REGISTER_METAVARIABLE(
"weMissM2OverMissE(maskName)", WE_MissM2OverMissE,
2210 "Returns missing mass squared over missing energy. The unit of the missing mass squared is :math:`\\text{GeV/c}^4`.", Manager::VariableDataType::c_double);
2212 REGISTER_METAVARIABLE(
"passesROEMask(maskName)", passesROEMask,
2213 "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);
2215 REGISTER_VARIABLE(
"printROE", printROE,
2216 "For debugging, prints indices of all particles in the ROE and all masks. Returns 0.");
2218 REGISTER_METAVARIABLE(
"pi0Prob(mode)", pi0Prob,
2219 "Returns pi0 probability, where mode is used to specify the selection criteria for soft photon. \n"
2220 "The following strings are available. \n\n"
2221 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2222 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2223 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2224 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2225 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.", Manager::VariableDataType::c_double);
2227 REGISTER_METAVARIABLE(
"etaProb(mode)", etaProb,
2228 "Returns eta probability, where mode is used to specify the selection criteria for soft photon. \n"
2229 "The following strings are available. \n\n"
2230 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2231 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2232 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2233 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2234 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.", Manager::VariableDataType::c_double);
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
void SetMag(DataType mag)
Set magnitude keeping theta and phi constant.
DataType Mag2() const
The magnitude squared (rho^2 in spherical coordinate system).
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
const MCParticle * getMCParticle() const
Returns the pointer to the MCParticle object that was used to create this Particle (ParticleType == c...
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Abstract base class for different kinds of events.