12 #include <analysis/variables/ROEVariables.h>
13 #include <analysis/variables/Variables.h>
14 #include <analysis/utility/PCmsLabTransform.h>
16 #include <analysis/VariableManager/Manager.h>
19 #include <framework/datastore/StoreArray.h>
20 #include <framework/datastore/StoreObjPtr.h>
23 #include <analysis/dataobjects/Particle.h>
24 #include <analysis/dataobjects/ParticleList.h>
26 #include <mdst/dataobjects/ECLCluster.h>
29 #include <framework/logging/Logger.h>
32 #include <analysis/utility/ReferenceFrame.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->getRelatedTo<MCParticle>();
72 auto* signal = roe->getRelatedFrom<Particle>();
73 auto signalFSPs = signal->getFinalStateDaughters();
74 for (
auto* daughter : signalFSPs) {
75 auto* daughterMC = daughter->getRelatedTo<MCParticle>();
76 if (daughterMC == particleMC) {
82 double hasAncestorFromSignalSide(
const Particle* particle)
84 StoreObjPtr<RestOfEvent> roe;
86 B2WARNING(
"Please use hasAncestorFromSignalSide variable in for_each ROE loop!");
87 return std::numeric_limits<float>::quiet_NaN();
89 auto* particleMC = particle->getRelatedTo<MCParticle>();
94 auto* signalMC = signalReco->getRelatedTo<MCParticle>();
95 MCParticle* ancestorMC = particleMC->getMother();
97 if (ancestorMC == signalMC) {
100 ancestorMC = ancestorMC->getMother();
107 Manager::FunctionPtr currentROEIsInList(
const std::vector<std::string>& arguments)
109 if (arguments.size() != 1)
110 B2FATAL(
"Wrong number of arguments (1 required) for meta function currentROEIsInList");
112 std::string listName = arguments[0];
114 auto func = [listName](
const Particle*) ->
double {
116 StoreObjPtr<ParticleList> particleList(listName);
117 if (!(particleList.isValid()))
119 B2FATAL(
"Invalid Listname " << listName <<
" given to currentROEIsInList!");
121 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
123 if (not roe.isValid())
126 auto* particle = roe->getRelatedFrom<Particle>();
127 if (particle ==
nullptr)
129 B2ERROR(
"Relation between particle and ROE doesn't exist! currentROEIsInList() variable has to be called from ROE loop");
130 return std::numeric_limits<float>::quiet_NaN();
132 return particleList->contains(particle) ? 1 : 0;
138 Manager::FunctionPtr particleRelatedToCurrentROE(
const std::vector<std::string>& arguments)
140 if (arguments.size() != 1)
141 B2FATAL(
"Wrong number of arguments (1 required) for meta function particleRelatedToCurrentROE");
143 const Variable::Manager::Var* var = Manager::Instance().getVariable(arguments[0]);
144 auto func = [var](
const Particle*) ->
double {
146 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
148 if (not roe.isValid())
149 return std::numeric_limits<float>::quiet_NaN();
151 auto* particle = roe->getRelatedFrom<Particle>();
152 if (particle ==
nullptr)
154 B2ERROR(
"Relation between particle and ROE doesn't exist! particleRelatedToCurrentROE() variable has to be called from ROE loop");
155 return std::numeric_limits<float>::quiet_NaN();
157 return var->function(particle);
163 Manager::FunctionPtr useROERecoilFrame(
const std::vector<std::string>& arguments)
165 if (arguments.size() == 1) {
166 const Variable::Manager::Var* var = Manager::Instance().getVariable(arguments[0]);
167 auto func = [var](
const Particle * particle) ->
double {
169 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
173 StoreObjPtr<RestOfEvent> roeObjPtr(
"RestOfEvent");
174 if (roeObjPtr.isValid()) {
180 B2ERROR(
"Neither relation between particle and ROE doesn't exist nor ROE object has not been found!");
181 return std::numeric_limits<float>::quiet_NaN();
184 TLorentzVector pRecoil = T.getBeamFourMomentum() - roe->get4Vector();
185 Particle tmp(pRecoil, 0);
186 UseReferenceFrame<RestFrame> frame(&tmp);
187 double result = var->function(particle);
192 B2WARNING(
"Wrong number of arguments for meta function useROERecoilFrame");
198 double nRemainingTracksInROE(
const Particle* particle,
const std::string& maskName)
200 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
201 if (not roe.isValid())
203 int n_roe_tracks = roe->getNTracks(maskName);
204 int n_par_tracks = 0;
205 const auto& daughters = particle->getFinalStateDaughters();
206 for (
const auto& daughter : daughters) {
207 if (daughter->getParticleSource() == Particle::EParticleSourceObject::c_Track && roe->hasParticle(daughter, maskName)) {
211 return n_roe_tracks - n_par_tracks;
214 Manager::FunctionPtr nROE_RemainingTracksWithMask(
const std::vector<std::string>& arguments)
216 std::string maskName;
218 if (arguments.size() == 0)
220 else if (arguments.size() == 1)
221 maskName = arguments[0];
223 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROETracks");
225 auto func = [maskName](
const Particle * particle) ->
double {
226 return nRemainingTracksInROE(particle, maskName);
231 double nROE_RemainingTracks(
const Particle* particle)
233 return nRemainingTracksInROE(particle);
236 double nROE_KLMClusters(
const Particle* particle)
239 const RestOfEvent* roe = getRelatedROEObject(particle);
242 B2ERROR(
"Relation between particle and ROE doesn't exist!");
246 return roe->getNKLMClusters();
249 double ROE_MC_E(
const Particle* particle)
251 const MCParticle* mcp = particle->getRelated<MCParticle>();
254 return std::numeric_limits<float>::quiet_NaN();
257 TLorentzVector boostvec = T.getBeamFourMomentum();
258 auto mcroe4vector = boostvec - mcp->get4Vector();
259 const auto& frame = ReferenceFrame::GetCurrent();
260 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
261 return frameMCRoe4Vector.Energy();
264 double ROE_MC_P(
const Particle* particle)
266 const MCParticle* mcp = particle->getRelated<MCParticle>();
269 return std::numeric_limits<float>::quiet_NaN();
272 TLorentzVector boostvec = T.getBeamFourMomentum();
273 auto mcroe4vector = boostvec - mcp->get4Vector();
274 const auto& frame = ReferenceFrame::GetCurrent();
275 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
276 return frameMCRoe4Vector.Vect().Mag();
279 double ROE_MC_Px(
const Particle* particle)
281 const MCParticle* mcp = particle->getRelated<MCParticle>();
284 return std::numeric_limits<float>::quiet_NaN();
287 TLorentzVector boostvec = T.getBeamFourMomentum();
288 auto mcroe4vector = boostvec - mcp->get4Vector();
289 const auto& frame = ReferenceFrame::GetCurrent();
290 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
292 return frameMCRoe4Vector.Vect().X();
295 double ROE_MC_Py(
const Particle* particle)
297 const MCParticle* mcp = particle->getRelated<MCParticle>();
300 return std::numeric_limits<float>::quiet_NaN();
303 TLorentzVector boostvec = T.getBeamFourMomentum();
304 auto mcroe4vector = boostvec - mcp->get4Vector();
305 const auto& frame = ReferenceFrame::GetCurrent();
306 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
308 return frameMCRoe4Vector.Vect().Y();
311 double ROE_MC_Pz(
const Particle* particle)
313 const MCParticle* mcp = particle->getRelated<MCParticle>();
316 return std::numeric_limits<float>::quiet_NaN();
319 TLorentzVector boostvec = T.getBeamFourMomentum();
320 auto mcroe4vector = boostvec - mcp->get4Vector();
321 const auto& frame = ReferenceFrame::GetCurrent();
322 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
324 return frameMCRoe4Vector.Vect().Z();
327 double ROE_MC_Pt(
const Particle* particle)
329 const MCParticle* mcp = particle->getRelated<MCParticle>();
332 return std::numeric_limits<float>::quiet_NaN();
335 TLorentzVector boostvec = T.getBeamFourMomentum();
336 auto mcroe4vector = boostvec - mcp->get4Vector();
337 const auto& frame = ReferenceFrame::GetCurrent();
338 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
340 return frameMCRoe4Vector.Vect().Perp();
343 double ROE_MC_PTheta(
const Particle* particle)
345 const MCParticle* mcp = particle->getRelated<MCParticle>();
348 return std::numeric_limits<float>::quiet_NaN();
351 TLorentzVector boostvec = T.getBeamFourMomentum();
352 auto mcroe4vector = boostvec - mcp->get4Vector();
353 const auto& frame = ReferenceFrame::GetCurrent();
354 auto frameMCRoe4Vector = frame.getMomentum(mcroe4vector);
356 return frameMCRoe4Vector.Theta();
359 double ROE_MC_M(
const Particle* particle)
361 const MCParticle* mcp = particle->getRelated<MCParticle>();
364 return std::numeric_limits<float>::quiet_NaN();
367 TLorentzVector boostvec = T.getBeamFourMomentum();
369 return (boostvec - mcp->get4Vector()).Mag();
372 Manager::FunctionPtr ROE_MC_MissingFlags(
const std::vector<std::string>& arguments)
374 std::string maskName;
376 if (arguments.size() == 0)
378 else if (arguments.size() == 1)
379 maskName = arguments[0];
381 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROETracks");
383 auto func = [maskName](
const Particle * particle) ->
double {
385 StoreArray<Particle> particles;
388 const MCParticle* mcParticle = particle->getRelatedTo<MCParticle>();
391 return std::numeric_limits<float>::quiet_NaN();
394 const MCParticle* mcMother = mcParticle->getMother();
397 return std::numeric_limits<float>::quiet_NaN();
400 std::vector<MCParticle*> mcDaughters = mcMother->getDaughters();
402 if (mcDaughters.size() != 2)
403 return std::numeric_limits<float>::quiet_NaN();
406 MCParticle* mcROE =
nullptr;
407 if (mcDaughters[0]->getArrayIndex() == mcParticle->getArrayIndex())
408 mcROE = mcDaughters[1];
410 mcROE = mcDaughters[0];
413 const RestOfEvent* roe = getRelatedROEObject(particle);
415 std::set<const MCParticle*> mcROEObjects;
417 auto roeParticles = roe->getParticles(maskName);
418 for (
auto* roeParticle : roeParticles)
420 auto* mcroeParticle = roeParticle->getRelated<MCParticle>();
421 if (mcroeParticle !=
nullptr) {
422 mcROEObjects.insert(mcroeParticle);
426 checkMCParticleMissingFlags(mcROE, mcROEObjects, flags);
433 Manager::FunctionPtr nROE_Tracks(
const std::vector<std::string>& arguments)
435 std::string maskName;
437 if (arguments.size() == 0)
439 else if (arguments.size() == 1)
440 maskName = arguments[0];
442 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROETracks");
444 auto func = [maskName](
const Particle * particle) ->
double {
447 const RestOfEvent* roe = getRelatedROEObject(particle);
451 B2ERROR(
"Relation between particle and ROE doesn't exist!");
455 return roe->getNTracks(maskName);
460 Manager::FunctionPtr nROE_ECLClusters(
const std::vector<std::string>& arguments)
462 std::string maskName;
464 if (arguments.size() == 0)
466 else if (arguments.size() == 1)
467 maskName = arguments[0];
469 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROEECLClusters");
471 auto func = [maskName](
const Particle * particle) ->
double {
474 const RestOfEvent* roe = getRelatedROEObject(particle);
478 B2ERROR(
"Relation between particle and ROE doesn't exist!");
482 return roe->getNECLClusters(maskName);
487 Manager::FunctionPtr nROE_NeutralECLClusters(
const std::vector<std::string>& arguments)
489 std::string maskName;
491 if (arguments.size() == 0)
493 else if (arguments.size() == 1)
494 maskName = arguments[0];
496 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROENeutralECLClusters");
498 auto func = [maskName](
const Particle * particle) ->
double {
501 const RestOfEvent* roe = getRelatedROEObject(particle);
505 B2ERROR(
"Relation between particle and ROE doesn't exist!");
510 std::vector<const ECLCluster*> roeClusters = roe->getECLClusters(maskName);
514 for (
auto& roeCluster : roeClusters)
515 if (roeCluster->isNeutral())
523 Manager::FunctionPtr nROE_Photons(
const std::vector<std::string>& arguments)
525 std::string maskName =
"";
527 if (arguments.size() == 1) {
528 maskName = arguments[0];
530 if (arguments.size() > 1) {
531 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROE_Photons");
533 auto func = [maskName](
const Particle * particle) ->
double {
536 const RestOfEvent* roe = getRelatedROEObject(particle);
540 B2ERROR(
"Relation between particle and ROE doesn't exist!");
544 return roe->getPhotons(maskName).size();
549 Manager::FunctionPtr nROE_NeutralHadrons(
const std::vector<std::string>& arguments)
551 std::string maskName =
"";
553 if (arguments.size() == 1) {
554 maskName = arguments[0];
556 if (arguments.size() > 1) {
557 B2FATAL(
"Wrong number of arguments (1 optional only) for meta function nROE_NeutralHadrons");
559 auto func = [maskName](
const Particle * particle) ->
double {
562 const RestOfEvent* roe = getRelatedROEObject(particle);
566 B2ERROR(
"Relation between particle and ROE doesn't exist!");
570 return roe->getHadrons(maskName).size();
575 Manager::FunctionPtr nROE_ChargedParticles(
const std::vector<std::string>& arguments)
577 std::string maskName =
"";
579 if (arguments.size() == 1) {
580 maskName = arguments[0];
582 if (arguments.size() == 2) {
583 maskName = arguments[0];
585 pdgCode = std::stoi(arguments[1]);
586 }
catch (std::invalid_argument& e) {
587 B2ERROR(
"First argument of nROE_ChargedParticles must be a PDG code");
591 if (arguments.size() > 2) {
592 B2FATAL(
"Wrong number of arguments (2 optional) for meta function nROE_ChargedParticles");
594 auto func = [maskName, pdgCode](
const Particle * particle) ->
double {
597 const RestOfEvent* roe = getRelatedROEObject(particle);
601 B2ERROR(
"Relation between particle and ROE doesn't exist!");
605 return roe->getChargedParticles(maskName, abs(pdgCode)).size();
610 Manager::FunctionPtr nROE_ParticlesInList(
const std::vector<std::string>& arguments)
612 std::string pListName;
613 std::string maskName;
615 if (arguments.size() == 1) {
616 pListName = arguments[0];
618 }
else if (arguments.size() == 2) {
619 pListName = arguments[0];
620 maskName = arguments[1];
622 B2FATAL(
"Wrong number of arguments (1 required) for meta function nROE_ParticlesInList");
624 auto func = [pListName, maskName](
const Particle * particle) ->
double {
627 const RestOfEvent* roe = getRelatedROEObject(particle);
631 B2ERROR(
"Relation between particle and ROE doesn't exist!");
638 StoreObjPtr<ParticleList> pList(pListName);
639 if (!pList.isValid())
640 B2FATAL(
"ParticleList " << pListName <<
" could not be found or is not valid!");
642 for (
unsigned int i = 0; i < pList->getListSize(); i++)
644 const Particle* part = pList->getParticle(i);
645 if (isInThisRestOfEvent(part, roe, maskName))
654 Manager::FunctionPtr ROE_Charge(
const std::vector<std::string>& arguments)
656 std::string maskName;
658 if (arguments.size() == 0)
660 else if (arguments.size() == 1)
661 maskName = arguments[0];
663 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROECharge");
665 auto func = [maskName](
const Particle * particle) ->
double {
668 const RestOfEvent* roe = getRelatedROEObject(particle);
672 B2ERROR(
"Relation between particle and ROE doesn't exist!");
677 auto roeParticles = roe->getParticles(maskName);
680 for (
auto* roeParticle : roeParticles)
682 roeCharge += roeParticle->getCharge();
690 Manager::FunctionPtr ROE_ExtraEnergy(
const std::vector<std::string>& arguments)
692 std::string maskName;
694 if (arguments.size() == 0)
696 else if (arguments.size() == 1)
697 maskName = arguments[0];
699 B2FATAL(
"Wrong number of arguments (1 required) for meta function extraEnergy");
701 auto func = [maskName](
const Particle * particle) ->
double {
704 const RestOfEvent* roe = getRelatedROEObject(particle);
708 B2ERROR(
"Relation between particle and ROE doesn't exist!");
712 std::vector<const ECLCluster*> roeClusters = roe->getECLClusters(maskName);
715 for (
auto& roeCluster : roeClusters)
716 extraE += roeCluster->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons);
723 Manager::FunctionPtr ROE_NeutralExtraEnergy(
const std::vector<std::string>& arguments)
725 std::string maskName;
727 if (arguments.size() == 0)
729 else if (arguments.size() == 1)
730 maskName = arguments[0];
732 B2FATAL(
"Wrong number of arguments (1 required) for meta function extraEnergy");
734 auto func = [maskName](
const Particle * particle) ->
double {
737 const RestOfEvent* roe = getRelatedROEObject(particle);
741 B2ERROR(
"Relation between particle and ROE doesn't exist!");
744 auto roephotons = roe->getPhotons(maskName);
745 TLorentzVector total4vector;
746 for (
auto* photon : roephotons)
748 total4vector += photon->get4Vector();
750 const auto& frame = ReferenceFrame::GetCurrent();
751 auto frameRoe4Vector = frame.getMomentum(total4vector);
752 return frameRoe4Vector.Energy();
757 Manager::FunctionPtr ROE_E(
const std::vector<std::string>& arguments)
759 std::string maskName;
760 if (arguments.size() == 0)
762 else if (arguments.size() == 1)
763 maskName = arguments[0];
765 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_E");
766 auto func = [maskName](
const Particle * particle) ->
double {
767 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
770 B2ERROR(
"Relation between particle and ROE doesn't exist!");
773 const auto& frame = ReferenceFrame::GetCurrent();
774 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
775 return frameRoe4Vector.Energy();
780 Manager::FunctionPtr ROE_M(
const std::vector<std::string>& arguments)
782 std::string maskName;
784 if (arguments.size() == 0)
786 else if (arguments.size() == 1)
787 maskName = arguments[0];
789 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_M");
791 auto func = [maskName](
const Particle * particle) ->
double {
794 const RestOfEvent* roe = getRelatedROEObject(particle);
798 B2ERROR(
"Relation between particle and ROE doesn't exist!");
802 return roe->get4Vector(maskName).Mag();
807 Manager::FunctionPtr ROE_P(
const std::vector<std::string>& arguments)
809 std::string maskName;
811 if (arguments.size() == 0)
813 else if (arguments.size() == 1)
814 maskName = arguments[0];
816 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_P");
818 auto func = [maskName](
const Particle * particle) ->
double {
821 const RestOfEvent* roe = getRelatedROEObject(particle);
825 B2ERROR(
"Relation between particle and ROE doesn't exist!");
829 const auto& frame = ReferenceFrame::GetCurrent();
830 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
831 return frameRoe4Vector.Vect().Mag();
836 Manager::FunctionPtr ROE_Px(
const std::vector<std::string>& arguments)
838 std::string maskName;
840 if (arguments.size() == 0)
842 else if (arguments.size() == 1)
843 maskName = arguments[0];
845 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_Px");
847 auto func = [maskName](
const Particle * particle) ->
double {
850 const RestOfEvent* roe = getRelatedROEObject(particle);
854 B2ERROR(
"Relation between particle and ROE doesn't exist!");
858 const auto& frame = ReferenceFrame::GetCurrent();
859 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
860 return frameRoe4Vector.Vect().X();
865 Manager::FunctionPtr ROE_Py(
const std::vector<std::string>& arguments)
867 std::string maskName;
869 if (arguments.size() == 0)
871 else if (arguments.size() == 1)
872 maskName = arguments[0];
874 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_Py");
876 auto func = [maskName](
const Particle * particle) ->
double {
879 const RestOfEvent* roe = getRelatedROEObject(particle);
883 B2ERROR(
"Relation between particle and ROE doesn't exist!");
887 const auto& frame = ReferenceFrame::GetCurrent();
888 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
889 return frameRoe4Vector.Vect().Y();
894 Manager::FunctionPtr ROE_Pt(
const std::vector<std::string>& arguments)
896 std::string maskName;
898 if (arguments.size() == 0)
900 else if (arguments.size() == 1)
901 maskName = arguments[0];
903 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_Pt");
905 auto func = [maskName](
const Particle * particle) ->
double {
908 const RestOfEvent* roe = getRelatedROEObject(particle);
912 B2ERROR(
"Relation between particle and ROE doesn't exist!");
916 const auto& frame = ReferenceFrame::GetCurrent();
917 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
918 return frameRoe4Vector.Vect().Perp();
923 Manager::FunctionPtr ROE_Pz(
const std::vector<std::string>& arguments)
925 std::string maskName;
927 if (arguments.size() == 0)
929 else if (arguments.size() == 1)
930 maskName = arguments[0];
932 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_Pz");
934 auto func = [maskName](
const Particle * particle) ->
double {
937 const RestOfEvent* roe = getRelatedROEObject(particle);
941 B2ERROR(
"Relation between particle and ROE doesn't exist!");
945 const auto& frame = ReferenceFrame::GetCurrent();
946 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
947 return frameRoe4Vector.Vect().Z();
952 Manager::FunctionPtr ROE_PTheta(
const std::vector<std::string>& arguments)
954 std::string maskName;
956 if (arguments.size() == 0)
958 else if (arguments.size() == 1)
959 maskName = arguments[0];
961 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_PTheta");
963 auto func = [maskName](
const Particle * particle) ->
double {
966 const RestOfEvent* roe = getRelatedROEObject(particle);
970 B2ERROR(
"Relation between particle and ROE doesn't exist!");
974 const auto& frame = ReferenceFrame::GetCurrent();
975 auto frameRoe4Vector = frame.getMomentum(roe->get4Vector(maskName));
976 return frameRoe4Vector.Theta();
981 Manager::FunctionPtr ROE_DeltaE(
const std::vector<std::string>& arguments)
983 std::string maskName;
985 if (arguments.size() == 0)
987 else if (arguments.size() == 1)
988 maskName = arguments[0];
990 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_deltae");
992 auto func = [maskName](
const Particle * particle) ->
double {
995 const RestOfEvent* roe = getRelatedROEObject(particle);
999 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1004 TLorentzVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1005 return vec.E() - T.getCMSEnergy() / 2;
1010 Manager::FunctionPtr ROE_Mbc(
const std::vector<std::string>& arguments)
1012 std::string maskName;
1014 if (arguments.size() == 0)
1016 else if (arguments.size() == 1)
1017 maskName = arguments[0];
1019 B2FATAL(
"Wrong number of arguments (1 required) for meta function ROE_mbc");
1021 auto func = [maskName](
const Particle * particle) ->
double {
1024 const RestOfEvent* roe = getRelatedROEObject(particle);
1028 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1033 TLorentzVector vec = T.rotateLabToCms() * roe->get4Vector(maskName);
1035 double E = T.getCMSEnergy() / 2;
1036 double m2 = E * E - vec.Vect().Mag2();
1037 double mbc = m2 > 0 ? sqrt(m2) : 0;
1044 Manager::FunctionPtr bssMassDifference(
const std::vector<std::string>& arguments)
1046 std::string maskName;
1048 if (arguments.size() == 0)
1050 else if (arguments.size() == 1)
1051 maskName = arguments[0];
1053 B2FATAL(
"Wrong number of arguments (1 required) for meta function bssMassDifference");
1055 auto func = [maskName](
const Particle * particle) ->
double {
1058 TLorentzVector neutrino4vec = missing4Vector(particle->getDaughter(0), maskName,
"6");
1059 TLorentzVector sig4vec = particle->getDaughter(0)->get4Vector();
1061 TLorentzVector bsMom = neutrino4vec + sig4vec;
1062 TLorentzVector bssMom = bsMom + particle->getDaughter(1)->get4Vector();
1064 return bssMom.M() - bsMom.M();
1069 Manager::FunctionPtr WE_DeltaE(
const std::vector<std::string>& arguments)
1071 std::string maskName;
1074 if (arguments.size() == 1) {
1077 }
else if (arguments.size() == 2) {
1078 maskName = arguments[0];
1081 B2FATAL(
"Wrong number of arguments (2 required) for meta function correctedB_deltae");
1083 auto func = [maskName, opt](
const Particle * particle) ->
double {
1086 TLorentzVector boostvec = T.getBeamFourMomentum();
1087 TLorentzVector sig4vec = T.rotateLabToCms() * particle->get4Vector();
1088 TLorentzVector sig4vecLAB = particle->get4Vector();
1089 TLorentzVector neutrino4vec = missing4Vector(particle, maskName,
"1");
1090 TLorentzVector neutrino4vecLAB = missing4Vector(particle, maskName,
"6");
1092 double deltaE = std::numeric_limits<float>::quiet_NaN();
1097 double totalSigEnergy = (sig4vec + neutrino4vec).Energy();
1098 double E = T.getCMSEnergy() / 2;
1099 deltaE = totalSigEnergy - E;
1103 else if (opt ==
"1")
1105 double Ecms = T.getCMSEnergy();
1106 double s = Ecms * Ecms;
1107 deltaE = ((sig4vecLAB + neutrino4vecLAB) * boostvec - s / 2.0) / sqrt(s);
1111 B2FATAL(
"Option for correctedB_deltae variable should only be 0/1 (CMS/LAB)");
1118 Manager::FunctionPtr WE_Mbc(
const std::vector<std::string>& arguments)
1120 std::string maskName;
1123 if (arguments.size() == 1) {
1126 }
else if (arguments.size() == 2) {
1127 maskName = arguments[0];
1130 B2FATAL(
"Wrong number of arguments (2 required) for meta function correctedB_mbc");
1132 auto func = [maskName, opt](
const Particle * particle) ->
double {
1135 TLorentzVector boostvec = T.getBeamFourMomentum();
1136 TLorentzVector sig4vec = T.rotateLabToCms() * particle->get4Vector();
1137 TLorentzVector sig4vecLAB = particle->get4Vector();
1138 TLorentzVector neutrino4vec;
1140 double mbc = std::numeric_limits<float>::quiet_NaN();
1145 neutrino4vec = missing4Vector(particle, maskName,
"1");
1146 TVector3 bmom = (sig4vec + neutrino4vec).Vect();
1147 double E = T.getCMSEnergy() / 2;
1148 double m2 = E * E - bmom.Mag2();
1149 mbc = m2 > 0 ? sqrt(m2) : 0;
1153 else if (opt ==
"1")
1155 neutrino4vec = missing4Vector(particle, maskName,
"6");
1156 TVector3 bmom = (sig4vecLAB + neutrino4vec).Vect();
1157 double Ecms = T.getCMSEnergy();
1158 double s = Ecms * Ecms;
1159 double m2 = pow((s / 2.0 + bmom * boostvec.Vect()) / boostvec.Energy(), 2.0) - bmom.Mag2();
1160 mbc = m2 > 0 ? sqrt(m2) : 0;
1164 else if (opt ==
"2")
1166 neutrino4vec = missing4Vector(particle, maskName,
"7");
1167 TVector3 bmom = (sig4vec + neutrino4vec).Vect();
1168 double E = T.getCMSEnergy() / 2;
1169 double m2 = E * E - bmom.Mag2();
1170 mbc = m2 > 0 ? sqrt(m2) : 0;
1174 B2FATAL(
"Option for correctedB_mbc variable should only be 0/1/2 (CMS/LAB/CMS with factor)");
1181 Manager::FunctionPtr WE_MissM2(
const std::vector<std::string>& arguments)
1183 std::string maskName;
1186 if (arguments.size() == 1) {
1189 }
else if (arguments.size() == 2) {
1190 maskName = arguments[0];
1193 B2FATAL(
"Wrong number of arguments (2 required) for meta function missM2");
1195 auto func = [maskName, opt](
const Particle * particle) ->
double {
1197 return missing4Vector(particle, maskName, opt).Mag2();
1202 double REC_MissM2(
const Particle* particle)
1205 TLorentzVector rec4vecLAB = particle->get4Vector();
1206 TLorentzVector rec4vec = T.rotateLabToCms() * rec4vecLAB;
1208 TLorentzVector miss4vec;
1209 double E_beam_cms = T.getCMSEnergy() / 2.0;
1211 miss4vec.SetVect(-rec4vec.Vect());
1212 miss4vec.SetE(E_beam_cms - rec4vec.Energy());
1214 return miss4vec.Mag2();
1217 Manager::FunctionPtr WE_MissPTheta(
const std::vector<std::string>& arguments)
1219 std::string maskName;
1222 if (arguments.size() == 1) {
1225 }
else if (arguments.size() == 2) {
1226 maskName = arguments[0];
1229 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPTheta");
1231 auto func = [maskName, opt](
const Particle * particle) ->
double {
1234 const RestOfEvent* roe = getRelatedROEObject(particle);
1238 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1242 return missing4Vector(particle, maskName, opt).Theta();
1247 Manager::FunctionPtr WE_MissP(
const std::vector<std::string>& arguments)
1249 std::string maskName;
1252 if (arguments.size() == 1) {
1255 }
else if (arguments.size() == 2) {
1256 maskName = arguments[0];
1259 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissP");
1261 auto func = [maskName, opt](
const Particle * particle) ->
double {
1264 const RestOfEvent* roe = getRelatedROEObject(particle);
1268 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1272 return missing4Vector(particle, maskName, opt).Vect().Mag();
1277 Manager::FunctionPtr WE_MissPx(
const std::vector<std::string>& arguments)
1279 std::string maskName;
1282 if (arguments.size() == 1) {
1285 }
else if (arguments.size() == 2) {
1286 maskName = arguments[0];
1289 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPx");
1291 auto func = [maskName, opt](
const Particle * particle) ->
double {
1294 const RestOfEvent* roe = getRelatedROEObject(particle);
1298 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1302 return missing4Vector(particle, maskName, opt).Vect().Px();
1307 Manager::FunctionPtr WE_MissPy(
const std::vector<std::string>& arguments)
1309 std::string maskName;
1312 if (arguments.size() == 1) {
1315 }
else if (arguments.size() == 2) {
1316 maskName = arguments[0];
1319 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPy");
1321 auto func = [maskName, opt](
const Particle * particle) ->
double {
1324 const RestOfEvent* roe = getRelatedROEObject(particle);
1328 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1332 return missing4Vector(particle, maskName, opt).Vect().Py();
1337 Manager::FunctionPtr WE_MissPz(
const std::vector<std::string>& arguments)
1339 std::string maskName;
1342 if (arguments.size() == 1) {
1345 }
else if (arguments.size() == 2) {
1346 maskName = arguments[0];
1349 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissPz");
1351 auto func = [maskName, opt](
const Particle * particle) ->
double {
1354 const RestOfEvent* roe = getRelatedROEObject(particle);
1358 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1362 return missing4Vector(particle, maskName, opt).Vect().Pz();
1367 Manager::FunctionPtr WE_MissE(
const std::vector<std::string>& arguments)
1369 std::string maskName;
1372 if (arguments.size() == 1) {
1375 }
else if (arguments.size() == 2) {
1376 maskName = arguments[0];
1379 B2FATAL(
"Wrong number of arguments (2 required) for meta function WE_MissE");
1381 auto func = [maskName, opt](
const Particle * particle) ->
double {
1384 const RestOfEvent* roe = getRelatedROEObject(particle);
1388 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1392 return missing4Vector(particle, maskName, opt).Energy();
1397 Manager::FunctionPtr WE_xiZ(
const std::vector<std::string>& arguments)
1399 std::string maskName;
1401 if (arguments.size() == 0)
1403 else if (arguments.size() == 1)
1404 maskName = arguments[0];
1406 B2FATAL(
"Wrong number of arguments (1 required) for meta function xiZ");
1408 auto func = [maskName](
const Particle * particle) ->
double {
1411 const RestOfEvent* roe = getRelatedROEObject(particle);
1415 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1423 std::vector<const Particle*> recTrackParticles = particle->getFinalStateDaughters();
1426 for (
auto& recTrackParticle : recTrackParticles)
1428 pz += recTrackParticle->getPz();
1429 energy += recTrackParticle->getEnergy();
1433 pz += roe->get4VectorTracks(maskName).Vect().Pz();
1434 energy += roe->get4VectorTracks(maskName).Energy();
1441 Manager::FunctionPtr WE_MissM2OverMissE(
const std::vector<std::string>& arguments)
1443 std::string maskName;
1445 if (arguments.size() == 0)
1447 else if (arguments.size() == 1)
1448 maskName = arguments[0];
1450 B2FATAL(
"Wrong number of arguments (1 required) for meta function WE_MissM2OverMissE");
1452 auto func = [maskName](
const Particle * particle) ->
double {
1455 const RestOfEvent* roe = getRelatedROEObject(particle);
1459 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1464 TLorentzVector missing4Momentum;
1465 TLorentzVector boostvec = T.getBeamFourMomentum();
1467 return missing4Vector(particle, maskName,
"5").Mag2() / (2.0 * missing4Vector(particle, maskName,
"5").Energy());
1472 double REC_q2BhSimple(
const Particle* particle)
1479 TLorentzVector hadron4vec;
1481 int n = particle->getNDaughters();
1484 return std::numeric_limits<float>::quiet_NaN();
1487 for (
unsigned i = 0; i < particle->getNDaughters(); i++) {
1488 int absPDG = abs(particle->getDaughter(i)->getPDGCode());
1489 if (absPDG == 11 || absPDG == 13 || absPDG == 15)
1492 hadron4vec += particle->getDaughter(i)->get4Vector();
1497 TLorentzVector phCMS = T.rotateLabToCms() * hadron4vec;
1498 TLorentzVector pBCMS;
1499 pBCMS.SetXYZM(0.0, 0.0, 0.0, particle->getPDGMass());
1501 return (pBCMS - phCMS).Mag2();
1504 double REC_q2Bh(
const Particle* particle)
1511 TLorentzVector hadron4vec;
1513 int n = particle->getNDaughters();
1516 return std::numeric_limits<float>::quiet_NaN();
1518 for (
unsigned i = 0; i < particle->getNDaughters(); i++) {
1519 int absPDG = abs(particle->getDaughter(i)->getPDGCode());
1520 if (absPDG == 11 || absPDG == 13 || absPDG == 15)
1523 hadron4vec += particle->getDaughter(i)->get4Vector();
1528 TLorentzVector had_cm = T.rotateLabToCms() * hadron4vec;
1529 TLorentzVector Y_cm = T.rotateLabToCms() * particle->get4Vector();
1533 double bmass = particle->getPDGMass();
1536 double cos_cone_angle = Variable::cosThetaBetweenParticleAndNominalB(particle);
1538 if (abs(cos_cone_angle) > 1) {
1540 return Variable::REC_q2BhSimple(particle);
1543 double thetaBY = TMath::ACos(cos_cone_angle);
1544 const double E_B = T.getCMSEnergy() / 2.0;
1545 const double p_B = sqrt(E_B * E_B - bmass * bmass);
1547 double phi_start = gRandom->Uniform(0, TMath::Pi() / 2);
1552 for (
int around_the_cone = 0; around_the_cone < 4; around_the_cone++) {
1553 TLorentzVector one_B(1, 1, 1, E_B);
1554 double B_theta = Y_cm.Theta() + thetaBY * cos(phi_start + around_the_cone / 2.*TMath::Pi());
1555 double B_phi = Y_cm.Phi() + thetaBY * sin(phi_start + around_the_cone / 2.*TMath::Pi());
1556 one_B.SetTheta(B_theta);
1557 one_B.SetPhi(B_phi);
1560 double this_q2 = (one_B - had_cm).Mag2();
1561 q2 += this_q2 * sin(B_theta) * sin(B_theta);
1562 denom += sin(B_theta) * sin(B_theta);
1570 Manager::FunctionPtr WE_q2lnuSimple(
const std::vector<std::string>& arguments)
1572 std::string maskName(
"");
1573 std::string option(
"1");
1575 if (arguments.size() == 1) {
1576 maskName = arguments[0];
1577 }
else if (arguments.size() == 2) {
1578 maskName = arguments[0];
1579 option = arguments[1];
1580 }
else if (arguments.size() > 2) {
1581 B2FATAL(
"Too many arguments. At most two arguments are allowed for meta function q2lnuSimple(maskname,option)");
1584 auto func = [maskName, option](
const Particle * particle) ->
double {
1587 const RestOfEvent* roe = getRelatedROEObject(particle);
1591 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1595 int n = particle->getNDaughters();
1598 return std::numeric_limits<float>::quiet_NaN();
1602 const Particle* lep = particle->getDaughter(n - 1);
1603 TLorentzVector lep4vec = T.rotateLabToCms() * lep->get4Vector();
1604 TLorentzVector nu4vec = missing4Vector(particle, maskName, option);
1606 return (lep4vec + nu4vec).Mag2();
1611 Manager::FunctionPtr WE_q2lnu(
const std::vector<std::string>& arguments)
1613 std::string maskName(
"");
1614 std::string option(
"7");
1616 if (arguments.size() == 1) {
1617 maskName = arguments[0];
1618 }
else if (arguments.size() == 2) {
1619 maskName = arguments[0];
1620 option = arguments[1];
1621 }
else if (arguments.size() > 2) {
1622 B2FATAL(
"Too many arguments. At most two arguments are allowed for meta function q2lnu(maskname, option)");
1625 auto func = [maskName, option](
const Particle * particle) ->
double {
1628 const RestOfEvent* roe = getRelatedROEObject(particle);
1632 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1636 int n = particle->getNDaughters();
1639 return std::numeric_limits<float>::quiet_NaN();
1642 const Particle* lep = particle->getDaughter(n - 1);
1643 TLorentzVector lep_cm = T.rotateLabToCms() * lep->get4Vector();
1645 TLorentzVector Y_cm = T.rotateLabToCms() * particle->get4Vector();
1646 TLorentzVector neu_cm = missing4Vector(particle, maskName, option);
1649 double e_beam = T.getCMSEnergy() / 2.0;
1652 double bmass = particle->getPDGMass();
1653 double pB2 = e_beam * e_beam - bmass * bmass;
1656 double cos_angle_nu = (pB2 - Y_cm.Vect().Mag2() - neu_cm.Vect().Mag2()) / (2.0 * Y_cm.Vect().Mag() * neu_cm.Vect().Mag());
1657 if (abs(cos_angle_nu) > 1)
1659 return (lep_cm + neu_cm).Mag2();
1662 double angle_nu = TMath::ACos(cos_angle_nu);
1664 TLorentzVector rotated_neu(-1 * Y_cm.Vect(), Y_cm.E());
1666 double nu_theta = rotated_neu.Theta() + (TMath::Pi() - angle_nu);
1667 double nu_phi = rotated_neu.Phi();
1668 rotated_neu.SetTheta(nu_theta);
1669 rotated_neu.SetPhi(nu_phi);
1670 rotated_neu.SetRho(neu_cm.Rho());
1671 rotated_neu.SetE(neu_cm.E());
1673 TVector3 Yneu_norm = Y_cm.Vect().Cross(neu_cm.Vect());
1674 TVector3 Yrot_norm = Y_cm.Vect().Cross(rotated_neu.Vect());
1678 double rot_angle = Yneu_norm.Angle(Yrot_norm);
1680 TLorentzVector rotated_neu2(rotated_neu);
1686 rotated_neu.Rotate(rot_angle, Y_cm.Vect());
1687 rotated_neu2.Rotate(-rot_angle, Y_cm.Vect());
1689 double dot1 = rotated_neu.Vect().Dot(Yneu_norm);
1690 double dot2 = rotated_neu2.Vect().Dot(Yneu_norm);
1692 if (abs(dot2) < abs(dot1)) rotated_neu = rotated_neu2;
1694 return (lep_cm + rotated_neu).Mag2();
1699 Manager::FunctionPtr WE_cosThetaEll(
const std::vector<std::string>& arguments)
1701 std::string maskName;
1703 if (arguments.size() == 0)
1705 else if (arguments.size() == 1)
1706 maskName = arguments[0];
1708 B2FATAL(
"Wrong number of arguments (1 required) for meta function cosThetaEll");
1710 auto func = [maskName](
const Particle * particle) ->
double {
1713 TLorentzVector boostvec = T.getBeamFourMomentum();
1714 TLorentzVector pNu = missing4Vector(particle, maskName,
"6");
1716 TLorentzVector pLep;
1718 for (
unsigned i = 0; i < particle->getNDaughters(); i++)
1720 int absPDG = abs(particle->getDaughter(i)->getPDGCode());
1721 if (absPDG == 11 || absPDG == 13 || absPDG == 15) {
1722 pLep = particle->getDaughter(i)->get4Vector();
1727 TLorentzVector pW = pNu + pLep;
1728 TLorentzVector pB = particle->get4Vector() + pNu;
1731 TVector3 boost2W = -(pW.BoostVector());
1732 pLep.Boost(boost2W);
1735 TVector3 lep3Vector = pLep.Vect();
1736 TVector3 B3Vector = pB.Vect();
1737 double numerator = lep3Vector.Dot(B3Vector);
1738 double denominator = (lep3Vector.Mag()) * (B3Vector.Mag());
1740 return numerator / denominator;
1745 Manager::FunctionPtr passesROEMask(
const std::vector<std::string>& arguments)
1747 std::string maskName;
1749 if (arguments.size() == 0)
1751 else if (arguments.size() == 1)
1752 maskName = arguments[0];
1754 B2FATAL(
"Wrong number of arguments (1 required) for meta function passesROEMask");
1756 auto func = [maskName](
const Particle * particle) ->
double {
1760 StoreObjPtr<RestOfEvent> roe(
"RestOfEvent");
1761 if (not roe.isValid())
1766 if (roe->hasParticle(particle, maskName))
1776 double printROE(
const Particle* particle)
1778 const RestOfEvent* roe = getRelatedROEObject(particle);
1781 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1782 }
else roe->print();
1787 Manager::FunctionPtr pi0Prob(
const std::vector<std::string>& arguments)
1789 if (arguments.size() != 1)
1790 B2ERROR(
"Wrong number of arguments (1 required) for pi0Prob");
1793 mode = arguments[0];
1795 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1796 B2ERROR(
"the given argument is not supported in pi0Prob!");
1798 auto func = [mode](
const Particle * particle) ->
double {
1799 if (mode ==
"standard")
1801 if (particle->hasExtraInfo(
"Pi0ProbOrigin")) {
1802 return particle->getExtraInfo(
"Pi0ProbOrigin");
1804 B2WARNING(
"Pi0ProbOrigin is not registerted in extraInfo! \n"
1805 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1806 return std::numeric_limits<float>::quiet_NaN();
1810 else if (mode ==
"tight")
1812 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThreshold")) {
1813 return particle->getExtraInfo(
"Pi0ProbTightEnergyThreshold");
1815 B2WARNING(
"Pi0ProbTightEnergyThreshold is not registerted in extraInfo! \n"
1816 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1817 return std::numeric_limits<float>::quiet_NaN();
1821 else if (mode ==
"cluster")
1823 if (particle->hasExtraInfo(
"Pi0ProbLargeClusterSize")) {
1824 return particle->getExtraInfo(
"Pi0ProbLargeClusterSize");
1826 B2WARNING(
"Pi0ProbLargeClusterSize is not registerted in extraInfo! \n"
1827 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1828 return std::numeric_limits<float>::quiet_NaN();
1832 else if (mode ==
"both")
1834 if (particle->hasExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize")) {
1835 return particle->getExtraInfo(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize");
1837 B2WARNING(
"Pi0ProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1838 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1839 return std::numeric_limits<float>::quiet_NaN();
1845 return std::numeric_limits<float>::quiet_NaN();
1851 Manager::FunctionPtr etaProb(
const std::vector<std::string>& arguments)
1853 if (arguments.size() != 1)
1854 B2ERROR(
"Wrong number of arguments (1 required) for etaProb");
1857 mode = arguments[0];
1859 if (mode !=
"standard" and mode !=
"tight" and mode !=
"cluster" and mode !=
"both")
1860 B2ERROR(
"the given argument is not supported in etaProb!");
1862 auto func = [mode](
const Particle * particle) ->
double {
1863 if (mode ==
"standard")
1865 if (particle->hasExtraInfo(
"EtaProbOrigin")) {
1866 return particle->getExtraInfo(
"EtaProbOrigin");
1868 B2WARNING(
"EtaProbOrigin is not registerted in extraInfo! \n"
1869 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1870 return std::numeric_limits<float>::quiet_NaN();
1874 else if (mode ==
"tight")
1876 if (particle->hasExtraInfo(
"EtaProbTightEnergyThreshold")) {
1877 return particle->getExtraInfo(
"EtaProbTightEnergyThreshold");
1879 B2WARNING(
"EtaProbTightEnergyThreshold is not registerted in extraInfo! \n"
1880 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1881 return std::numeric_limits<float>::quiet_NaN();
1885 else if (mode ==
"cluster")
1887 if (particle->hasExtraInfo(
"EtaProbLargeClusterSize")) {
1888 return particle->getExtraInfo(
"EtaProbLargeClusterSize");
1890 B2WARNING(
"EtaProbLargeClusterSize is not registerted in extraInfo! \n"
1891 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1892 return std::numeric_limits<float>::quiet_NaN();
1896 else if (mode ==
"both")
1898 if (particle->hasExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize")) {
1899 return particle->getExtraInfo(
"EtaProbTightEnergyThresholdAndLargeClusterSize");
1901 B2WARNING(
"EtaProbTightEnergyThresholdAndLargeClusterSize is not registerted in extraInfo! \n"
1902 "the function writePi0EtaVeto has to be executed to register this extraInfo.");
1903 return std::numeric_limits<float>::quiet_NaN();
1909 return std::numeric_limits<float>::quiet_NaN();
1919 TLorentzVector missing4Vector(
const Particle* particle,
const std::string& maskName,
const std::string& opt)
1922 const RestOfEvent* roe = getRelatedROEObject(particle);
1925 B2ERROR(
"Relation between particle and ROE doesn't exist!");
1926 TLorentzVector empty;
1931 TLorentzVector boostvec = T.getBeamFourMomentum();
1933 TLorentzVector rec4vecLAB = particle->get4Vector();
1934 TLorentzVector roe4vecLAB = roe->get4Vector(maskName);
1936 TLorentzVector rec4vec = T.rotateLabToCms() * rec4vecLAB;
1937 TLorentzVector roe4vec = T.rotateLabToCms() * roe4vecLAB;
1939 TLorentzVector miss4vec;
1940 double E_beam_cms = T.getCMSEnergy() / 2.0;
1944 miss4vec.SetVect(- (rec4vec.Vect() + roe4vec.Vect()));
1945 miss4vec.SetE(2 * E_beam_cms - (rec4vec.E() + roe4vec.E()));
1949 else if (opt ==
"1") {
1950 miss4vec.SetVect(- (rec4vec.Vect() + roe4vec.Vect()));
1951 miss4vec.SetE(miss4vec.Vect().Mag());
1955 else if (opt ==
"2") {
1956 miss4vec.SetVect(- (rec4vec.Vect() + roe4vec.Vect()));
1957 miss4vec.SetE(E_beam_cms - rec4vec.E());
1961 else if (opt ==
"3") {
1962 miss4vec.SetVect(- rec4vec.Vect());
1963 miss4vec.SetE(E_beam_cms - rec4vec.E());
1967 else if (opt ==
"4") {
1968 TVector3 pB = - roe4vec.Vect();
1970 miss4vec.SetVect(pB - rec4vec.Vect());
1971 miss4vec.SetE(E_beam_cms - rec4vec.E());
1975 else if (opt ==
"5") {
1976 miss4vec.SetVect(boostvec.Vect() - (rec4vecLAB.Vect() + roe4vecLAB.Vect()));
1977 miss4vec.SetE(boostvec.E() - (rec4vecLAB.E() + roe4vecLAB.E()));
1981 else if (opt ==
"6") {
1982 miss4vec.SetVect(boostvec.Vect() - (rec4vecLAB.Vect() + roe4vecLAB.Vect()));
1983 miss4vec.SetE(miss4vec.Vect().Mag());
1987 else if (opt ==
"7") {
1988 miss4vec.SetVect(-(rec4vec.Vect() + roe4vec.Vect()));
1989 miss4vec.SetE(miss4vec.Vect().Mag());
1990 double factorAlpha = (E_beam_cms - rec4vec.E()) / miss4vec.E();
1991 miss4vec.SetRho(factorAlpha * miss4vec.Rho());
1992 miss4vec.SetE(miss4vec.Rho());
1998 void checkMCParticleMissingFlags(
const MCParticle* mcp, std::set<const MCParticle*> mcROEObjects,
int& missingFlags)
2000 std::vector<MCParticle*> daughters = mcp->getDaughters();
2001 for (
auto& daughter : daughters) {
2003 if (!daughter->hasStatus(MCParticle::c_PrimaryParticle))
2006 if (mcROEObjects.find(daughter) == mcROEObjects.end()) {
2008 int pdg = abs(daughter->getPDG());
2011 if (pdg == Const::photon.getPDGCode() and (missingFlags & 1) == 0)
2015 else if (pdg == Const::electron.getPDGCode() and (missingFlags & 2) == 0)
2019 else if (pdg == Const::muon.getPDGCode() and (missingFlags & 4) == 0)
2023 else if (pdg == Const::pion.getPDGCode() and (missingFlags & 8) == 0)
2027 else if (pdg == Const::kaon.getPDGCode() and (missingFlags & 16) == 0)
2031 else if (pdg == Const::proton.getPDGCode() and (missingFlags & 32) == 0)
2035 else if (pdg == Const::neutron.getPDGCode() and (missingFlags & 64) == 0)
2039 else if (pdg == Const::Kshort.getPDGCode() and ((missingFlags & 128) == 0 or (missingFlags & 256) == 0)) {
2040 std::vector<MCParticle*> ksDaug = daughter->getDaughters();
2041 if (ksDaug.size() == 2) {
2043 if (abs(ksDaug[0]->getPDG()) == Const::pion.getPDGCode() and abs(ksDaug[1]->getPDG()) == Const::pion.getPDGCode()
2044 and (missingFlags & 128) == 0) {
2045 if (mcROEObjects.find(ksDaug[0]) == mcROEObjects.end() or mcROEObjects.find(ksDaug[1]) == mcROEObjects.end())
2046 missingFlags += 128;
2049 else if (abs(ksDaug[0]->getPDG()) == Const::pi0.getPDGCode() and abs(ksDaug[1]->getPDG()) == Const::pi0.getPDGCode()
2050 and (missingFlags & 256) == 0) {
2051 std::vector<MCParticle*> pi0Daug0 = ksDaug[0]->getDaughters();
2052 std::vector<MCParticle*> pi0Daug1 = ksDaug[1]->getDaughters();
2053 if (mcROEObjects.find(pi0Daug0[0]) == mcROEObjects.end() or
2054 mcROEObjects.find(pi0Daug0[1]) == mcROEObjects.end() or
2055 mcROEObjects.find(pi0Daug1[0]) == mcROEObjects.end() or
2056 mcROEObjects.find(pi0Daug1[1]) == mcROEObjects.end())
2057 missingFlags += 256;
2063 else if (pdg == Const::Klong.getPDGCode() and (missingFlags & 512) == 0)
2064 missingFlags += 512;
2067 else if ((pdg == 12 or pdg == 14 or pdg == 16) and (missingFlags & 1024) == 0)
2068 missingFlags += 1024;
2070 checkMCParticleMissingFlags(daughter, mcROEObjects, missingFlags);
2074 double isInThisRestOfEvent(
const Particle* particle,
const RestOfEvent* roe,
const std::string& maskName)
2076 if (particle->getParticleSource() == Particle::c_Composite or
2077 particle->getParticleSource() == Particle::c_V0) {
2078 std::vector<const Particle*> fspDaug = particle->getFinalStateDaughters();
2079 for (
auto& i : fspDaug) {
2080 if (isInThisRestOfEvent(i, roe, maskName) == 0)
2085 return roe->hasParticle(particle, maskName);
2088 const RestOfEvent* getRelatedROEObject(
const Particle* particle,
bool returnHostOnly)
2091 const RestOfEvent* roe = particle->getRelatedTo<RestOfEvent>();
2092 if (!roe && !returnHostOnly) {
2093 roe = particle->getRelatedTo<RestOfEvent>(
"NestedRestOfEvents");
2099 VARIABLE_GROUP(
"Rest Of Event");
2101 REGISTER_VARIABLE(
"useROERecoilFrame(variable)", useROERecoilFrame,
2102 "Returns the value of the variable using the rest frame of the ROE recoil as current reference frame.\n"
2103 "Can be used inside for_each loop or outside of it if the particle has associated Rest of Event.\n"
2104 "E.g. ``useROERecoilFrame(E)`` returns the energy of a particle in the ROE recoil frame.");
2106 REGISTER_VARIABLE(
"isInRestOfEvent", isInRestOfEvent,
2107 "Returns 1 if a track, ecl or klmCluster associated to particle is in the current RestOfEvent object, 0 otherwise."
2108 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2110 REGISTER_VARIABLE(
"isCloneOfSignalSide", isCloneOfSignalSide,
2111 "Returns 1 if a particle is a clone of signal side final state particles, 0 otherwise. "
2112 "Requires generator information and truth-matching. "
2113 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2115 REGISTER_VARIABLE(
"hasAncestorFromSignalSide", hasAncestorFromSignalSide,
2116 "Returns 1 if a particle has ancestor from signal side, 0 otherwise. "
2117 "Requires generator information and truth-matching. "
2118 "One can use this variable only in a ``for_each`` loop over the RestOfEvent StoreArray.");
2120 REGISTER_VARIABLE(
"currentROEIsInList(particleList)", currentROEIsInList,
2121 "[Eventbased] Returns 1 the associated particle of the current ROE is contained in the given list or its charge-conjugated."
2122 "Useful to restrict the for_each loop over ROEs to ROEs of a certain ParticleList.");
2124 REGISTER_VARIABLE(
"nROE_RemainingTracks", nROE_RemainingTracks,
2125 "Returns number of tracks in ROE - number of tracks of given particle"
2126 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2128 REGISTER_VARIABLE(
"nROE_RemainingTracks(maskName)", nROE_RemainingTracksWithMask,
2129 "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."
2130 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray."
2131 "Is required for the specific FEI. :noindex:");
2136 REGISTER_VARIABLE(
"nROE_KLMClusters", nROE_KLMClusters,
2137 "Returns number of all remaining KLM clusters in the related RestOfEvent object.");
2139 REGISTER_VARIABLE(
"nROE_Charged(maskName, PDGcode = 0)", nROE_ChargedParticles,
2140 "Returns number of all charged particles in the related RestOfEvent object. First optional argument is ROE mask name. "
2141 "Second argument is a PDG code to count only one charged particle species, independently of charge. "
2142 "For example: ``nROE_Charged(cleanMask, 321)`` will output number of kaons in Rest Of Event with ``cleanMask``. "
2143 "PDG code 0 is used to count all charged particles");
2145 REGISTER_VARIABLE(
"nROE_Photons(maskName)", nROE_Photons,
2146 "Returns number of all photons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ");
2148 REGISTER_VARIABLE(
"nROE_NeutralHadrons(maskName)", nROE_NeutralHadrons,
2149 "Returns number of all neutral hadrons in the related RestOfEvent object, accepts 1 optional argument of ROE mask name. ");
2151 REGISTER_VARIABLE(
"particleRelatedToCurrentROE(var)", particleRelatedToCurrentROE,
2152 "[Eventbased] Returns variable applied to the particle which is related to the current RestOfEvent object"
2153 "One can use this variable only in a for_each loop over the RestOfEvent StoreArray.");
2155 REGISTER_VARIABLE(
"roeMC_E", ROE_MC_E,
2156 "Returns true energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2158 REGISTER_VARIABLE(
"roeMC_M", ROE_MC_M,
2159 "Returns true invariant mass of unused tracks and clusters in ROE");
2161 REGISTER_VARIABLE(
"roeMC_P", ROE_MC_P,
2162 "Returns true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2164 REGISTER_VARIABLE(
"roeMC_Px", ROE_MC_Px,
2165 "Returns x component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2167 REGISTER_VARIABLE(
"roeMC_Py", ROE_MC_Py,
2168 "Returns y component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2170 REGISTER_VARIABLE(
"roeMC_Pz", ROE_MC_Pz,
2171 "Returns z component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2173 REGISTER_VARIABLE(
"roeMC_Pt", ROE_MC_Pt,
2174 "Returns transverse component of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2176 REGISTER_VARIABLE(
"roeMC_PTheta", ROE_MC_PTheta,
2177 "Returns polar angle of true momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2179 REGISTER_VARIABLE(
"roeMC_MissFlags(maskName)", ROE_MC_MissingFlags,
2180 "Returns flags corresponding to missing particles on ROE side.");
2182 REGISTER_VARIABLE(
"nROE_Tracks(maskName)", nROE_Tracks,
2183 "Returns number of tracks in the related RestOfEvent object that pass the selection criteria.");
2185 REGISTER_VARIABLE(
"nROE_ECLClusters(maskName)", nROE_ECLClusters,
2186 "Returns number of ECL clusters in the related RestOfEvent object that pass the selection criteria.");
2188 REGISTER_VARIABLE(
"nROE_NeutralECLClusters(maskName)", nROE_NeutralECLClusters,
2189 "Returns number of neutral ECL clusters in the related RestOfEvent object that pass the selection criteria.");
2191 REGISTER_VARIABLE(
"nROE_ParticlesInList(pListName)", nROE_ParticlesInList,
2192 "Returns the number of particles in ROE from the given particle list.\n"
2193 "Use of variable aliases is advised.");
2195 REGISTER_VARIABLE(
"roeCharge(maskName)", ROE_Charge,
2196 "Returns total charge of the related RestOfEvent object.");
2198 REGISTER_VARIABLE(
"roeEextra(maskName)", ROE_ExtraEnergy,
2199 "Returns extra energy from ECLClusters in the calorimeter that is not associated to the given Particle");
2201 REGISTER_VARIABLE(
"roeNeextra(maskName)", ROE_NeutralExtraEnergy,
2202 "Returns extra energy from neutral ECLClusters in the calorimeter that is not associated to the given Particle, can be used with ``use***Frame()`` function.");
2204 REGISTER_VARIABLE(
"roeE(maskName)", ROE_E,
2205 "Returns energy of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2207 REGISTER_VARIABLE(
"roeM(maskName)", ROE_M,
2208 "Returns invariant mass of unused tracks and clusters in ROE");
2210 REGISTER_VARIABLE(
"roeP(maskName)", ROE_P,
2211 "Returns momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2213 REGISTER_VARIABLE(
"roePt(maskName)", ROE_Pt,
2214 "Returns transverse component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2216 REGISTER_VARIABLE(
"roePx(maskName)", ROE_Px,
2217 "Returns x component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2219 REGISTER_VARIABLE(
"roePy(maskName)", ROE_Py,
2220 "Returns y component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2222 REGISTER_VARIABLE(
"roePz(maskName)", ROE_Pz,
2223 "Returns z component of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2225 REGISTER_VARIABLE(
"roePTheta(maskName)", ROE_PTheta,
2226 "Returns theta angle of momentum of unused tracks and clusters in ROE, can be used with ``use***Frame()`` function.");
2228 REGISTER_VARIABLE(
"roeDeltae(maskName)", ROE_DeltaE,
2229 "Returns energy difference of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`.");
2231 REGISTER_VARIABLE(
"roeMbc(maskName)", ROE_Mbc,
2232 "Returns beam constrained mass of the related RestOfEvent object with respect to :math:`E_\\mathrm{cms}/2`.");
2234 REGISTER_VARIABLE(
"weDeltae(maskName, opt)", WE_DeltaE,
2235 "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`.");
2237 REGISTER_VARIABLE(
"weMbc(maskName, opt)", WE_Mbc,
2238 "Returns beam constrained mass of B meson, corrected with the missing neutrino momentum (reconstructed side + neutrino) with respect to :math:`E_\\mathrm{cms}/2`.");
2240 REGISTER_VARIABLE(
"weMissM2(maskName, opt)", WE_MissM2,
2241 "Returns the invariant mass squared of the missing momentum (see :b2:var:`weMissE` possible options)");
2243 REGISTER_VARIABLE(
"recMissM2", REC_MissM2,
2244 "Returns the invariant mass squared of the missing momentum calculated assumings the"
2245 "reco B is at rest and calculating the neutrino (missing) momentum from :math:`p_\\nu = p_B - p_\\mathrm{had} - p_\\mathrm{lep}`");
2247 REGISTER_VARIABLE(
"weMissPTheta(maskName, opt)", WE_MissPTheta,
2248 "Returns the polar angle of the missing momentum (see possible :b2:var:`weMissE` options)");
2250 REGISTER_VARIABLE(
"weMissP(maskName, opt)", WE_MissP,
2251 "Returns the magnitude of the missing momentum (see possible :b2:var:`weMissE` options)");
2253 REGISTER_VARIABLE(
"weMissPx(maskName, opt)", WE_MissPx,
2254 "Returns the x component of the missing momentum (see :b2:var:`weMissE` possible options)");
2256 REGISTER_VARIABLE(
"weMissPy(maskName, opt)", WE_MissPy,
2257 "Returns the y component of the missing momentum (see :b2:var:`weMissE` possible options)");
2259 REGISTER_VARIABLE(
"weMissPz(maskName, opt)", WE_MissPz,
2260 "Returns the z component of the missing momentum (see :b2:var:`weMissE` possible options)");
2262 REGISTER_VARIABLE(
"weMissE(maskName, opt)", WE_MissE,
2263 R
"DOC(Returns the energy of the missing momentum, possible options ``opt`` are the following:
2265 - ``0``: CMS, use energy and momentum of charged particles and photons
2266 - ``1``: CMS, same as ``0``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}`
2267 - ``2``: CMS, same as ``0``, fix :math:`E_\mathrm{roe} = E_\mathrm{cms}/2`
2268 - ``3``: CMS, use only energy and momentum of signal side
2269 - ``4``: CMS, same as ``3``, update with direction of ROE momentum
2270 - ``5``: LAB, use energy and momentum of charged particles and photons from whole event
2271 - ``6``: LAB, same as ``5``, fix :math:`E_\mathrm{miss} = p_\mathrm{miss}``
2272 - ``7``: CMS, correct pmiss 3-momentum vector with factor alpha so that :math:`d_E = 0`` (used for :math:`M_\mathrm{bc}` calculation).)DOC");
2274 REGISTER_VARIABLE("weXiZ(maskName)", WE_xiZ,
2275 "Returns Xi_z in event (for Bhabha suppression and two-photon scattering)");
2277 REGISTER_VARIABLE(
"bssMassDifference(maskName)", bssMassDifference,
2278 "Bs* - Bs mass difference");
2280 REGISTER_VARIABLE(
"weCosThetaEll(maskName)", WE_cosThetaEll, R
"DOC(
2282 Returns the angle between :math:`M` and lepton in :math:`W` rest frame in the decays of the type:
2283 :math:`M \to h_1 ... h_n \ell`, where W 4-momentum is given as
2286 p_W = p_\ell + p_\nu.
2288 The neutrino momentum is calculated from ROE taking into account the specified mask, and setting
2291 E_{\nu} = |p_{miss}|.
2295 REGISTER_VARIABLE("recQ2BhSimple", REC_q2BhSimple,
2296 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_B - p_h)^2`, \n"
2297 "where p_h is the CMS momentum of all hadrons in the decay :math:`B \\to H_1 ... H_n \\ell \\nu_\\ell`.\n"
2298 "The B meson momentum in CMS is assumed to be 0.");
2300 REGISTER_VARIABLE(
"recQ2Bh", REC_q2Bh,
2301 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_B - p_h)^2`, \n"
2302 "where p_h is the CMS momentum of all hadrons in the decay :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`.\n"
2303 "This calculation uses a weighted average of the B meson around the reco B cone");
2305 REGISTER_VARIABLE(
"weQ2lnuSimple(maskName,option)", WE_q2lnuSimple,
2306 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2307 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2308 "By default, option is set to ``1`` (see :b2:var:`weMissE`). Unless you know what you are doing, keep this default value.");
2310 REGISTER_VARIABLE(
"weQ2lnu(maskName,option)", WE_q2lnu,
2311 "Returns the momentum transfer squared, :math:`q^2`, calculated in CMS as :math:`q^2 = (p_l + p_\\nu)^2`, \n"
2312 "where :math:`B \\to H_1\\dots H_n \\ell \\nu_\\ell`. Lepton is assumed to be the last reconstructed daughter. \n"
2313 "This calculation uses constraints from dE = 0 and Mbc = Mb to correct the neutrino direction. \n"
2314 "By default, option is set to ``7`` (see :b2:var:`weMissE`). Unless you know what you are doing, keep this default value.");
2316 REGISTER_VARIABLE(
"weMissM2OverMissE(maskName)", WE_MissM2OverMissE,
2317 "Returns missing mass squared over missing energy");
2319 REGISTER_VARIABLE(
"passesROEMask(maskName)", passesROEMask,
2320 "Returns boolean value if track or eclCluster type particle passes a certain mask or not. Only to be used in for_each path");
2322 REGISTER_VARIABLE(
"printROE", printROE,
2323 "For debugging, prints indices of all particles in the ROE and all masks. Returns 0.");
2325 REGISTER_VARIABLE(
"pi0Prob(mode)", pi0Prob,
2326 "Returns pi0 probability, where mode is used to specify the selection criteria for soft photon. \n"
2327 "The following strings are available. \n\n"
2328 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2329 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2330 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2331 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2332 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.");
2334 REGISTER_VARIABLE(
"etaProb(mode)", etaProb,
2335 "Returns eta probability, where mode is used to specify the selection criteria for soft photon. \n"
2336 "The following strings are available. \n\n"
2337 "- ``standard``: loose energy cut and no clusterNHits cut are applied to soft photon \n"
2338 "- ``tight``: tight energy cut and no clusterNHits cut are applied to soft photon \n"
2339 "- ``cluster``: loose energy cut and clusterNHits cut are applied to soft photon \n"
2340 "- ``both``: tight energy cut and clusterNHits cut are applied to soft photon \n\n"
2341 "You can find more details in `writePi0EtaVeto` function in modularAnalysis.py.");