10 #include <analysis/modules/KlongDecayReconstructor/KlongMomentumCalculatorExpertModule.h>
13 #include <framework/logging/Logger.h>
16 #include <analysis/dataobjects/Particle.h>
19 #include <analysis/DecayDescriptor/DecayDescriptorParticle.h>
22 #include <analysis/DecayDescriptor/ParticleListName.h>
23 #include <analysis/utility/ParticleCopy.h>
50 setDescription(
"This module is used to employ kinematic constraints to determine the momentum of Klongs for two body B decays containing a K_L0 and something else. The module creates a list of K_L0 candidates whose K_L0 momentum is reconstructed by combining the reconstructed direction (from either the ECL or KLM) of the K_L0 and kinematic constraints of the intial state.");
51 setPropertyFlags(c_ParallelProcessingCertified);
54 addParam(
"decayString", m_decayString,
55 "Input DecayDescriptor string.");
56 addParam(
"cut", m_cutParameter,
"Selection criteria to be applied", std::string(
""));
57 addParam(
"maximumNumberOfCandidates", m_maximumNumberOfCandidates,
58 "Don't reconstruct channel if more candidates than given are produced.", -1);
59 addParam(
"decayMode", m_decayModeID,
"User-specified decay mode identifier (saved in 'decayModeID' extra-info for each Particle)",
61 addParam(
"writeOut", m_writeOut,
62 "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.",
false);
63 addParam(
"recoList", m_recoList,
64 "Suffix attached to the output K_L list, if not defined it is set to '_reco' \n", std::string(
"_reco"));
68 void KlongMomentumCalculatorExpertModule::initialize()
75 m_isSelfConjugatedParticle =
false;
76 m_generator =
nullptr;
79 bool valid = m_decaydescriptor.init(m_decayString);
81 B2ERROR(
"Invalid input DecayString: " << m_decayString);
86 m_pdgCode = mother->getPDGCode();
87 m_listName = mother->getFullName();
89 m_antiListName = ParticleListName::antiParticleListName(m_listName);
90 m_isSelfConjugatedParticle = (m_listName == m_antiListName);
92 m_klistName = m_recoList;
96 int nProducts = m_decaydescriptor.getNDaughters();
97 for (
int i = 0; i < nProducts; ++i) {
99 m_decaydescriptor.getDaughter(i)->getMother();
101 if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
102 m_klistName = daughter->getFullName() + m_klistName;
108 B2FATAL(
"This module is meant to reconstruct decays with a K_L0 in the final state. There is no K_L0 in this decay!");
110 m_generator = std::make_unique<ParticleGenerator>(m_decayString, m_cutParameter);
113 m_koutputList.registerInDataStore(m_klistName, flags);
115 m_cut = Variable::Cut::compile(m_cutParameter);
119 void KlongMomentumCalculatorExpertModule::event()
121 m_koutputList.create();
122 m_koutputList->initialize(Const::Klong.getPDGCode(), m_klistName);
126 int numberOfCandidates = 0;
127 while (m_generator->loadNext()) {
129 Particle particle = m_generator->getCurrentParticle();
131 TLorentzVector missDaughters;
134 bool is_physical =
true;
136 const std::vector<Particle*> daughters = particle.getDaughters();
138 if (daughters.size() < 2)
139 B2FATAL(
"Reconstructing particle as a daughter of a decay with less then 2 daughters!");
141 if (daughters.size() > 3)
142 B2FATAL(
"Higher multiplicity (>2) missing momentum decays not implemented yet!");
144 TLorentzVector pDaughters;
145 for (
auto daughter : daughters) {
146 if (daughter->getPDGCode() != Const::Klong.getPDGCode()) {
147 pDaughters += daughter->get4Vector();
151 TLorentzVector klDaughters;
152 for (
auto daughter : daughters) {
153 if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
154 kparticle = ParticleCopy::copyParticle(daughter);
155 klDaughters += daughter->get4Vector();
161 double m_b = particle.getPDGMass();
162 double m_k = Const::Klong.getMass();
167 for (
auto daughter : daughters) {
168 if (daughter->getPDGCode() != Const::Klong.getPDGCode()) {
169 m_j = daughter->getPDGMass();
170 idx = daughter->getArrayIndex() + idx * 100;
174 if (daughters.size() == 3) {
175 m_j = pDaughters.M();
178 double s_p = (klDaughters.Vect().Unit()).Dot(pDaughters.Vect());
179 double m_sum = (m_b * m_b) - (m_j * m_j) - (m_k * m_k);
180 double e_j = pDaughters.E();
182 double s_p2 = s_p * s_p;
183 double m_sum2 = m_sum * m_sum;
184 double s_pm = s_p * m_sum;
185 double e_j2 = e_j * e_j;
186 double m_k2 = m_k * m_k;
188 k_mag1 = (s_pm + std::sqrt((s_p2) * (m_sum2) - 4 * ((e_j2) - (s_p2)) * ((e_j2) * (m_k2) - (m_sum2) / 4))) / (2 * (e_j2 - s_p2));
189 k_mag2 = (s_pm - std::sqrt((s_p2) * (m_sum2) - 4 * ((e_j2) - (s_p2)) * ((e_j2) * (m_k2) - (m_sum2) / 4))) / (2 * (e_j2 - s_p2));
192 missDaughters.SetVect(k_mag1 * (klDaughters.Vect().Unit()));
194 missDaughters.SetVect(k_mag2 * (klDaughters.Vect().Unit()));
195 missDaughters.SetE(std::sqrt(m_k * m_k + missDaughters.Vect().Mag2()));
197 for (
auto daughter : daughters) {
198 if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
199 if (!isnan(missDaughters.Vect().Mag())) {
207 TLorentzVector mom = pDaughters + missDaughters;
208 mom.SetE(std::sqrt(m_b * m_b + mom.Vect().Mag2()));
209 particle.set4Vector(mom);
210 if (isnan(mom.Vect().Mag()))
214 if (!m_cut->check(&particle))
220 numberOfCandidates++;
222 if (m_maximumNumberOfCandidates > 0 and numberOfCandidates > m_maximumNumberOfCandidates) {
223 m_koutputList->clear();
227 m_koutputList->addParticle(kparticle);
EStoreFlags
Flags describing behaviours of objects etc.
Represents a particle in the DecayDescriptor.
Class to store reconstructed particles.
void set4Vector(const TLorentzVector &p4)
Sets Lorentz vector.
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Accessor to arrays stored in the data store.
Type-safe access to single objects in the data store.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.