Belle II Software  release-05-01-25
KlongMomentumCalculatorExpertModule.cc
1 /*************************************************************************
2 * BASF2 (Belle Analysis Framework 2) *
3 * Copyright(C) 2018 - Belle II Collaboration *
4 * *
5 * Author: The Belle II Collaboration *
6 * Contributors: B.Oberhof, benjamin.oberhof@lnf.infn.it *
7 * *
8 * This software is provided "as is" without any warranty. *
9 **************************************************************************/
10 
11 // Own include
12 #include <analysis/modules/KlongDecayReconstructor/KlongMomentumCalculatorExpertModule.h>
13 
14 // framework aux
15 #include <framework/logging/Logger.h>
16 
17 // dataobjects
18 #include <analysis/dataobjects/Particle.h>
19 
20 // decay descriptor
21 #include <analysis/DecayDescriptor/DecayDescriptorParticle.h>
22 
23 // utilities
24 #include <analysis/DecayDescriptor/ParticleListName.h>
25 #include <analysis/utility/ParticleCopy.h>
26 
27 #include <memory>
28 
29 using namespace std;
30 
31 namespace Belle2 {
37 //-----------------------------------------------------------------
38 // Register module
39 //-----------------------------------------------------------------
40 
41  REG_MODULE(KlongMomentumCalculatorExpert)
42 
43 //-----------------------------------------------------------------
44 // Implementation
45 //-----------------------------------------------------------------
46 
48  Module(), m_pdgCode(0)
49 
50  {
51  // set module description (e.g. insert text)
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);
54 
55  // Add parameters
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)",
62  0);
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"));
67 
68  }
69 
70  void KlongMomentumCalculatorExpertModule::initialize()
71  {
72  // clear everything, initialize private members
73  m_pdgCode = 0;
74  m_listName = "";
75  m_isSelfConjugatedParticle = false;
76  m_generator = nullptr;
77 
78  // obtain the input and output particle lists from the decay string
79  bool valid = m_decaydescriptor.init(m_decayString);
80  if (!valid)
81  B2ERROR("Invalid input DecayString: " << m_decayString);
82 
83  // Mother particle
84  const DecayDescriptorParticle* mother = m_decaydescriptor.getMother();
85 
86  m_pdgCode = mother->getPDGCode();
87  m_listName = mother->getFullName();
88 
89  m_antiListName = ParticleListName::antiParticleListName(m_listName);
90  m_isSelfConjugatedParticle = (m_listName == m_antiListName);
91 
92  m_klistName = m_recoList;
93 
94  // Daughters
95  bool k_check = false;
96  int nProducts = m_decaydescriptor.getNDaughters();
97  for (int i = 0; i < nProducts; ++i) {
98  const DecayDescriptorParticle* daughter =
99  m_decaydescriptor.getDaughter(i)->getMother();
100  StoreObjPtr<ParticleList>().isRequired(daughter->getFullName());
101  if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
102  m_klistName = daughter->getFullName() + m_klistName;
103  k_check = true;
104  }
105  }
106 
107  if (!k_check)
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!");
109 
110  m_generator = std::make_unique<ParticleGenerator>(m_decayString, m_cutParameter);
111 
112  StoreObjPtr<ParticleList> KparticleList(m_klistName);
113  DataStore::EStoreFlags flags = m_writeOut ? DataStore::c_WriteOut : DataStore::c_DontWriteOut;
114  KparticleList.registerInDataStore(flags);
115 
116  m_cut = Variable::Cut::compile(m_cutParameter);
117 
118  }
119 
120  void KlongMomentumCalculatorExpertModule::event()
121  {
122  StoreArray<Particle> particles;
123 
124  StoreObjPtr<ParticleList> koutputList(m_klistName);
125  koutputList.create();
126  koutputList->initialize(Const::Klong.getPDGCode(), m_klistName);
127 
128  m_generator->init();
129 
130  int numberOfCandidates = 0;
131  while (m_generator->loadNext()) {
132 
133  Particle particle = m_generator->getCurrentParticle();
134 
135  TLorentzVector missDaughters;
136  Particle* kparticle = nullptr;
137 
138  bool is_physical = true;
139 
140  const std::vector<Particle*> daughters = particle.getDaughters();
141 
142  if (daughters.size() < 2)
143  B2FATAL("Reconstructing particle as a daughter of a decay with less then 2 daughters!");
144 
145  if (daughters.size() > 3)
146  B2FATAL("Higher multiplicity (>2) missing momentum decays not implemented yet!");
147 
148  TLorentzVector pDaughters;
149  for (auto daughter : daughters) {
150  if (daughter->getPDGCode() != Const::Klong.getPDGCode()) {
151  pDaughters += daughter->get4Vector();
152  }
153  }
154 
155  TLorentzVector klDaughters;
156  for (auto daughter : daughters) {
157  if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
158  kparticle = ParticleCopy::copyParticle(daughter);
159  klDaughters += daughter->get4Vector();
160  }
161  }
162 
163  double k_mag1 = 0.;
164  double k_mag2 = 0.;
165  double m_b = particle.getPDGMass();
166  double m_k = Const::Klong.getMass();
167  double m_j = 0;
168 
169  int idx = 0;
170 
171  for (auto daughter : daughters) {
172  if (daughter->getPDGCode() != Const::Klong.getPDGCode()) {
173  m_j = daughter->getPDGMass();
174  idx = daughter->getArrayIndex() + idx * 100;
175  }
176  }
177 
178  if (daughters.size() == 3) {
179  m_j = pDaughters.M();
180  }
181 
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();
185 
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;
191 
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));
194 
195  if (k_mag1 > 0)
196  missDaughters.SetVect(k_mag1 * (klDaughters.Vect().Unit()));
197  else
198  missDaughters.SetVect(k_mag2 * (klDaughters.Vect().Unit()));
199  missDaughters.SetE(std::sqrt(m_k * m_k + missDaughters.Vect().Mag2()));
200 
201  for (auto daughter : daughters) {
202  if (daughter->getPDGCode() == Const::Klong.getPDGCode()) {
203  if (!isnan(missDaughters.Vect().Mag())) {
204  kparticle->set4Vector(missDaughters);
205  } else
206  is_physical = false;
207  }
208  }
209 
210  if (is_physical) {
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()))
215  is_physical = false;
216  }
217 
218  if (!m_cut->check(&particle))
219  continue;
220 
221  if (!is_physical)
222  continue;
223 
224  numberOfCandidates++;
225 
226  if (m_maximumNumberOfCandidates > 0 and numberOfCandidates > m_maximumNumberOfCandidates) {
227  koutputList->clear();
228  break;
229  }
230 
231  koutputList->addParticle(kparticle);
232  kparticle->addExtraInfo("permID", idx);
233 
234  } //while
235 
236  } //event
237 
239 } // end Belle2 namespace
240 
Belle2::Particle::set4Vector
void set4Vector(const TLorentzVector &p4)
Sets Lorentz vector.
Definition: Particle.h:279
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::Particle::addExtraInfo
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1224
Belle2::DataStore::EStoreFlags
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:71
Belle2::DecayDescriptorParticle
Represents a particle in the DecayDescriptor.
Definition: DecayDescriptorParticle.h:37
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StoreObjPtr
Type-safe access to single objects in the data store.
Definition: ParticleList.h:33
Belle2::Particle
Class to store reconstructed particles.
Definition: Particle.h:77
Belle2::KlongMomentumCalculatorExpertModule
reco missing module
Definition: KlongMomentumCalculatorExpertModule.h:40
Belle2::StoreArray< Particle >