Belle II Software  release-05-02-19
ParticleCombinerModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Marko Staric, Anze Zupanc *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 // Own include
12 #include <analysis/modules/ParticleCombiner/ParticleCombinerModule.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/EvtPDLUtil.h>
26 #include <analysis/utility/PCmsLabTransform.h>
27 
28 #include <memory>
29 
30 using namespace std;
31 
32 namespace Belle2 {
38 //-----------------------------------------------------------------
39 // Register module
40 //-----------------------------------------------------------------
41 
42  REG_MODULE(ParticleCombiner)
43 
44 //-----------------------------------------------------------------
45 // Implementation
46 //-----------------------------------------------------------------
47 
49  Module()
50 
51  {
52  // set module description (e.g. insert text)
53  setDescription("Makes particle combinations");
54  setPropertyFlags(c_ParallelProcessingCertified);
55 
56  // Add parameters
57  addParam("decayString", m_decayString,
58  "Input DecayDescriptor string (see :ref:`DecayString`).");
59  addParam("cut", m_cutParameter, "Selection criteria to be applied", std::string(""));
60  addParam("maximumNumberOfCandidates", m_maximumNumberOfCandidates,
61  "Max. number of candidates reconstructed. By default, if the limit is reached no candidates will be produced.\n"
62  "This behaviour can be changed by \'ignoreIfTooManyCandidates\' flag.", 10000);
63 
64  addParam("ignoreIfTooManyCandidates", m_ignoreIfTooManyCandidates,
65  "Don't reconstruct channel if more candidates than given by \'maximumNumberOfCandidates\' are produced.", true);
66 
67  addParam("decayMode", m_decayModeID, "User-specified decay mode identifier (saved in 'decayModeID' extra-info for each Particle)",
68  0);
69  addParam("writeOut", m_writeOut,
70  "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.", false);
71  addParam("recoilParticleType", m_recoilParticleType,
72  "If not equal 0, the mother Particle is reconstructed in the recoil against the daughter particles.\n"
73  "In the case of the following decay chain M -> D1 D2 ... Dn and\n\n"
74  ""
75  " a) recoilParticleType = 1: \n\n"
76  " - the mother momentum is given by: p(M) = p(e+e-) - p(D1) - p(D2) - ... - p(DN)\n"
77  " - D1, D2, ..., DN are attached as daughters of M\n\n"
78  " b) recoilParticleType = 2: \n\n"
79  " - the mother momentum is given by: p(M) = p(D1) - p(D2) - ... - p(DN)\n"
80  " - D1, D2, ..., DN are attached as daughters of M\n\n" , 0);
81  addParam("chargeConjugation", m_chargeConjugation,
82  "If true, the charge-conjugated mode will be reconstructed as well", true);
83  addParam("allowChargeViolation", m_allowChargeViolation,
84  "If true the decay string does not have to conserve electric charge", false);
85 
86  // initializing the rest of private members
87  m_pdgCode = 0;
88  m_isSelfConjugatedParticle = false;
89  m_generator = nullptr;
90  }
91 
92  void ParticleCombinerModule::initialize()
93  {
94  // clear everything
95  m_pdgCode = 0;
96  m_listName = "";
97 
98  // obtain the input and output particle lists from the decay string
99  bool valid = m_decaydescriptor.init(m_decayString);
100  if (!valid)
101  B2ERROR("Invalid input DecayString: " << m_decayString);
102 
103  // Mother particle
104  const DecayDescriptorParticle* mother = m_decaydescriptor.getMother();
105 
106  m_pdgCode = mother->getPDGCode();
107  m_listName = mother->getFullName();
108 
109  m_antiListName = ParticleListName::antiParticleListName(m_listName);
110  m_isSelfConjugatedParticle = (m_listName == m_antiListName);
111 
112  // Daughters
113  int nProducts = m_decaydescriptor.getNDaughters();
114  int daughtersNetCharge = 0;
115  for (int i = 0; i < nProducts; ++i) {
116  const DecayDescriptorParticle* daughter =
117  m_decaydescriptor.getDaughter(i)->getMother();
118  StoreObjPtr<ParticleList>().isRequired(daughter->getFullName());
119  int daughterPDGCode = daughter->getPDGCode();
120  if (m_recoilParticleType == 2 && i == 0) {
121  daughtersNetCharge -= EvtPDLUtil::charge(daughterPDGCode);
122  } else {
123  daughtersNetCharge += EvtPDLUtil::charge(daughterPDGCode);
124  }
125  }
126 
127  if (daughtersNetCharge != EvtPDLUtil::charge(m_pdgCode)) {
128  if (!m_allowChargeViolation) {
129  B2FATAL("Your decay string " << m_decayString << " violates electric charge conservation!\n"
130  "If you want to allow this you can set the argument 'allowChargeViolation' to True. Something like:\n"
131  "modularAnalysis.reconstructDecay(" << m_decayString << ", your_cuts, allowChargeViolation=True, path=mypath)");
132  }
133  B2WARNING("Your decay string " << m_decayString << " violates electric charge conservation!\n"
134  "Processing is continued assuming that you allowed this deliberately, e.g. for systematic studies etc.");
135  }
136 
137  m_generator = std::make_unique<ParticleGenerator>(m_decayString, m_cutParameter);
138 
139  StoreObjPtr<ParticleList> particleList(m_listName);
140  DataStore::EStoreFlags flags = m_writeOut ? DataStore::c_WriteOut : DataStore::c_DontWriteOut;
141  particleList.registerInDataStore(flags);
142  if (!m_isSelfConjugatedParticle && m_chargeConjugation) {
143  StoreObjPtr<ParticleList> antiParticleList(m_antiListName);
144  antiParticleList.registerInDataStore(flags);
145  }
146 
147  if (m_recoilParticleType != 0 && m_recoilParticleType != 1 && m_recoilParticleType != 2)
148  B2FATAL("Invalid recoil particle type = " << m_recoilParticleType <<
149  "! Valid values are 0 (not a recoil), 1 (recoiling against e+e- and daughters), 2 (daughter of a recoil)");
150  }
151 
152  void ParticleCombinerModule::event()
153  {
154  StoreArray<Particle> particles;
155 
156  StoreObjPtr<ParticleList> outputList(m_listName);
157  outputList.create();
158  outputList->initialize(m_pdgCode, m_listName);
159 
160  if (!m_isSelfConjugatedParticle && m_chargeConjugation) {
161  StoreObjPtr<ParticleList> outputAntiList(m_antiListName);
162  outputAntiList.create();
163  outputAntiList->initialize(-1 * m_pdgCode, m_antiListName);
164 
165  outputList->bindAntiParticleList(*(outputAntiList));
166  }
167 
168  m_generator->init();
169 
170  int numberOfCandidates = 0;
171  while (m_generator->loadNext(m_chargeConjugation)) {
172 
173  Particle&& particle = m_generator->getCurrentParticle();
174 
175  // if particle is reconstructed in the recoil,
176  // its 4-momentum vector needs to be fixed
177  // at this stage its 4 momentum is:
178  // p(mother) = Sum_i p(daughter_i)
179  // but it needs to be
180  // a) in the case of recoilParticleType == 1
181  // - p(mother) = p(e-) + p(e+) - Sum_i p(daughter_i)
182  // b) in the case of recoilParticleType == 2
183  // - p(mother) = p(daughter_0) - Sum_i p(daughter_i) (where i > 0)
184  if (m_recoilParticleType == 1) {
186  TLorentzVector recoilMomentum = T.getBeamFourMomentum() - particle.get4Vector();
187  particle.set4Vector(recoilMomentum);
188  } else if (m_recoilParticleType == 2) {
189  const std::vector<Particle*> daughters = particle.getDaughters();
190 
191  if (daughters.size() < 2)
192  B2FATAL("Reconstructing particle as a daughter of a recoil with less then 2 daughters!");
193 
194  TLorentzVector pDaughters;
195  for (unsigned i = 1; i < daughters.size(); i++) {
196  pDaughters += daughters[i]->get4Vector();
197  }
198 
199  TLorentzVector mom = daughters[0]->get4Vector() - pDaughters;
200  particle.set4Vector(mom);
201  }
202 
203  numberOfCandidates++;
204 
205  if (m_maximumNumberOfCandidates > 0 and numberOfCandidates > m_maximumNumberOfCandidates) {
206  if (m_ignoreIfTooManyCandidates) {
207  B2WARNING("Maximum number of " << m_maximumNumberOfCandidates << " candidates reached, skipping event");
208  outputList->clear();
209  } else {
210  B2WARNING("Maximum number of " << m_maximumNumberOfCandidates << " candidates reached. Ignoring others");
211  }
212  break;
213  }
214 
215  Particle* newParticle = particles.appendNew(particle);
216 
217  outputList->addParticle(newParticle);
218 
219  // append to the created particle the user specified decay mode ID
220  newParticle->addExtraInfo("decayModeID", m_decayModeID);
221  }
222  }
223 
225 } // end Belle2 namespace
226 
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::ParticleCombinerModule
particle combiner module
Definition: ParticleCombinerModule.h:40
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::PCmsLabTransform::getBeamFourMomentum
TLorentzVector getBeamFourMomentum() const
Returns LAB four-momentum of e+e-.
Definition: PCmsLabTransform.h:65
Belle2::Particle
Class to store reconstructed particles.
Definition: Particle.h:77
Belle2::PCmsLabTransform
Class to hold Lorentz transformations from/to CMS and boost vector.
Definition: PCmsLabTransform.h:37
Belle2::StoreArray< Particle >