12 #include <analysis/modules/KlongDecayReconstructor/KlongMomentumCalculatorExpertModule.h>
15 #include <framework/logging/Logger.h>
18 #include <analysis/dataobjects/Particle.h>
21 #include <analysis/DecayDescriptor/DecayDescriptorParticle.h>
24 #include <analysis/DecayDescriptor/ParticleListName.h>
25 #include <analysis/utility/ParticleCopy.h>
52 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.");
53 setPropertyFlags(c_ParallelProcessingCertified);
56 addParam(
"decayString", m_decayString,
57 "Input DecayDescriptor string.");
58 addParam(
"cut", m_cutParameter,
"Selection criteria to be applied", std::string(
""));
59 addParam(
"maximumNumberOfCandidates", m_maximumNumberOfCandidates,
60 "Don't reconstruct channel if more candidates than given are produced.", -1);
61 addParam(
"decayMode", m_decayModeID,
"User-specified decay mode identifier (saved in 'decayModeID' extra-info for each Particle)",
63 addParam(
"writeOut", m_writeOut,
64 "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.",
false);
65 addParam(
"recoList", m_recoList,
66 "Suffix attached to the output K_L list, if not defined it is set to '_reco' \n", std::string(
"_reco"));
70 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);
114 KparticleList.registerInDataStore(flags);
116 m_cut = Variable::Cut::compile(m_cutParameter);
120 void KlongMomentumCalculatorExpertModule::event()
125 koutputList.create();
126 koutputList->initialize(Const::Klong.getPDGCode(), m_klistName);
130 int numberOfCandidates = 0;
131 while (m_generator->loadNext()) {
133 Particle particle = m_generator->getCurrentParticle();
135 TLorentzVector missDaughters;
138 bool is_physical =
true;
140 const std::vector<Particle*> daughters = particle.getDaughters();
142 if (daughters.size() < 2)
143 B2FATAL(
"Reconstructing particle as a daughter of a decay with less then 2 daughters!");
145 if (daughters.size() > 3)
146 B2FATAL(
"Higher multiplicity (>2) missing momentum decays not implemented yet!");
148 TLorentzVector pDaughters;
149 for (
auto daughter : daughters) {
150 if (daughter->getPDGCode() != Const::Klong.getPDGCode()) {
151 pDaughters += daughter->get4Vector();
155 TLorentzVector klDaughters;
156 for (
auto daughter : daughters) {
157 if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
158 kparticle = ParticleCopy::copyParticle(daughter);
159 klDaughters += daughter->get4Vector();
165 double m_b = particle.getPDGMass();
166 double m_k = Const::Klong.getMass();
171 for (
auto daughter : daughters) {
172 if (daughter->getPDGCode() != Const::Klong.getPDGCode()) {
173 m_j = daughter->getPDGMass();
174 idx = daughter->getArrayIndex() + idx * 100;
178 if (daughters.size() == 3) {
179 m_j = pDaughters.M();
182 double s_p = (klDaughters.Vect().Unit()).Dot(pDaughters.Vect());
183 double m_sum = (m_b * m_b) - (m_j * m_j) - (m_k * m_k);
184 double e_j = pDaughters.E();
186 double s_p2 = s_p * s_p;
187 double m_sum2 = m_sum * m_sum;
188 double s_pm = s_p * m_sum;
189 double e_j2 = e_j * e_j;
190 double m_k2 = m_k * m_k;
192 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));
193 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));
196 missDaughters.SetVect(k_mag1 * (klDaughters.Vect().Unit()));
198 missDaughters.SetVect(k_mag2 * (klDaughters.Vect().Unit()));
199 missDaughters.SetE(std::sqrt(m_k * m_k + missDaughters.Vect().Mag2()));
201 for (
auto daughter : daughters) {
202 if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
203 if (!isnan(missDaughters.Vect().Mag())) {
211 TLorentzVector mom = pDaughters + missDaughters;
212 mom.SetE(std::sqrt(m_b * m_b + mom.Vect().Mag2()));
213 particle.set4Vector(mom);
214 if (isnan(mom.Vect().Mag()))
218 if (!m_cut->check(&particle))
224 numberOfCandidates++;
226 if (m_maximumNumberOfCandidates > 0 and numberOfCandidates > m_maximumNumberOfCandidates) {
227 koutputList->clear();
231 koutputList->addParticle(kparticle);