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