Belle II Software  light-2212-foldex
ParticleLoaderModule.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/ParticleLoader/ParticleLoaderModule.h>
11 
12 // framework aux
13 #include <framework/logging/Logger.h>
14 #include <framework/core/ModuleParam.templateDetails.h>
15 
16 // utilities
17 #include <analysis/DecayDescriptor/ParticleListName.h>
18 #include <analysis/utility/PCmsLabTransform.h>
19 
20 #include <utility>
21 
22 using namespace std;
23 using namespace Belle2;
24 
25 //-----------------------------------------------------------------
26 // Register module
27 //-----------------------------------------------------------------
28 
29 REG_MODULE(ParticleLoader);
30 
31 //-----------------------------------------------------------------
32 // Implementation
33 //-----------------------------------------------------------------
34 
35 ParticleLoaderModule::ParticleLoaderModule() : Module()
36 
37 {
38  setDescription("Loads MDST dataobjects as Particle objects to the StoreArray<Particle> and collects them in specified ParticleList.");
40 
41  // Add parameters
42  addParam("decayStrings", m_decayStrings,
43  "List of decay strings (see :ref:`DecayString` for syntax) that specify all output ParticleLists to be created by the module.",
44  {});
45 
46  addParam("useMCParticles", m_useMCParticles,
47  "Use MCParticles instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)", false);
48 
49  addParam("useROEs", m_useROEs,
50  "Use ROE instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)", false);
51 
52  addParam("roeMaskName", m_roeMaskName,
53  "ROE mask name to load", std::string(RestOfEvent::c_defaultMaskName));
54 
55  addParam("sourceParticleListName", m_sourceParticleListName,
56  "Particle list name from which we need to get ROEs", std::string(""));
57 
58  addParam("useMissing", m_useMissing,
59  "If true, the Particle List will be filled with missing momentum from the ROE and signal particle.", false);
60 
61  addParam("writeOut", m_writeOut,
62  "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.", false);
63 
64  addParam("skipNonPrimary", m_skipNonPrimary,
65  "If true, the secondary MC particle will be skipped, default is false",
66  false);
67 
68  addParam("addDaughters", m_addDaughters,
69  "If true, the particles from the bottom part of the selected particle's decay chain will also be created in the datastore and mother-daughter relations are recursively set",
70  false);
71 
72  addParam("skipNonPrimaryDaughters", m_skipNonPrimaryDaughters,
73  "If true, the secondary MC daughters will be skipped, default is false",
74  false);
75 
76  addParam("trackHypothesis", m_trackHypothesis,
77  "Track hypothesis to use when loading the particle. By default, use the particle's own hypothesis.",
78  0);
79 
80  addParam("enforceFitHypothesis", m_enforceFitHypothesis,
81  "If true, a Particle is only created if a track fit with the particle hypothesis passed to the ParticleLoader is available.",
83 
84  addParam("useDummy", m_useDummy,
85  "Use Dummy instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)", false);
86 
87  addParam("dummyMDSTIndex", m_dummyMDSTIndex,
88  "mdst index to use for dummy particle", 0);
89 
90  addParam("dummyCovMatrix", m_dummyCovMatrix,
91  "Diagonal value of covariance matrix to use for dummy particle", 10000.);
92 
93  addParam("dummyTreatAsInvisible", m_dummyTreatAsInvisible,
94  "Should treeFitter treat the particle as invisible?", true);
95 
96 }
97 
99 {
100  B2INFO("ParticleLoader's Summary of Actions:");
101 
102  m_particles.registerInDataStore();
103  m_particleExtraInfoMap.registerInDataStore();
104  m_eventExtraInfo.registerInDataStore();
105  //register relations if these things exists
106  if (m_mcparticles.isOptional()) {
107  m_particles.registerRelationTo(m_mcparticles);
108  }
109  if (m_pidlikelihoods.isOptional()) {
110  m_particles.registerRelationTo(m_pidlikelihoods);
111  }
112  if (m_trackfitresults.isOptional()) {
113  m_particles.registerRelationTo(m_trackfitresults);
114  }
115 
116  if (m_useMCParticles) {
117  m_mcparticles.isRequired();
118  }
119 
120  if (m_useROEs) {
121  m_roes.isRequired();
122  m_roes.registerRelationTo(m_particles);
123 
124  StoreArray<RestOfEvent> nestedRoes("NestedRestOfEvents");
125  if (nestedRoes.isOptional())
126  nestedRoes.registerRelationTo(m_particles);
127  }
128 
129  if (m_decayStrings.empty()) {
130  B2WARNING("Obsolete usage of the ParticleLoader module (load all MDST objects as all possible Particle object types). Specify the particle type via decayStrings module parameter instead.");
131  } else {
132  for (auto decayString : m_decayStrings) {
133 
134  // obtain the output particle lists from the decay string
135  bool valid = m_decaydescriptor.init(decayString);
136  if (!valid)
137  B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString: " << decayString);
138 
139  // Mother particle
141  int nProducts = m_decaydescriptor.getNDaughters();
142 
143  int pdgCode = mother->getPDGCode();
144  // The default list name is "all"
145  string listName = mother->getName() + ":all";
146  // ROE particles get the full name
147  if (m_useROEs) listName = mother->getFullName();
148  // dummy particles get the full name
149  else if (m_useDummy) listName = mother->getFullName();
150  // MC particles get the full name
151  else if (m_useMCParticles) listName = mother->getFullName();
152  // V0s get the label "V0"
153  else if (nProducts > 0) listName = mother->getName() + ":V0";
154 
155  string antiListName = ParticleListName::antiParticleListName(listName);
156  bool isSelfConjugatedParticle = (listName == antiListName);
157 
158  StoreObjPtr<ParticleList> particleList(listName);
159  // if the particle list doesn't exist, we have to register it
160  if (!particleList.isOptional()) {
162  particleList.registerInDataStore(flags);
163  if (!isSelfConjugatedParticle) {
164  StoreObjPtr<ParticleList> antiParticleList(antiListName);
165  antiParticleList.registerInDataStore(flags);
166  }
167  } else if (m_useMCParticles) {
168  B2WARNING("ParticleList " << listName << " already exists and will not be created again. " <<
169  "The given options (addDaughters, skipNonPrimaryDaughters, skipNonPrimary) do not applied on the existing list.");
170  }
171 
172  if (not isValidPDGCode(pdgCode) and (m_useMCParticles == false and m_useROEs == false and m_useDummy == false))
173  B2ERROR("Invalid particle type requested to be loaded. Set a valid decayString module parameter.");
174 
175  // if we're not loading MCParticles and we are loading K0S, Lambdas, or photons --> ee then this decaystring is a V0
176  bool mdstSourceIsV0 = false;
177  if (!m_useMCParticles &&
178  (abs(pdgCode) == abs(Const::Kshort.getPDGCode()) || abs(pdgCode) == abs(Const::Lambda.getPDGCode())
179  || (abs(pdgCode) == abs(Const::photon.getPDGCode()) && m_addDaughters == true)))
180  mdstSourceIsV0 = true;
181 
182  if (mdstSourceIsV0 == false) {
183  if (nProducts > 0) {
184  if (!m_useROEs and !m_useDummy) {
185  B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString " << decayString
186  << ". DecayString should not contain any daughters, only the mother particle.");
187  } else {
188  B2INFO("ParticleLoaderModule: Replacing the source particle list name by " <<
190  << " all other daughters will be ignored.");
192  }
193  }
194  } else {
195  if (nProducts != 2)
196  B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString " << decayString
197  << ". MDST source of the particle list is V0, DecayString should contain exactly two daughters, as well as the mother particle.");
198  else {
200  B2ERROR("MDST source of the particle list is V0, the two daughters should have opposite charge");
201  }
202  }
203 
204  // add PList to corresponding collection of Lists
205  B2INFO(" o) creating (anti-)ParticleList with name: " << listName << " (" << antiListName << ")");
206  if (m_useROEs) {
207  B2INFO(" -> MDST source: RestOfEvents");
208  m_ROE2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
209  } else if (m_useDummy) {
210  B2INFO(" -> MDST source: No MDST source");
211  m_Dummies2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
212  } else if (m_useMCParticles) {
213  B2INFO(" -> MDST source: MCParticles");
214  m_MCParticles2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
215  } else {
216  bool chargedFSP = Const::chargedStableSet.contains(Const::ParticleType(abs(pdgCode)));
217  if (chargedFSP) {
218  B2INFO(" -> MDST source: Tracks");
219  m_Tracks2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
220  }
221 
222  if (abs(pdgCode) == abs(Const::photon.getPDGCode())) {
223  if (m_addDaughters == false) {
224  m_ECLKLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
225  B2INFO(" -> MDST source: ECLClusters and KLMClusters");
226  } else {
227  B2INFO(" -> MDST source: V0");
228  m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
229  }
230  }
231 
232  if (abs(pdgCode) == abs(Const::Kshort.getPDGCode())) {
233  B2INFO(" -> MDST source: V0");
234  m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
235  }
236 
237  if (abs(pdgCode) == abs(Const::Klong.getPDGCode()) || abs(pdgCode) == abs(Const::neutron.getPDGCode())) {
238  B2INFO(" -> MDST source: exclusively KLMClusters or exclusively ECLClusters (matching between those not used)");
239  m_ECLKLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
240  }
241 
242  if (abs(pdgCode) == abs(Const::Lambda.getPDGCode())) {
243  B2INFO(" -> MDST source: V0");
244  m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
245  }
246  }
247  }
248  }
249 
250 
251  m_chargeZeroTrackCounts = std::vector<int>(m_Tracks2Plists.size(), 0);
252  m_sameChargeDaughtersV0Counts = std::vector<int>(m_V02Plists.size(), 0);
253 }
254 
256 {
257  if (not m_particleExtraInfoMap) {
258  m_particleExtraInfoMap.create();
259  }
260 
261  if (m_useROEs)
262  roeToParticles();
263  else if (m_useDummy)
265  else if (m_useMCParticles)
267  else {
270  v0sToParticles();
271  }
272 }
273 
275 {
276  // report track errors integrated
277  for (size_t i = 0; i < m_Tracks2Plists.size(); i++)
278  if (m_chargeZeroTrackCounts[i] > 0) {
279  auto track2Plist = m_Tracks2Plists[i];
280  B2WARNING("There were " << m_chargeZeroTrackCounts[i]
281  << " tracks skipped because of zero charge for "
282  << get<c_PListName>(track2Plist));
283  }
284  // report V0 errors integrated
285  for (size_t i = 0; i < m_V02Plists.size(); i++)
286  if (m_sameChargeDaughtersV0Counts[i] > 0) {
287  auto v02Plist = m_V02Plists[i];
288  B2WARNING("There were " << m_sameChargeDaughtersV0Counts[i]
289  << " v0s skipped because of same charge daughters for "
290  << get<c_PListName>(v02Plist));
291  }
292 }
293 
294 
296 {
297  if (m_Dummies2Plists.empty()) // nothing to do
298  return;
299  if (m_Dummies2Plists.size() != 1)
300  B2ERROR("ParticleLoaderModule::dummyToParticles Multiple particle lists are not supported!");
301  auto dummy2Plist = m_Dummies2Plists[0];
302  string dummyListName = get<c_PListName>(dummy2Plist);
303  string antiDummyListName = get<c_AntiPListName>(dummy2Plist);
304  int pdgCode = get<c_PListPDGCode>(dummy2Plist);
305  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(dummy2Plist);
306 
307  StoreObjPtr<ParticleList> plist(dummyListName);
308  plist.create();
309  plist->initialize(pdgCode, dummyListName);
310 
311  if (!isSelfConjugatedParticle) {
312  StoreObjPtr<ParticleList> antiPlist(antiDummyListName);
313  antiPlist.create();
314  antiPlist->initialize(-1 * pdgCode, antiDummyListName);
315  antiPlist->bindAntiParticleList(*(plist));
316  }
317 
318  TMatrixFSym covariance(7);
319  for (int row = 0; row < 7; ++row) { //diag
320  covariance(row, row) = m_dummyCovMatrix;
321  }
322 
323  Particle* newPart = nullptr;
324  Particle* newAntiPart = nullptr;
325 
326  auto isFlavored = (isSelfConjugatedParticle) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
327 
328  ROOT::Math::PxPyPzEVector zero4Vector = {0., 0., 0., 0.};
329 
330  newPart = m_particles.appendNew(zero4Vector, pdgCode, isFlavored, Particle::EParticleSourceObject::c_NoMDSTSource,
332  if (m_dummyCovMatrix > 0.) newPart->setMomentumVertexErrorMatrix(covariance);
333  if (m_dummyTreatAsInvisible) newPart->writeExtraInfo("treeFitterTreatMeAsInvisible", 1);
334  plist->addParticle(newPart);
335 
336  if (!isSelfConjugatedParticle) {
337  newAntiPart = m_particles.appendNew(zero4Vector, -pdgCode, isFlavored, Particle::EParticleSourceObject::c_NoMDSTSource,
339  if (m_dummyCovMatrix > 0.) newAntiPart->setMomentumVertexErrorMatrix(covariance);
340  if (m_dummyTreatAsInvisible) newAntiPart->writeExtraInfo("treeFitterTreatMeAsInvisible", 1);
341  plist->addParticle(newAntiPart);
342  }
343 
344 }
345 
346 
348 {
349  if (m_ROE2Plists.empty()) // nothing to do
350  return;
351  // Multiple particle lists are not supported
352  auto roe2Plist = m_ROE2Plists[0];
353  string listName = get<c_PListName>(roe2Plist);
354  string antiListName = get<c_AntiPListName>(roe2Plist);
355  int pdgCode = get<c_PListPDGCode>(roe2Plist);
356  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(roe2Plist);
357 
358  StoreObjPtr<ParticleList> plist(listName);
359  // since a particle list in the ParticleLoader always contains all possible objects
360  // we check whether it already exists in this path and can skip any further steps if it does
361  if (plist.isValid())
362  return;
363  plist.create();
364  plist->initialize(pdgCode, listName);
365 
366  if (!isSelfConjugatedParticle) {
367  StoreObjPtr<ParticleList> antiPlist(antiListName);
368  antiPlist.create();
369  antiPlist->initialize(-1 * pdgCode, antiListName);
370  antiPlist->bindAntiParticleList(*(plist));
371  }
372  if (m_sourceParticleListName != "") {
373  // Take related ROEs from a particle list
375  if (!pList.isValid())
376  B2FATAL("ParticleList " << m_sourceParticleListName << " could not be found or is not valid!");
377 
378  for (unsigned int i = 0; i < pList->getListSize(); i++) {
379  RestOfEvent* roe = pList->getParticle(i)->getRelatedTo<RestOfEvent>("ALL");
380  if (!roe) {
381  B2ERROR("ParticleList " << m_sourceParticleListName << " has no associated ROEs!");
382  } else {
383 
384  if (isSelfConjugatedParticle)
385  addROEToParticleList(roe, i, pdgCode, isSelfConjugatedParticle);
386  else if (i < pList->getListSize(false))
387  addROEToParticleList(roe, i, pdgCode, isSelfConjugatedParticle);
388  else
389  addROEToParticleList(roe, i, -1 * pdgCode, isSelfConjugatedParticle);
390  }
391  }
392 
393  } else {
394  // Take all ROE if no particle list provided
395  for (int i = 0; i < m_roes.getEntries(); i++) {
397  }
398  }
399 }
400 
401 void ParticleLoaderModule::addROEToParticleList(RestOfEvent* roe, int mdstIndex, int pdgCode, bool isSelfConjugatedParticle)
402 {
403 
404  Particle* newPart = nullptr;
405  if (!m_useMissing) {
406  // Convert ROE to particle
407  newPart = roe->convertToParticle(m_roeMaskName, pdgCode, isSelfConjugatedParticle);
408  } else {
409  // Create a particle from missing momentum
410  auto* signalSideParticle = roe->getRelatedFrom<Particle>();
412  ROOT::Math::PxPyPzEVector boost4Vector = T.getBeamFourMomentum();
413 
414  ROOT::Math::PxPyPzEVector signal4Vector = signalSideParticle->get4Vector();
415  ROOT::Math::PxPyPzEVector roe4Vector = roe->get4Vector(m_roeMaskName);
416  ROOT::Math::PxPyPzEVector missing4Vector = boost4Vector - signal4Vector - roe4Vector;
417  auto isFlavored = (isSelfConjugatedParticle) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
418  newPart = m_particles.appendNew(missing4Vector, pdgCode, isFlavored, Particle::EParticleSourceObject::c_Undefined, mdstIndex);
419  }
420 
421  roe->addRelationTo(newPart);
422 
423  for (auto roe2Plist : m_ROE2Plists) {
424  string listName = get<c_PListName>(roe2Plist);
425  StoreObjPtr<ParticleList> plist(listName);
426  plist->addParticle(newPart);
427  }
428 }
429 
430 
432 {
433  if (m_V02Plists.empty()) // nothing to do
434  return;
435 
436  // check if the order of the daughters in the decay string (decided by the user) is the same as the v0 daughters' order (fixed)
437  bool matchingDaughtersOrder = true;
440  matchingDaughtersOrder = false;
441 
442  // loop over all ParticleLists
443  for (size_t ilist = 0; ilist < m_V02Plists.size(); ilist++) {
444  auto v02Plist = m_V02Plists[ilist];
445  string listName = get<c_PListName>(v02Plist);
446  string antiListName = get<c_AntiPListName>(v02Plist);
447  int pdgCode = get<c_PListPDGCode>(v02Plist);
448  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(v02Plist);
449 
450  StoreObjPtr<ParticleList> plist(listName);
451  // since a particle list in the ParticleLoader always contains all possible objects
452  // we check whether it already exists in this path and can skip any further steps if it does
453  if (plist.isValid())
454  continue;
455  plist.create();
456  plist->initialize(pdgCode, listName);
457 
458  if (!isSelfConjugatedParticle) {
459  StoreObjPtr<ParticleList> antiPlist(antiListName);
460  antiPlist.create();
461  antiPlist->initialize(-1 * pdgCode, antiListName);
462 
463  antiPlist->bindAntiParticleList(*(plist));
464  }
465 
466  plist->setEditable(true); // :V0 list is originally reserved. we have to set it as editable.
467 
468  // load reconstructed V0s as Kshorts (pi-pi+ combination), Lambdas (p+pi- combinations), and converted photons (e-e+ combinations)
469  for (int i = 0; i < m_v0s.getEntries(); i++) {
470  const V0* v0 = m_v0s[i];
471  Const::ParticleType v0Type = v0->getV0Hypothesis();
472 
473  if (abs(pdgCode) != abs(v0Type.getPDGCode()))
474  continue;
475 
476  // check if the charge of the 2 V0's daughters is opposite
477  if (v0->getTrackFitResults().first->getChargeSign() == v0->getTrackFitResults().second->getChargeSign()) {
478  B2DEBUG(19, "V0 with same charge daughters skipped!");
480  continue;
481  }
482 
486 
487  if (v0Type.getPDGCode() == Const::Kshort.getPDGCode()) { // K0s -> pi+ pi-
488  pTypeP = Const::pion;
489  pTypeM = Const::pion;
490  } else if (v0Type.getPDGCode() == Const::Lambda.getPDGCode()) { // Lambda -> p+ pi-
491  pTypeP = Const::proton;
492  pTypeM = Const::pion;
493  v0FlavorType = Particle::c_Flavored; // K0s are not flavoured, lambdas are
494  } else if (v0Type.getPDGCode() == Const::antiLambda.getPDGCode()) { // anti-Lambda -> pi+ anti-p-
495  pTypeP = Const::pion;
496  pTypeM = Const::proton;
497  v0FlavorType = Particle::c_Flavored;
498  } else if (v0Type.getPDGCode() == Const::photon.getPDGCode()) { // gamma -> e+ e-
499  pTypeP = Const::electron;
500  pTypeM = Const::electron;
501  } else {
502  B2WARNING("Unknown V0 hypothesis!");
503  }
504 
505  // check if, given the initial user's decay descriptor, the current v0 is a particle or an anti-particle.
506  // in the V0 the order of the daughters is fixed, first the positive and then the negative; to be coherent with the decay descriptor, when creating
507  // one particle list and one anti-particle, the v0 daughters' order has to be switched only in one case
508  bool correctOrder = matchingDaughtersOrder;
509  if (abs(v0Type.getPDGCode()) == abs(m_decaydescriptor.getMother()->getPDGCode())
510  && v0Type.getPDGCode() != m_decaydescriptor.getMother()->getPDGCode())
511  correctOrder = !correctOrder;
512 
513  std::pair<Track*, Track*> v0Tracks = v0->getTracks();
514  std::pair<TrackFitResult*, TrackFitResult*> v0TrackFitResults = v0->getTrackFitResults();
515 
516  Particle daugP((v0Tracks.first)->getArrayIndex(), v0TrackFitResults.first, pTypeP);
517  Particle daugM((v0Tracks.second)->getArrayIndex(), v0TrackFitResults.second, pTypeM);
518 
519  const PIDLikelihood* pidP = (v0Tracks.first)->getRelated<PIDLikelihood>();
520  const PIDLikelihood* pidM = (v0Tracks.second)->getRelated<PIDLikelihood>();
521 
522  const auto& mcParticlePWithWeight = (v0Tracks.first)->getRelatedToWithWeight<MCParticle>();
523  const auto& mcParticleMWithWeight = (v0Tracks.second)->getRelatedToWithWeight<MCParticle>();
524 
525  // add V0 daughters to the Particle StoreArray
526  Particle* newDaugP;
527  Particle* newDaugM;
528 
529  if (correctOrder) {
530  newDaugP = m_particles.appendNew(daugP);
531  newDaugM = m_particles.appendNew(daugM);
532  } else {
533  newDaugM = m_particles.appendNew(daugM);
534  newDaugP = m_particles.appendNew(daugP);
535  }
536 
537  // if there are PIDLikelihoods and MCParticles then also add relations to the particles
538  if (pidP)
539  newDaugP->addRelationTo(pidP);
540  if (mcParticlePWithWeight.first)
541  newDaugP->addRelationTo(mcParticlePWithWeight.first, mcParticlePWithWeight.second);
542  newDaugP->addRelationTo(v0TrackFitResults.first);
543 
544  if (pidM)
545  newDaugM->addRelationTo(pidM);
546  if (mcParticleMWithWeight.first)
547  newDaugM->addRelationTo(mcParticleMWithWeight.first, mcParticleMWithWeight.second);
548  newDaugM->addRelationTo(v0TrackFitResults.second);
549 
550  // sum the 4-momenta of the daughters and construct a particle object
551  ROOT::Math::PxPyPzEVector v0Momentum = newDaugP->get4Vector() + newDaugM->get4Vector();
552  Particle v0P(v0Momentum, v0Type.getPDGCode(), v0FlavorType,
553  Particle::EParticleSourceObject::c_V0, v0->getArrayIndex());
554 
555  // add the daughters of the V0 (in the correct order) and don't update
556  // the type to c_Composite (i.e. maintain c_V0)
557  if (correctOrder) {
558  v0P.appendDaughter(newDaugP, false);
559  v0P.appendDaughter(newDaugM, false);
560  } else {
561  v0P.appendDaughter(newDaugM, false);
562  v0P.appendDaughter(newDaugP, false);
563  }
564 
565  // append the particle to the Particle StoreArray and add the new particle to the ParticleList
566  Particle* newPart = m_particles.appendNew(v0P);
567  plist->addParticle(newPart);
568  }
569 
570  plist->setEditable(false); // set the :V0 list as not editable.
571  }
572 }
573 
575 {
576  if (m_Tracks2Plists.empty()) // nothing to do
577  return;
578 
579  // loop over all requested particle lists
580  for (size_t ilist = 0; ilist < m_Tracks2Plists.size(); ilist++) {
581  auto track2Plist = m_Tracks2Plists[ilist];
582  string listName = get<c_PListName>(track2Plist);
583  string antiListName = get<c_AntiPListName>(track2Plist);
584  int pdgCode = get<c_PListPDGCode>(track2Plist);
585  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(track2Plist);
586 
587  StoreObjPtr<ParticleList> plist(listName);
588  // since a particle list in the ParticleLoader always contains all possible objects
589  // we check whether it already exists in this path and can skip any further steps if it does
590  if (plist.isValid())
591  continue;
592  plist.create();
593  plist->initialize(pdgCode, listName);
594 
595  // if cc exists then also create and bind that list
596  if (!isSelfConjugatedParticle) {
597  StoreObjPtr<ParticleList> antiPlist(antiListName);
598  antiPlist.create();
599  antiPlist->initialize(-1 * pdgCode, antiListName);
600 
601  antiPlist->bindAntiParticleList(*(plist));
602  }
603 
604  plist->setEditable(true); // :all list is originally reserved. we have to set it as editable.
605 
606  // the inner loop over all tracks from which Particles
607  // are created, and get sorted in the particle lists
608  for (int i = 0; i < m_tracks.getEntries(); i++) {
609  const Track* track = m_tracks[i];
610  const PIDLikelihood* pid = track->getRelated<PIDLikelihood>();
611  const auto& mcParticleWithWeight = track->getRelatedToWithWeight<MCParticle>();
612 
613  // if a special track hypothesis is requested, use it
614  if (m_trackHypothesis != 0) pdgCode = m_trackHypothesis;
615  Const::ChargedStable type(abs(pdgCode));
616 
617  // load the TrackFitResult for the requested particle or if not available use
618  // the one with the closest mass
619  const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(type);
620 
621  if (!trackFit) { // should never happen with the "closest mass" getter - leave as a sanity check
622  B2WARNING("Track returned null TrackFitResult pointer for ChargedStable::getPDGCode() = " << type.getPDGCode());
623  continue;
624  }
625 
626  if (m_enforceFitHypothesis && (trackFit->getParticleType().getPDGCode() != type.getPDGCode())) {
627  // the required hypothesis does not exist for this track, skip it
628  continue;
629  }
630 
631  // charge zero tracks can appear, filter them and
632  // count number of tracks filtered out
633  int charge = trackFit->getChargeSign();
634  if (charge == 0) {
635  B2DEBUG(19, "Track with charge = 0 skipped!");
636  m_chargeZeroTrackCounts[ilist]++;
637  continue;
638  }
639 
640  // create particle and add it to the Particle list.
641  Particle particle(track->getArrayIndex(), trackFit, type);
642 
643  if (particle.getParticleSource() == Particle::c_Track) { // should always hold but...
644 
645  Particle* newPart = m_particles.appendNew(particle);
646  if (pid)
647  newPart->addRelationTo(pid);
648  if (mcParticleWithWeight.first)
649  newPart->addRelationTo(mcParticleWithWeight.first, mcParticleWithWeight.second);
650  newPart->addRelationTo(trackFit);
651 
652  plist->addParticle(newPart);
653 
654  } // sanity check correct particle type
655  } // loop over tracks
656 
657  plist->setEditable(false); // set the :all list as not editable.
658  } // particle lists
659 }
660 
662 {
663  if (m_ECLKLMClusters2Plists.empty()) // nothing to do
664  return;
665 
666  // loop over all ParticleLists
667  for (auto eclKLMCluster2Plist : m_ECLKLMClusters2Plists) {
668  string listName = get<c_PListName>(eclKLMCluster2Plist);
669  string antiListName = get<c_AntiPListName>(eclKLMCluster2Plist);
670  int pdgCode = get<c_PListPDGCode>(eclKLMCluster2Plist);
671  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(eclKLMCluster2Plist);
672 
673  StoreObjPtr<ParticleList> plist(listName);
674  // since a particle list in the ParticleLoader always contains all possible objects
675  // we check whether it already exists in this path and can skip any further steps if it does
676  if (plist.isValid())
677  continue;
678  plist.create();
679  plist->initialize(pdgCode, listName);
680 
681  // create anti-particle list if necessary
682  if (!isSelfConjugatedParticle) {
683  StoreObjPtr<ParticleList> antiPlist(antiListName);
684  antiPlist.create();
685  antiPlist->initialize(-1 * pdgCode, antiListName);
686 
687  antiPlist->bindAntiParticleList(*(plist));
688  }
689 
690  plist->setEditable(true); // :all list is originally reserved. we have to set it as editable.
691 
692  // load reconstructed neutral ECL clusters as photons or Klongs or neutrons
693  for (int i = 0; i < m_eclclusters.getEntries(); i++) {
694  const ECLCluster* cluster = m_eclclusters[i];
695 
696  // ECLClusters can be reconstructed under different hypotheses, for
697  // example photons or neutral hadrons, we only load particles from these
698  // for now
699  if (!cluster->isNeutral()) continue;
700  if (not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)
701  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
702  continue;
703 
704  // ECLCluster can be matched to multiple MCParticles
705  // order the relations by weights and set Particle -> multiple MCParticle relation
706  // preserve the weight
707  RelationVector<MCParticle> mcRelations = cluster->getRelationsTo<MCParticle>();
708  // order relations by weights
709  std::vector<std::pair<int, double>> weightsAndIndices;
710  for (unsigned int iMCParticle = 0; iMCParticle < mcRelations.size(); iMCParticle++) {
711  const MCParticle* relMCParticle = mcRelations[iMCParticle];
712  double weight = mcRelations.weight(iMCParticle);
713  if (relMCParticle)
714  weightsAndIndices.emplace_back(relMCParticle->getArrayIndex(), weight);
715  }
716  // sort descending by weight
717  std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
718  [](const std::pair<int, double>& left, const std::pair<int, double>& right) {
719  return left.second > right.second;
720  });
721 
722  Const::ParticleType thisType(pdgCode);
723 
724  // don't fill photon list with clusters that don't have
725  // the nPhotons hypothesis (ECL people call this N1)
726  if (pdgCode == Const::photon.getPDGCode()
727  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
728  continue;
729 
730  // don't fill a KLong list with clusters that don't have the neutral
731  // hadron hypothesis set (ECL people call this N2)
732  if (pdgCode == Const::Klong.getPDGCode()
733  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
734  continue;
735 
736  // don't fill a neutron list with clusters that don't have the neutral
737  // hadron hypothesis set (ECL people call this N2)
738  if (abs(pdgCode) == Const::neutron.getPDGCode()
739  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
740  continue;
741 
742  // create particle and check it before adding to list
743  Particle particle(cluster, thisType);
744  if (particle.getParticleSource() != Particle::c_ECLCluster) {
745  B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
746  continue;
747  }
748  Particle* newPart = m_particles.appendNew(particle);
749 
750  // set relations to mcparticles
751  for (auto& weightsAndIndex : weightsAndIndices) {
752  const MCParticle* relMCParticle = m_mcparticles[weightsAndIndex.first];
753  double weight = weightsAndIndex.second;
754 
755  // TODO: study this further and avoid hard-coded values
756  // set the relation only if the MCParticle(reconstructed Particle)'s
757  // energy contribution to this cluster amounts to at least 30(20)%
758  if (relMCParticle)
759  if (weight / newPart->getECLClusterEnergy() > 0.20
760  && weight / relMCParticle->getEnergy() > 0.30)
761  newPart->addRelationTo(relMCParticle, weight);
762  }
763 
764  // add particle to list
765  plist->addParticle(newPart);
766  }
767 
768  // load reconstructed KLM clusters as Klongs or neutrons or photons
769  for (int i = 0; i < m_klmclusters.getEntries(); i++) {
770  const KLMCluster* cluster = m_klmclusters[i];
771 
772  if (std::isnan(cluster->getMomentumMag())) {
773  B2DEBUG(19, "Skipping KLMCluster because its momentum is NaN. "
774  "This can happen if the timing calibration is missing or wrong, so that the velocity is calculated to be negative.");
775  continue;
776  }
777 
778  const MCParticle* mcParticle = cluster->getRelated<MCParticle>();
779 
780  // create particle and check its type before adding it to list
781  Particle particle(cluster, pdgCode);
782  if (particle.getParticleSource() != Particle::c_KLMCluster) {
783  B2FATAL("Particle created from KLMCluster does not have KLMCluster type.");
784  }
785  Particle* newPart = m_particles.appendNew(particle);
786 
787  if (mcParticle)
788  newPart->addRelationTo(mcParticle);
789 
790  // add particle to list
791  plist->addParticle(newPart);
792  }
793 
794  plist->setEditable(false); // set the :all list as not editable.
795  } // loop over particle lists
796 }
797 
799 {
800  if (m_MCParticles2Plists.empty()) // nothing to do
801  return;
802 
803  // create all lists
804  for (auto mcParticle2Plist : m_MCParticles2Plists) {
805  string listName = get<c_PListName>(mcParticle2Plist);
806  string antiListName = get<c_AntiPListName>(mcParticle2Plist);
807  int pdgCode = get<c_PListPDGCode>(mcParticle2Plist);
808  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(mcParticle2Plist);
809 
810  StoreObjPtr<ParticleList> plist(listName);
811  if (plist.isValid())
812  continue;
813  plist.create();
814  plist->initialize(pdgCode, listName);
815 
816  if (!isSelfConjugatedParticle) {
817  StoreObjPtr<ParticleList> antiPlist(antiListName);
818  antiPlist.create();
819  antiPlist->initialize(-1 * pdgCode, antiListName);
820 
821  antiPlist->bindAntiParticleList(*(plist));
822  }
823 
824  for (int i = 0; i < m_mcparticles.getEntries(); i++) {
825  const MCParticle* mcParticle = m_mcparticles[i];
826 
827  if (abs(pdgCode) != abs(mcParticle->getPDG()))
828  continue;
829 
831  continue;
832 
833  Particle particle(mcParticle);
834  Particle* newPart = m_particles.appendNew(particle);
835  newPart->addRelationTo(mcParticle);
836 
837  //append the whole bottom part of the decay tree to this particle
839 
840  plist->addParticle(newPart);
841  }
842 
843  }
844 }
845 
847 {
848  bool result = false;
849 
850  // is particle type = charged final state particle?
851  if (Const::chargedStableSet.find(abs(pdgCode)) != Const::invalidParticle)
852  return true;
853 
854  if (abs(pdgCode) == abs(Const::photon.getPDGCode()))
855  return true;
856 
857  if (abs(pdgCode) == abs(Const::Kshort.getPDGCode()))
858  return true;
859 
860  if (abs(pdgCode) == abs(Const::Klong.getPDGCode()))
861  return true;
862 
863  if (abs(pdgCode) == abs(Const::Lambda.getPDGCode()))
864  return true;
865 
866  if (abs(pdgCode) == abs(Const::neutron.getPDGCode()))
867  return true;
868 
869  return result;
870 }
871 
873 {
874  auto* mcmother = mother->getRelated<MCParticle>();
875 
876  if (!mcmother)
877  return;
878 
879  vector<MCParticle*> mcdaughters = mcmother->getDaughters();
880 
881  for (auto& mcdaughter : mcdaughters) {
882  if (!mcdaughter->hasStatus(MCParticle::c_PrimaryParticle) and m_skipNonPrimaryDaughters) continue;
883  Particle particle(mcdaughter);
884  Particle* daughter = m_particles.appendNew(particle);
885  daughter->addRelationTo(mcdaughter);
886  mother->appendDaughter(daughter, false);
887 
888  if (mcdaughter->getNDaughters() > 0)
889  appendDaughtersRecursive(daughter);
890  }
891 }
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:580
bool contains(const ParticleType &p) const
Returns true if and only if the set contains 'p'.
Definition: UnitConst.cc:423
The ParticleType class for identifying different particle types.
Definition: Const.h:399
int getPDGCode() const
PDG code.
Definition: Const.h:464
static const ParticleType neutron
neutron particle
Definition: Const.h:666
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:669
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:609
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:668
static const ParticleType antiLambda
Anti-Lambda particle.
Definition: Const.h:670
static const ChargedStable proton
proton particle
Definition: Const.h:654
static const ParticleType invalidParticle
Invalid particle, used internally.
Definition: Const.h:671
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:667
static const ParticleType photon
photon particle
Definition: Const.h:664
static const ChargedStable electron
electron particle
Definition: Const.h:650
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.
int getPDGCode() const
Return PDG code.
std::string getFullName() const
returns the full name of the particle full_name = name:label
std::string getName() const
evt.pdl name of the particle.
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.
const DecayDescriptor * getDaughter(int i) const
return i-th daughter (0 based index).
ECL cluster data.
Definition: ECLCluster.h:27
@ c_nPhotons
CR is split into n photons (N1)
@ c_neutralHadron
CR is reconstructed as a neutral hadron (N2)
KLM cluster data.
Definition: KLMCluster.h:28
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
float getEnergy() const
Return particle energy in GeV.
Definition: MCParticle.h:147
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
Definition: MCParticle.cc:52
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
Definition: MCParticle.h:129
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:244
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
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-.
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
Definition: PIDLikelihood.h:26
std::vector< PList > m_ECLKLMClusters2Plists
Collection of PLists that will collect Particles created from ECLClusters and KLMClusters.
void mcParticlesToParticles()
Loads specified MCParticles as Particle to StoreArray<Particle>
void v0sToParticles()
Loads V0 object as Particle of specified type to StoreArray<Particle> and adds it to the ParticleList...
StoreArray< TrackFitResult > m_trackfitresults
StoreArray of TrackFitResults.
std::vector< PList > m_Dummies2Plists
Collection of PLists that will collect Particles created from Dummies.
std::vector< std::string > m_decayStrings
Input decay strings specifying the particles being created/loaded.
void roeToParticles()
Loads ROE object as Particle of specified type to StoreArray<Particle> and adds it to the ParticleLis...
bool m_dummyTreatAsInvisible
should treeFitter treat the particle as invisible?
virtual void initialize() override
Initialize the Module.
int m_trackHypothesis
pdg code for track hypothesis that should be used to create the particle
StoreArray< KLMCluster > m_klmclusters
StoreArray of KLMCluster.
std::vector< int > m_sameChargeDaughtersV0Counts
internally used to count the number of V0s with same charge daughters
StoreArray< V0 > m_v0s
StoreArray of V0s.
void addROEToParticleList(RestOfEvent *roe, int mdstIndex, int pdgCode=0, bool isSelfConjugatedParticle=true)
Helper method to load ROE object as Particle.
virtual void event() override
Event processor.
std::string m_sourceParticleListName
Particle list name from which we need to get related ROEs.
bool isValidPDGCode(const int pdgCode)
returns true if the PDG code determined from the decayString is valid
StoreArray< MCParticle > m_mcparticles
StoreArray of MCParticles.
StoreArray< Particle > m_particles
StoreArray of Particles.
int m_dummyMDSTIndex
mdst index for dummy particles
std::string m_roeMaskName
ROE mask name to load.
virtual void terminate() override
Terminate the Module.
void tracksToParticles()
Loads Track object as Particle to StoreArray<Particle> and adds it to the ParticleList.
StoreObjPtr< ParticleExtraInfoMap > m_particleExtraInfoMap
object pointer to extra info map
double m_dummyCovMatrix
diag value of cov matrix for dummy particles
bool m_addDaughters
toggle addition of the bottom part of the particle's decay chain
StoreArray< PIDLikelihood > m_pidlikelihoods
StoreArray of PIDLikelihoods.
bool m_skipNonPrimaryDaughters
toggle skip of secondary MC daughters
StoreArray< Track > m_tracks
StoreArray of Tracks.
bool m_enforceFitHypothesis
If true, a Particle is only created if a track fit with the particle hypothesis passed to the Particl...
std::vector< PList > m_ROE2Plists
Collection of PLists that will collect Particles created from V0.
StoreArray< RestOfEvent > m_roes
StoreArray of ROEs.
void appendDaughtersRecursive(Particle *mother)
recursively append bottom of a particle's decay chain (daughters of mother, granddaughters of daughte...
std::vector< PList > m_MCParticles2Plists
Collection of PLists that will collect Particles created from MCParticles.
void dummyToParticles()
Loads dummy object as Particle of specified type to StoreArray<Particle> and adds it to the ParticleL...
std::vector< PList > m_V02Plists
Collection of PLists that will collect Particles created from V0.
DecayDescriptor m_decaydescriptor
Decay descriptor for parsing the user specified DecayString.
bool m_useDummy
Switch to load dummy as Particle.
bool m_writeOut
toggle particle list btw.
std::vector< int > m_chargeZeroTrackCounts
internally used to count number of tracks with charge zero
std::vector< PList > m_Tracks2Plists
Collection of PLists that will collect Particles created from Tracks.
StoreObjPtr< EventExtraInfo > m_eventExtraInfo
object pointer to event extra info
StoreArray< ECLCluster > m_eclclusters
StoreArray of ECLCluster.
bool m_skipNonPrimary
toggle skip of secondary MC particle
bool m_useROEs
Switch to load ROE as Particle.
bool m_useMissing
Use missing momentum to build a particle.
void eclAndKLMClustersToParticles()
Loads ECLCluster and KLMCluster object as Particle to StoreArray<Particle> and adds it to the Particl...
bool m_useMCParticles
Load MCParticle as Particle instead of the corresponding MDST dataobject.
Class to store reconstructed particles.
Definition: Particle.h:74
void appendDaughter(const Particle *daughter, const bool updateType=true, const int daughterProperty=c_Ordinary)
Appends index of daughter to daughters index array.
Definition: Particle.cc:708
void writeExtraInfo(const std::string &name, const double value)
Sets the user defined extraInfo.
Definition: Particle.cc:1335
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:532
void setMomentumVertexErrorMatrix(const TMatrixFSym &errMatrix)
Sets 7x7 error matrix.
Definition: Particle.cc:425
EParticleSourceObject getParticleSource() const
Returns particle source as defined with enum EParticleSourceObject.
Definition: Particle.h:465
EFlavorType
describes flavor type, see getFlavorType().
Definition: Particle.h:93
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:94
@ c_Flavored
Is either particle or antiparticle.
Definition: Particle.h:95
double getECLClusterEnergy() const
Returns the energy of the ECLCluster for the particle.
Definition: Particle.cc:949
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
float weight(int index) const
Get weight with index.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
This is a general purpose class for collecting reconstructed MDST data objects that are not used in r...
Definition: RestOfEvent.h:57
ROOT::Math::PxPyPzEVector get4Vector(const std::string &maskName=c_defaultMaskName) const
Get 4-momentum vector all (no mask) or a subset (use mask) of all Tracks and ECLClusters in ROE.
Definition: RestOfEvent.cc:306
static constexpr const char * c_defaultMaskName
Default mask name.
Definition: RestOfEvent.h:60
Particle * convertToParticle(const std::string &maskName=c_defaultMaskName, int pdgCode=0, bool isSelfConjugated=true)
Converts ROE to Particle and adds it to StoreArray.
Definition: RestOfEvent.cc:443
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool create(bool replace=false)
Create a default object in the data store.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:110
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
Const::ParticleType getParticleType() const
Getter for ParticleType of the mass hypothesis of the track fit.
Class that bundles various TrackFitResults.
Definition: Track.h:25
Object holding information for V0s.
Definition: V0.h:30
std::pair< TrackFitResult *, TrackFitResult * > getTrackFitResults() const
Get pair of the TrackFitResults, that are part of the V0 particle.
Definition: V0.h:53
std::pair< Track *, Track * > getTracks() const
Get pair of yhe Tracks, that are part of the V0 particle.
Definition: V0.h:40
Const::ParticleType getV0Hypothesis() const
Get the hypothesis under which the V0 particle was created.
Definition: V0.cc:28
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
std::string antiParticleListName(const std::string &listName)
Returns name of anti-particle-list corresponding to listName.
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23