Belle II Software  release-08-01-10
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 header.
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 using namespace std;
24 using namespace Belle2;
25 
26 //-----------------------------------------------------------------
27 // Register module
28 //-----------------------------------------------------------------
29 
30 REG_MODULE(ParticleCombiner);
31 
32 //-----------------------------------------------------------------
33 // Implementation
34 //-----------------------------------------------------------------
35 
36 ParticleCombinerModule::ParticleCombinerModule() :
37  Module()
38 
39 {
40  // set module description (e.g. insert text)
41  setDescription("Makes particle combinations");
43 
44  // Add parameters
45  addParam("decayString", m_decayString,
46  "Input DecayDescriptor string (see :ref:`DecayString`).");
47  addParam("cut", m_cutParameter, "Selection criteria to be applied", std::string(""));
48  addParam("maximumNumberOfCandidates", m_maximumNumberOfCandidates,
49  "Max. number of candidates reconstructed. By default, if the limit is reached no candidates will be produced.\n"
50  "This behaviour can be changed by \'ignoreIfTooManyCandidates\' flag.", 10000);
51 
52  addParam("ignoreIfTooManyCandidates", m_ignoreIfTooManyCandidates,
53  "Don't reconstruct channel if more candidates than given by \'maximumNumberOfCandidates\' are produced.", true);
54 
55  addParam("decayMode", m_decayModeID, "User-specified decay mode identifier (saved in 'decayModeID' extra-info for each Particle)",
56  0);
57  addParam("writeOut", m_writeOut,
58  "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.", false);
59  addParam("recoilParticleType", m_recoilParticleType,
60  "If not equal 0, the mother Particle is reconstructed in the recoil against the daughter particles.\n"
61  "In the case of the following decay chain M -> D1 D2 ... Dn and\n\n"
62  ""
63  " a) recoilParticleType = 1: \n\n"
64  " - the mother momentum is given by: p(M) = p(e+e-) - p(D1) - p(D2) - ... - p(DN)\n"
65  " - D1, D2, ..., DN are attached as daughters of M\n\n"
66  " b) recoilParticleType = 2: \n\n"
67  " - the mother momentum is given by: p(M) = p(D1) - p(D2) - ... - p(DN)\n"
68  " - D1, D2, ..., DN are attached as daughters of M\n\n", 0);
69  addParam("chargeConjugation", m_chargeConjugation,
70  "If true, the charge-conjugated mode will be reconstructed as well", true);
71  addParam("allowChargeViolation", m_allowChargeViolation,
72  "If true the decay string does not have to conserve electric charge", false);
73 
74  // initializing the rest of private members
75  m_pdgCode = 0;
77  m_generator = nullptr;
78 }
79 
81 {
82  // clear everything
83  m_pdgCode = 0;
84  m_listName = "";
85 
86  // obtain the input and output particle lists from the decay string
87  bool valid = m_decaydescriptor.init(m_decayString);
88  if (!valid)
89  B2ERROR("Invalid input DecayString: " << m_decayString);
90 
91  // Mother particle
93 
94  m_pdgCode = mother->getPDGCode();
95  m_listName = mother->getFullName();
96 
99 
100  // Daughters
101  int nProducts = m_decaydescriptor.getNDaughters();
102  int daughtersNetCharge = 0;
103  for (int i = 0; i < nProducts; ++i) {
104  const DecayDescriptorParticle* daughter =
106  StoreObjPtr<ParticleList>().isRequired(daughter->getFullName());
107  int daughterPDGCode = daughter->getPDGCode();
108  if (m_recoilParticleType == 2 && i == 0) {
109  daughtersNetCharge -= EvtPDLUtil::charge(daughterPDGCode);
110  } else {
111  daughtersNetCharge += EvtPDLUtil::charge(daughterPDGCode);
112  }
113  }
114 
115  // The electric charge check makes no sense for an inclusive decay
116  if (!m_decaydescriptor.isIgnoreMassive() and daughtersNetCharge != EvtPDLUtil::charge(m_pdgCode)) {
117  if (!m_allowChargeViolation) {
118  B2FATAL("Your decay string " << m_decayString << " violates electric charge conservation!\n"
119  "If you want to allow this you can set the argument 'allowChargeViolation' to True. Something like:\n"
120  "modularAnalysis.reconstructDecay(" << m_decayString << ", your_cuts, allowChargeViolation=True, path=mypath)");
121  }
122  B2WARNING("Your decay string " << m_decayString << " violates electric charge conservation!\n"
123  "Processing is continued assuming that you allowed this deliberately, e.g. for systematic studies etc.");
124  }
125 
126  if (m_recoilParticleType == 0) {
127  m_generator = std::make_unique<ParticleGenerator>(m_decayString, m_cutParameter);
128  } else {
129  string noCutInParticleCombiner = "";
130  m_generator = std::make_unique<ParticleGenerator>(m_decayString, noCutInParticleCombiner);
132  }
133 
135  m_outputList.registerInDataStore(m_listName, flags);
137  m_outputAntiList.registerInDataStore(m_antiListName, flags);
138  }
139 
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 
146 {
147  m_outputList.create();
148  m_outputList->initialize(m_pdgCode, m_listName);
149 
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  ROOT::Math::PxPyPzEVector 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  ROOT::Math::PxPyPzEVector pDaughters;
184  for (unsigned i = 1; i < daughters.size(); i++) {
185  pDaughters += daughters[i]->get4Vector();
186  }
187 
188  ROOT::Math::PxPyPzEVector mom = daughters[0]->get4Vector() - pDaughters;
189  particle.set4Vector(mom);
190  }
191  if (m_recoilParticleType > 0) {
192  if (!m_cut->check(&particle)) {
193  continue;
194  }
195  }
196 
197  numberOfCandidates++;
198 
199  if (m_maximumNumberOfCandidates > 0 and numberOfCandidates > m_maximumNumberOfCandidates) {
201  B2WARNING("Maximum number of " << m_maximumNumberOfCandidates << " candidates reached, skipping event");
202  m_outputList->clear();
203  } else {
204  B2WARNING("Maximum number of " << m_maximumNumberOfCandidates << " candidates reached. Ignoring others");
205  }
206  break;
207  }
208 
209  Particle* newParticle = m_particles.appendNew(particle);
210 
211  m_outputList->addParticle(newParticle);
212 
213  // append to the created particle the user specified decay mode ID
214  newParticle->addExtraInfo("decayModeID", m_decayModeID);
215  }
216 }
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:69
@ c_WriteOut
Object/array should be saved by output modules.
Definition: DataStore.h:70
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
Represents a particle in the DecayDescriptor.
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
const DecayDescriptorParticle * getMother() const
return mother.
int getNDaughters() const
return number of direct daughters.
bool isIgnoreMassive() const
Check if missing massive final state particles shall be ignored.
const DecayDescriptor * getDaughter(int i) const
return i-th daughter (0 based index).
static std::unique_ptr< GeneralCut > compile(const std::string &cut)
Creates an instance of a cut and returns a unique_ptr to it, if you need a copy-able object instead y...
Definition: GeneralCut.h:84
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
Class to hold Lorentz transformations from/to CMS and boost vector.
ROOT::Math::PxPyPzEVector getBeamFourMomentum() const
Returns LAB four-momentum of e+e-, i.e.
int m_recoilParticleType
type of recoil particle: 0 - not recoil (normal reconstruction); 1 - recoil against e+e- and all daug...
bool m_isSelfConjugatedParticle
flag that indicates whether an anti-particle mother does not exist and should not be reconstructed as...
int m_maximumNumberOfCandidates
maximum number of reconstructed candidates
std::string m_antiListName
output anti-particle list name
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
std::string m_decayString
Input DecayString specifying the decay being reconstructed.
std::string m_listName
output particle list name
StoreObjPtr< ParticleList > m_outputAntiList
output anti-particle list
StoreArray< Particle > m_particles
StoreArray of Particles.
StoreObjPtr< ParticleList > m_outputList
output particle list
std::unique_ptr< ParticleGenerator > m_generator
Generates the combinations.
std::unique_ptr< Variable::Cut > m_cut
cut object which performs the cuts
int m_decayModeID
user specified decay mode identifier
bool m_allowChargeViolation
switch to turn on and off the requirement of electric charge conservation
std::string m_cutParameter
selection criteria
DecayDescriptor m_decaydescriptor
Decay descriptor of the decay being reconstructed.
bool m_writeOut
toggle output particle list btw.
bool m_ignoreIfTooManyCandidates
drop all candidates if max.
int m_pdgCode
PDG code of the combined mother particle.
bool m_chargeConjugation
boolean to control whether charge conjugated decay should be reconstructed as well
Class to store reconstructed particles.
Definition: Particle.h:75
void addExtraInfo(const std::string &name, double value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1337
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:96
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Definition: EvtPDLUtil.cc:44
std::string antiParticleListName(const std::string &listName)
Returns name of anti-particle-list corresponding to listName.
Abstract base class for different kinds of events.