Belle II Software  release-06-00-14
RestOfEvent.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 #include <analysis/dataobjects/RestOfEvent.h>
10 
11 #include <framework/datastore/StoreArray.h>
12 
13 #include <analysis/dataobjects/Particle.h>
14 #include <mdst/dataobjects/MCParticle.h>
15 #include <mdst/dataobjects/Track.h>
16 #include <mdst/dataobjects/ECLCluster.h>
17 #include <mdst/dataobjects/KLMCluster.h>
18 
19 #include <analysis/ClusterUtility/ClusterUtils.h>
20 
21 #include <TLorentzVector.h>
22 
23 using namespace Belle2;
24 // New methods:
25 void RestOfEvent::addParticles(const std::vector<const Particle*>& particlesToAdd)
26 {
27  StoreArray<Particle> allParticles;
28  for (auto* particleToAdd : particlesToAdd) {
29  std::vector<const Particle*> daughters = particleToAdd->getFinalStateDaughters();
30  for (auto* daughter : daughters) {
31  bool toAdd = true;
32  for (auto& myIndex : m_particleIndices) {
33  if (allParticles[myIndex]->isCopyOf(daughter, true)) {
34  toAdd = false;
35  break;
36  }
37  }
38  if (toAdd) {
39  B2DEBUG(10, "\t\tAdding particle with PDG " << daughter->getPDGCode());
40  m_particleIndices.insert(daughter->getArrayIndex());
41  }
42  }
43  }
44 }
45 
46 std::vector<const Particle*> RestOfEvent::getParticles(const std::string& maskName, bool unpackComposite) const
47 {
48  std::vector<const Particle*> result;
49  StoreArray<Particle> allParticles;
50  std::set<int> source;
51  if (m_particleIndices.size() == 0) {
52  B2DEBUG(10, "ROE contains no particles, masks are empty too");
53  return result;
54  }
55  if (maskName == "") {
56  // if no mask provided work with internal source
57  source = m_particleIndices;
58  } else {
59  bool maskFound = false;
60  for (auto& mask : m_masks) {
61  if (mask.getName() == maskName) {
62  maskFound = true;
63  source = mask.getParticles();
64  break;
65  }
66  }
67  if (!maskFound) {
68  B2FATAL("No " << maskName << " mask defined in current ROE!");
69  }
70  }
71  for (const int index : source) {
72  if ((allParticles[index]->getParticleSource() == Particle::EParticleSourceObject::c_Composite or
73  allParticles[index]->getParticleSource() == Particle::EParticleSourceObject::c_V0) && unpackComposite) {
74  auto fsdaughters = allParticles[index]->getFinalStateDaughters();
75  for (auto* daughter : fsdaughters) {
76  result.push_back(daughter);
77  }
78  continue;
79  }
80  result.push_back(allParticles[index]);
81  }
82  return result;
83 }
84 
85 std::vector<const Particle*> RestOfEvent::getPhotons(const std::string& maskName, bool unpackComposite) const
86 {
87  auto particles = getParticles(maskName, unpackComposite);
88  std::vector<const Particle*> photons;
89  for (auto* particle : particles) {
90  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_ECLCluster) {
91  photons.push_back(particle);
92  }
93  }
94  return photons;
95 }
96 
97 std::vector<const Particle*> RestOfEvent::getHadrons(const std::string& maskName, bool unpackComposite) const
98 {
99  auto particles = getParticles(maskName, unpackComposite);
100  std::vector<const Particle*> hadrons;
101  for (auto* particle : particles) {
102  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_KLMCluster) {
103  hadrons.push_back(particle);
104  }
105  }
106  return hadrons;
107 }
108 
109 std::vector<const Particle*> RestOfEvent::getChargedParticles(const std::string& maskName, unsigned int pdg,
110  bool unpackComposite) const
111 {
112  auto particles = getParticles(maskName, unpackComposite);
113  std::vector<const Particle*> charged;
114  for (auto* particle : particles) {
115  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_Track) {
116  if (pdg == 0 || pdg == abs(particle->getPDGCode())) {
117  charged.push_back(particle);
118  }
119  }
120  }
121  return charged;
122 }
123 
124 
125 bool RestOfEvent::hasParticle(const Particle* particle, const std::string& maskName) const
126 {
127  if (maskName != "" && !hasMask(maskName)) {
128  B2FATAL("No " << maskName << " mask defined in current ROE!");
129  }
130 
131  std::vector<const Particle*> particlesROE = getParticles(maskName);
132  return isInParticleList(particle, particlesROE);
133 }
134 
135 void RestOfEvent::initializeMask(const std::string& name, const std::string& origin)
136 {
137  if (name == "") {
138  B2FATAL("Creation of ROE Mask with an empty name is not allowed!");
139  }
140  if (findMask(name)) {
141  B2FATAL("ROE Mask already exists!");
142  }
143  Mask elon(name, origin);
144  m_masks.push_back(elon);
145 }
146 
147 void RestOfEvent::excludeParticlesFromMask(const std::string& maskName, const std::vector<const Particle*>& particlesToUpdate,
148  Particle::EParticleSourceObject listType, bool discard)
149 {
150  Mask* mask = findMask(maskName);
151  if (!mask) {
152  B2FATAL("No " << maskName << " mask defined in current ROE!");
153  }
154  std::string maskNameToGetParticles = maskName;
155  if (!mask->isValid()) {
156  maskNameToGetParticles = "";
157  }
158  std::vector<const Particle*> allROEParticles = getParticles(maskNameToGetParticles);
159  std::vector<const Particle*> toKeepinROE;
160  for (auto* roeParticle : allROEParticles) {
161  if (isInParticleList(roeParticle, particlesToUpdate)) {
162  if (!discard) {
163  // If keep particles option is on, take the equal particles
164  toKeepinROE.push_back(roeParticle);
165  }
166  } else {
167  // Keep all particles which has different type than provided list
168  if (listType != roeParticle->getParticleSource()) {
169  toKeepinROE.push_back(roeParticle);
170  } else if (discard) {
171  // If keep particles option is off, take not equal particles
172  toKeepinROE.push_back(roeParticle);
173  }
174  }
175  }
176  mask->clearParticles();
177  mask->addParticles(toKeepinROE);
178 }
179 
180 void RestOfEvent::updateMaskWithCuts(const std::string& maskName, const std::shared_ptr<Variable::Cut>& trackCut,
181  const std::shared_ptr<Variable::Cut>& eclCut, const std::shared_ptr<Variable::Cut>& klmCut, bool updateExisting)
182 {
183  Mask* mask = findMask(maskName);
184  if (!mask) {
185  B2FATAL("ROE Mask does not exist!");
186  }
187  std::string sourceName = "";
188  if (updateExisting) {
189  // if mask already exists, take its particles to update
190  sourceName = maskName;
191  }
192  // get all initial ROE particles, don't touch the possible V0s, otherwise, some daughters may be excluded, and some not... This may be revisited if needed
193  std::vector<const Particle*> allROEParticles = getParticles(sourceName, false);
194  std::vector<const Particle*> maskedParticles;
195  // First check particle type, then check cuts, if no cuts provided, take all particles of this type
196  for (auto* particle : allROEParticles) {
197  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_Track && (!trackCut || trackCut->check(particle))) {
198  maskedParticles.push_back(particle);
199  }
200  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_ECLCluster && (!eclCut || eclCut->check(particle))) {
201  maskedParticles.push_back(particle);
202  }
203  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_KLMCluster && (!klmCut || klmCut->check(particle))) {
204  maskedParticles.push_back(particle);
205  }
206  // don't lose a possible V0 particle
207  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_Composite or
208  particle->getParticleSource() == Particle::EParticleSourceObject::c_V0) {
209  maskedParticles.push_back(particle);
210  }
211  }
212  mask->clearParticles();
213  mask->addParticles(maskedParticles);
214 }
215 
216 void RestOfEvent::updateMaskWithV0(const std::string& name, const Particle* particleV0)
217 {
218  Mask* mask = findMask(name);
219  if (!mask) {
220  B2FATAL("ROE Mask does not exist!");
221  }
222  std::vector<const Particle*> allROEParticles = getParticles(name, false);
223  std::vector<int> indicesToErase;
224  std::vector<const Particle*> daughtersV0 = particleV0->getFinalStateDaughters();
225  for (auto* maskParticle : allROEParticles) {
226  bool toKeep = true;
227  for (auto* daughterV0 : daughtersV0) {
228  if (daughterV0->isCopyOf(maskParticle, true)) {
229  toKeep = false;
230  }
231  }
232  if (!toKeep) {
233  indicesToErase.push_back(maskParticle->getArrayIndex());
234  }
235  }
236  if (daughtersV0.size() != indicesToErase.size()) {
237  B2DEBUG(10, "Only " << indicesToErase.size() << " daughters are excluded from mask particles. Abort");
238  return;
239  }
240  std::string toprint = "We will erase next indices from " + name + " mask: ";
241  for (auto& i : indicesToErase) {
242  toprint += std::to_string(i) + " ";
243  }
244  B2DEBUG(10, toprint);
245  // If everything is good, we add
246  mask->addV0(particleV0, indicesToErase);
247 }
248 
249 bool RestOfEvent::checkCompatibilityOfMaskAndV0(const std::string& name, const Particle* particleV0)
250 {
251  Mask* mask = findMask(name);
252  if (!mask) {
253  B2FATAL("ROE Mask does not exist!");
254  }
255  if (!mask->isValid()) {
256  return false; //We should have particles here!
257  }
258  if (particleV0->getParticleSource() != Particle::EParticleSourceObject::c_Composite and
259  particleV0->getParticleSource() != Particle::EParticleSourceObject::c_V0) {
260  return false;
261  }
262  std::vector<const Particle*> daughtersV0 = particleV0->getFinalStateDaughters();
263  for (auto* daughter : daughtersV0) {
264  if (daughter->getParticleSource() != Particle::EParticleSourceObject::c_Track) {
265  return false; // Non tracks are not supported yet
266  }
267  }
268  if (mask->hasV0(particleV0)) {
269  return false; // We are not going to add another one
270  }
271  return true;
272 }
273 
274 bool RestOfEvent::hasMask(const std::string& name) const
275 {
276  for (auto& mask : m_masks) {
277  if (mask.getName() == name) {
278  return true;
279  }
280  }
281  return false;
282 }
283 TLorentzVector RestOfEvent::get4Vector(const std::string& maskName) const
284 {
285  TLorentzVector roe4Vector;
286  std::vector<const Particle*> myParticles = RestOfEvent::getParticles(maskName);
287  for (const Particle* particle : myParticles) {
288  // KLMClusters are discarded, because KLM energy estimation is based on hit numbers, therefore it is unreliable
289  // also, enable it as an experimental option:
290  if (particle->getParticleSource() == Particle::EParticleSourceObject::c_KLMCluster and !m_useKLMEnergy) {
291  continue;
292  }
293  roe4Vector += particle->get4Vector();
294  }
295  return roe4Vector;
296 }
297 
298 
299 RestOfEvent::Mask* RestOfEvent::findMask(const std::string& name)
300 {
301  for (auto& mask : m_masks) {
302  if (mask.getName() == name) {
303  return &mask;
304  }
305  }
306  return nullptr;
307 
308 }
309 
310 int RestOfEvent::getNTracks(const std::string& maskName) const
311 {
312  int nTracks = getChargedParticles(maskName).size();
313  return nTracks;
314 }
315 
316 int RestOfEvent::getNECLClusters(const std::string& maskName) const
317 {
318  int nROEneutralECLClusters = getPhotons(maskName).size();
319  int nROEchargedECLClusters = 0;
320  for (auto& roeParticle : getChargedParticles(maskName)) {
321  if (roeParticle->getECLCluster()) ++nROEchargedECLClusters;
322  }
323 
324  return nROEneutralECLClusters + nROEchargedECLClusters;
325 }
326 
327 int RestOfEvent::getNKLMClusters(const std::string& maskName) const
328 {
329  int nROEKLMClusters = getHadrons(maskName).size();
330  return nROEKLMClusters;
331 }
332 
333 TLorentzVector RestOfEvent::get4VectorNeutralECLClusters(const std::string& maskName) const
334 {
335  auto roeClusters = getPhotons(maskName);
336  TLorentzVector roe4VectorECLClusters;
337 
338  // Add all momenta from neutral ECLClusters which have the nPhotons hypothesis
339  for (auto& roeCluster : roeClusters) {
340  if (roeCluster->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons)
341  roe4VectorECLClusters += roeCluster->get4Vector();
342  }
343 
344  return roe4VectorECLClusters;
345 }
346 
347 bool RestOfEvent::isInParticleList(const Particle* roeParticle, const std::vector<const Particle*>& particlesToUpdate) const
348 {
349  for (auto* listParticle : particlesToUpdate) {
350  if (roeParticle->isCopyOf(listParticle, true)) {
351  return true;
352  }
353  }
354  return false;
355 }
356 
357 std::vector<std::string> RestOfEvent::getMaskNames() const
358 {
359  std::vector<std::string> maskNames;
360 
361  for (auto& mask : m_masks) {
362  maskNames.push_back(mask.getName());
363  }
364 
365  return maskNames;
366 }
367 
368 void RestOfEvent::print(const std::string& maskName, bool unpackComposite) const
369 {
370  std::string tab = " - ";
371  if (maskName != "") {
372  // Disable possible B2FATAL in printing method, might be useful for tests
373  if (!hasMask(maskName)) {
374  B2WARNING("No mask with the name '" << maskName << "' exists in this ROE! Nothing else to print");
375  return;
376  }
377  tab = " - - ";
378  } else {
379  if (m_isNested) {
380  B2INFO(tab << "ROE is nested");
381  }
382  if (m_isFromMC) {
383  B2INFO(tab << "ROE is build from generated particles");
384  }
385  }
386  if (m_useKLMEnergy) {
387  B2WARNING("This ROE has KLM energy included into its 4-vector!");
388  }
389  if (!m_isFromMC) {
390  unsigned int nCharged = getChargedParticles(maskName, 0, unpackComposite).size();
391  unsigned int nPhotons = getPhotons(maskName, unpackComposite).size();
392  unsigned int nNeutralHadrons = getHadrons(maskName, unpackComposite).size();
393  B2INFO(tab << "No. of Charged particles in ROE: " << nCharged);
394  B2INFO(tab << "No. of Photons in ROE: " << nPhotons);
395  B2INFO(tab << "No. of K_L0 and neutrons in ROE: " << nNeutralHadrons);
396  } else {
397  unsigned int nParticles = getParticles(maskName, unpackComposite).size();
398  B2INFO(tab << "No. of generated particles in ROE: " << nParticles);
399  }
400  printIndices(maskName, unpackComposite, tab);
401 }
402 
403 void RestOfEvent::printIndices(const std::string& maskName, bool unpackComposite, const std::string& tab) const
404 {
405  auto particles = getParticles(maskName, unpackComposite);
406  if (particles.size() == 0) {
407  B2INFO(tab << "No indices to print");
408  return;
409  }
410  std::string printoutIndex = tab + "|";
411  std::string printoutPDG = tab + "|";
412  for (const auto particle : particles) {
413  printoutIndex += std::to_string(particle->getArrayIndex()) + " | ";
414  printoutPDG += std::to_string(particle->getPDGCode()) + " | ";
415  }
416  B2INFO(printoutPDG);
417  B2INFO(printoutIndex);
418 }
419 
420 Particle* RestOfEvent::convertToParticle(const std::string& maskName, int pdgCode, bool isSelfConjugated)
421 {
422  StoreArray<Particle> particles;
423  std::set<int> source;
424  if (maskName == "") {
425  // if no mask provided work with internal source
426  source = m_particleIndices;
427  } else {
428  bool maskFound = false;
429  for (auto& mask : m_masks) {
430  if (mask.getName() == maskName) {
431  maskFound = true;
432  source = mask.getParticles();
433  break;
434  }
435  }
436  if (!maskFound) {
437  B2FATAL("No " << maskName << " mask defined in current ROE!");
438  }
439  }
440  int particlePDG = (pdgCode == 0) ? getPDGCode() : pdgCode;
441  auto isFlavored = (isSelfConjugated) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
442  return particles.appendNew(get4Vector(maskName), particlePDG, isFlavored, std::vector(source.begin(),
443  source.end()), Particle::PropertyFlags::c_IsUnspecified);
444 }
445 
@ c_nPhotons
CR is split into n photons (N1)
Class to store reconstructed particles.
Definition: Particle.h:74
std::vector< const Belle2::Particle * > getFinalStateDaughters() const
Returns a vector of pointers to Final State daughter particles.
Definition: Particle.cc:657
EParticleSourceObject
particle source enumerators
Definition: Particle.h:81
bool isCopyOf(const Particle *oParticle, bool doDetailedComparison=false) const
Returns true if this Particle and oParticle are copies of each other.
Definition: Particle.cc:721
EParticleSourceObject getParticleSource() const
Returns particle source as defined with enum EParticleSourceObject.
Definition: Particle.h:416
int getPDGCode() const
Gets the PDG code of the rest of event.
Definition: RestOfEvent.h:210
std::set< int > m_particleIndices
StoreArray indices to unused particles.
Definition: RestOfEvent.h:361
TLorentzVector get4Vector(const std::string &maskName="") const
Get 4-momentum vector all (no mask) or a subset (use mask) of all Tracks and ECLClusters in ROE.
Definition: RestOfEvent.cc:283
int getNTracks(const std::string &maskName="") const
Get number of all (no mask) or a subset (use mask) of all Tracks in ROE.
Definition: RestOfEvent.cc:310
void initializeMask(const std::string &name, const std::string &origin="unknown")
Initialize new mask.
Definition: RestOfEvent.cc:135
bool checkCompatibilityOfMaskAndV0(const std::string &name, const Particle *particleV0)
Check if V0 can be added, maybe should be moved to private.
Definition: RestOfEvent.cc:249
bool hasParticle(const Particle *particle, const std::string &maskName="") const
Check if ROE has StoreArray index of given to the list of unused tracks in the event.
Definition: RestOfEvent.cc:125
void updateMaskWithCuts(const std::string &name, const std::shared_ptr< Variable::Cut > &trackCut=nullptr, const std::shared_ptr< Variable::Cut > &eclCut=nullptr, const std::shared_ptr< Variable::Cut > &klmCut=nullptr, bool updateExisting=false)
Update mask with cuts.
Definition: RestOfEvent.cc:180
void print(const std::string &maskName="", bool unpackComposite=true) const
Prints the contents of a RestOfEvent object to screen.
Definition: RestOfEvent.cc:368
bool hasMask(const std::string &name) const
True if this ROE object has mask.
Definition: RestOfEvent.cc:274
bool m_isFromMC
MC ROE indicator.
Definition: RestOfEvent.h:365
std::vector< const Particle * > getChargedParticles(const std::string &maskName="", unsigned int pdg=0, bool unpackComposite=true) const
Get charged particles from ROE mask.
Definition: RestOfEvent.cc:109
int getNECLClusters(const std::string &maskName="") const
Get number of all (no mask) or a subset (use mask) of all ECLclusters in ROE.
Definition: RestOfEvent.cc:316
std::vector< const Particle * > getHadrons(const std::string &maskName="", bool unpackComposite=true) const
Get hadrons from ROE mask.
Definition: RestOfEvent.cc:97
std::vector< const Particle * > getParticles(const std::string &maskName="", bool unpackComposite=true) const
Get all Particles from ROE mask.
Definition: RestOfEvent.cc:46
void printIndices(const std::string &maskName="", bool unpackComposite=true, const std::string &tab=" - ") const
Prints indices in the given set in a single line.
Definition: RestOfEvent.cc:403
Mask * findMask(const std::string &name)
Helper method to find ROE mask.
Definition: RestOfEvent.cc:299
void addParticles(const std::vector< const Particle * > &particle)
Add StoreArray indices of given Particles to the list of unused particles in the event.
Definition: RestOfEvent.cc:25
std::vector< std::string > getMaskNames() const
Get vector of all mask names of the ROE object.
Definition: RestOfEvent.cc:357
int getNKLMClusters(const std::string &maskName="") const
Get number of all remaining KLM clusters.
Definition: RestOfEvent.cc:327
void updateMaskWithV0(const std::string &name, const Particle *particleV0)
Update mask with composite particle.
Definition: RestOfEvent.cc:216
bool m_useKLMEnergy
Include KLM energy into ROE 4-vector.
Definition: RestOfEvent.h:366
Particle * convertToParticle(const std::string &maskName="", int pdgCode=0, bool isSelfConjugated=true)
Converts ROE to Particle and adds it to StoreArray.
Definition: RestOfEvent.cc:420
TLorentzVector get4VectorNeutralECLClusters(const std::string &maskName="") const
Get 4-momentum vector all (no mask) or a subset (use mask) of all ECLClusters in ROE.
Definition: RestOfEvent.cc:333
std::vector< Mask > m_masks
List of the ROE masks.
Definition: RestOfEvent.h:362
void excludeParticlesFromMask(const std::string &maskName, const std::vector< const Particle * > &particles, Particle::EParticleSourceObject listType, bool discard)
Update mask by keeping or excluding particles.
Definition: RestOfEvent.cc:147
bool isInParticleList(const Particle *roeParticle, const std::vector< const Particle * > &particlesToUpdate) const
Checks if a particle has its copy in the provided list.
Definition: RestOfEvent.cc:347
bool m_isNested
Nested ROE indicator.
Definition: RestOfEvent.h:364
std::vector< const Particle * > getPhotons(const std::string &maskName="", bool unpackComposite=true) const
Get photons from ROE mask.
Definition: RestOfEvent.cc:85
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Abstract base class for different kinds of events.
Structure of Rest of Event mask.
Definition: RestOfEvent.h:67