Belle II Software  light-2303-iriomote
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 header.
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 #include <analysis/utility/ValueIndexPairSorting.h>
20 
21 #include <utility>
22 
23 using namespace std;
24 using namespace Belle2;
25 
26 //-----------------------------------------------------------------
27 // Register module
28 //-----------------------------------------------------------------
29 
30 REG_MODULE(ParticleLoader);
31 
32 //-----------------------------------------------------------------
33 // Implementation
34 //-----------------------------------------------------------------
35 
36 ParticleLoaderModule::ParticleLoaderModule() : Module()
37 
38 {
39  setDescription("Loads MDST dataobjects as Particle objects to the StoreArray<Particle> and collects them in specified ParticleList.");
41 
42  // Add parameters
43  addParam("decayStrings", m_decayStrings,
44  "List of decay strings (see :ref:`DecayString` for syntax) that specify all output ParticleLists to be created by the module.",
45  {});
46 
47  addParam("useMCParticles", m_useMCParticles,
48  "Use MCParticles instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)", false);
49 
50  addParam("useROEs", m_useROEs,
51  "Use ROE instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)", false);
52 
53  addParam("roeMaskName", m_roeMaskName,
54  "ROE mask name to load", std::string(RestOfEvent::c_defaultMaskName));
55 
56  addParam("sourceParticleListName", m_sourceParticleListName,
57  "Particle list name from which we need to get ROEs", std::string(""));
58 
59  addParam("useMissing", m_useMissing,
60  "If true, the Particle List will be filled with missing momentum from the ROE and signal particle.", false);
61 
62  addParam("writeOut", m_writeOut,
63  "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.", false);
64 
65  addParam("skipNonPrimary", m_skipNonPrimary,
66  "If true, the secondary MC particle will be skipped, default is false",
67  false);
68 
69  addParam("addDaughters", m_addDaughters,
70  "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",
71  false);
72 
73  addParam("skipNonPrimaryDaughters", m_skipNonPrimaryDaughters,
74  "If true, the secondary MC daughters will be skipped, default is false",
75  false);
76 
77  addParam("trackHypothesis", m_trackHypothesis,
78  "Track hypothesis to use when loading the particle. By default, use the particle's own hypothesis.",
79  0);
80 
81  addParam("enforceFitHypothesis", m_enforceFitHypothesis,
82  "If true, a Particle is only created if a track fit with the particle hypothesis passed to the ParticleLoader is available.",
84 
85  addParam("useDummy", m_useDummy,
86  "Use Dummy instead of reconstructed MDST dataobjects (tracks, ECL, KLM, clusters, V0s, ...)", false);
87 
88  addParam("dummyMDSTIndex", m_dummyMDSTIndex,
89  "mdst index to use for dummy particle", 0);
90 
91  addParam("dummyCovMatrix", m_dummyCovMatrix,
92  "Diagonal value of covariance matrix to use for dummy particle", 10000.);
93 
94  addParam("dummyTreatAsInvisible", m_dummyTreatAsInvisible,
95  "Should treeFitter treat the particle as invisible?", true);
96 
97  addParam("loadChargedCluster", m_loadChargedCluster,
98  "Load neutral Particles from the clusters being matched with the track of the sourceParticleList",
99  false);
100  addParam("useOnlyMostEnergeticECLCluster", m_useOnlyMostEnergeticECLCluster,
101  "If true, the most energetic ECLCluster among ones matching with the Track is used. "
102  "If false, all matched ECLCluster are used. "
103  "This option is checked only when loadChargedCluster=True.",
104  true);
105 }
106 
107 
109 {
110  B2INFO("ParticleLoader's Summary of Actions:");
111 
112  if ((int)m_useMCParticles + (int)m_useROEs + (int)m_useDummy + (int)m_loadChargedCluster > 1)
113  B2FATAL("The options on how to load the Particle are not valid. The incompatible combination of options is selected. "
114  << "useMCParticles: " << m_useMCParticles << ", useROEs: " << m_useROEs << ", useDummy: " << m_useDummy
115  << ", loadChargedCluster: " << m_loadChargedCluster);
116 
117  m_particles.registerInDataStore();
118  m_particleExtraInfoMap.registerInDataStore();
119  m_eventExtraInfo.registerInDataStore();
120  //register relations if these things exists
121  if (m_mcparticles.isOptional()) {
122  m_particles.registerRelationTo(m_mcparticles);
123  }
124  if (m_pidlikelihoods.isOptional()) {
125  m_particles.registerRelationTo(m_pidlikelihoods);
126  }
127  if (m_trackfitresults.isOptional()) {
128  m_particles.registerRelationTo(m_trackfitresults);
129  }
130 
131  if (m_useMCParticles) {
132  m_mcparticles.isRequired();
133  }
134 
135  if (m_useROEs) {
136  m_roes.isRequired();
137  m_roes.registerRelationTo(m_particles);
138 
139  StoreArray<RestOfEvent> nestedRoes("NestedRestOfEvents");
140  if (nestedRoes.isOptional())
141  nestedRoes.registerRelationTo(m_particles);
142  }
143 
144  if (m_decayStrings.empty()) {
145  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.");
146  } else {
147  for (auto decayString : m_decayStrings) {
148 
149  // obtain the output particle lists from the decay string
150  const bool valid = m_decaydescriptor.init(decayString);
151  if (!valid)
152  B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString: " << decayString);
153 
154  // Mother particle
156  int nProducts = m_decaydescriptor.getNDaughters();
157 
158  int pdgCode = mother->getPDGCode();
159  // The default list name is "all"
160  string listName = mother->getName() + ":all";
161 
162  // Full name for ROE, dummy, MCParticle, chargedCluster particles
164  listName = mother->getFullName();
165  // V0s get the label "V0"
166  else if (nProducts > 0)
167  listName = mother->getName() + ":V0";
168 
169  string antiListName = ParticleListName::antiParticleListName(listName);
170  bool isSelfConjugatedParticle = (listName == antiListName);
171 
172  StoreObjPtr<ParticleList> particleList(listName);
173  // if the particle list doesn't exist, we have to register it
174  if (!particleList.isOptional()) {
176  particleList.registerInDataStore(flags);
177  if (!isSelfConjugatedParticle) {
178  StoreObjPtr<ParticleList> antiParticleList(antiListName);
179  antiParticleList.registerInDataStore(flags);
180  }
181  } else if (m_useMCParticles) {
182  B2WARNING("ParticleList " << listName << " already exists and will not be created again. " <<
183  "Please note that the given options (addDaughters, skipNonPrimaryDaughters, skipNonPrimary) do not apply to "
184  << listName);
185  } else if (m_loadChargedCluster) {
186  B2WARNING("ParticleList " << listName << " already exists and will not be created again. " <<
187  "Please note that the given option, useOnlyMostEnergeticECLCluster, does not apply to "
188  << listName);
189  }
190 
191  if (not isValidPDGCode(pdgCode) and (m_useMCParticles == false and m_useROEs == false and m_useDummy == false))
192  B2ERROR("Invalid particle type requested to be loaded. Set a valid decayString module parameter.");
193 
194  // if we're not loading MCParticles and we are loading K0S, Lambdas, or photons --> ee then this decaystring is a V0
195  bool mdstSourceIsV0 = false;
196  if (!m_useMCParticles &&
197  (abs(pdgCode) == abs(Const::Kshort.getPDGCode()) || abs(pdgCode) == abs(Const::Lambda.getPDGCode())
198  || (abs(pdgCode) == abs(Const::photon.getPDGCode()) && m_addDaughters == true)))
199  mdstSourceIsV0 = true;
200 
201  if (mdstSourceIsV0) {
202  if (nProducts == 2) {
203  m_properties = m_decaydescriptor.getProperty() | mother->getProperty(); // only used for V0s
205  B2ERROR("MDST source of the particle list is V0, the two daughters should have opposite charge");
206  } else {
207  B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString " << decayString
208  << ". MDST source of the particle list is V0, DecayString should contain exactly two daughters, as well as the mother particle.");
209  }
210  } else {
211  if (nProducts > 0) {
212  if (m_useROEs or m_useDummy) {
213  B2INFO("ParticleLoaderModule: Replacing the source particle list name by " <<
215  << " all other daughters will be ignored.");
217  } else {
218  B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString " << decayString
219  << ". DecayString should not contain any daughters, only the mother particle.");
220  }
221  }
222  }
223 
225  B2ERROR("The sourceParticleListName is not given. The charged ParticleList is required for the chargedCluster loading.");
226 
227  // add PList to corresponding collection of Lists
228  B2INFO(" o) creating (anti-)ParticleList with name: " << listName << " (" << antiListName << ")");
229  if (m_useROEs) {
230  B2INFO(" -> MDST source: RestOfEvents");
231  m_ROE2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
232  } else if (m_useDummy) {
233  B2INFO(" -> MDST source: No MDST source");
234  m_Dummies2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
235  } else if (m_useMCParticles) {
236  B2INFO(" -> MDST source: MCParticles");
237  m_MCParticles2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
238  } else if (m_loadChargedCluster) {
239  if (abs(pdgCode) == abs(Const::photon.getPDGCode()) || abs(pdgCode) == abs(Const::Klong.getPDGCode())
240  || abs(pdgCode) == abs(Const::neutron.getPDGCode())) {
241  m_ChargedCluster2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
242  B2INFO(" -> MDST source: ECLClusters and KLMClusters being matched with Tracks");
243  } else {
244  B2ERROR("The Particle type must be gamma, K_L0, or (anti-)n0 for the loadChargedCluster option.");
245  }
246  } else {
247  bool chargedFSP = Const::chargedStableSet.contains(Const::ParticleType(abs(pdgCode)));
248  if (chargedFSP) {
249  B2INFO(" -> MDST source: Tracks");
250  m_Tracks2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
251  }
252 
253  if (abs(pdgCode) == abs(Const::photon.getPDGCode())) {
254  if (m_addDaughters == false) {
255  m_ECLKLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
256  B2INFO(" -> MDST source: ECLClusters and KLMClusters");
257  } else {
258  B2INFO(" -> MDST source: V0");
259  m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
260  }
261  }
262 
263  if (abs(pdgCode) == abs(Const::Kshort.getPDGCode())) {
264  B2INFO(" -> MDST source: V0");
265  m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
266  }
267 
268  if (abs(pdgCode) == abs(Const::Klong.getPDGCode()) || abs(pdgCode) == abs(Const::neutron.getPDGCode())) {
269  B2INFO(" -> MDST source: exclusively KLMClusters or exclusively ECLClusters (matching between those not used)");
270  m_ECLKLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
271  }
272 
273  if (abs(pdgCode) == abs(Const::Lambda.getPDGCode())) {
274  B2INFO(" -> MDST source: V0");
275  m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
276  }
277  }
278  }
279  }
280 
281 
282  m_chargeZeroTrackCounts = std::vector<int>(m_Tracks2Plists.size(), 0);
283  m_sameChargeDaughtersV0Counts = std::vector<int>(m_V02Plists.size(), 0);
284 }
285 
287 {
288  if (not m_particleExtraInfoMap) {
289  m_particleExtraInfoMap.create();
290  }
291 
292  if (m_useROEs)
293  roeToParticles();
294  else if (m_useDummy)
296  else if (m_useMCParticles)
298  else if (m_loadChargedCluster)
300  else {
303  v0sToParticles();
304  }
305 }
306 
308 {
309  // report track errors integrated
310  for (size_t i = 0; i < m_Tracks2Plists.size(); i++)
311  if (m_chargeZeroTrackCounts[i] > 0) {
312  auto track2Plist = m_Tracks2Plists[i];
313  B2WARNING("There were " << m_chargeZeroTrackCounts[i]
314  << " tracks skipped because of zero charge for "
315  << get<c_PListName>(track2Plist));
316  }
317  // report V0 errors integrated
318  for (size_t i = 0; i < m_V02Plists.size(); i++)
319  if (m_sameChargeDaughtersV0Counts[i] > 0) {
320  auto v02Plist = m_V02Plists[i];
321  B2WARNING("There were " << m_sameChargeDaughtersV0Counts[i]
322  << " v0s skipped because of same charge daughters for "
323  << get<c_PListName>(v02Plist));
324  }
325 }
326 
327 
329 {
330  if (m_Dummies2Plists.empty()) // nothing to do
331  return;
332  if (m_Dummies2Plists.size() != 1)
333  B2ERROR("ParticleLoaderModule::dummyToParticles Multiple particle lists are not supported!");
334  auto dummy2Plist = m_Dummies2Plists[0];
335  string dummyListName = get<c_PListName>(dummy2Plist);
336  string antiDummyListName = get<c_AntiPListName>(dummy2Plist);
337  int pdgCode = get<c_PListPDGCode>(dummy2Plist);
338  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(dummy2Plist);
339 
340  StoreObjPtr<ParticleList> plist(dummyListName);
341  plist.create();
342  plist->initialize(pdgCode, dummyListName);
343 
344  if (!isSelfConjugatedParticle) {
345  StoreObjPtr<ParticleList> antiPlist(antiDummyListName);
346  antiPlist.create();
347  antiPlist->initialize(-1 * pdgCode, antiDummyListName);
348  antiPlist->bindAntiParticleList(*(plist));
349  }
350 
351  TMatrixFSym covariance(7);
352  for (int row = 0; row < 7; ++row) { //diag
353  covariance(row, row) = m_dummyCovMatrix;
354  }
355 
356  Particle* newPart = nullptr;
357  Particle* newAntiPart = nullptr;
358 
359  auto isFlavored = (isSelfConjugatedParticle) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
360 
361  ROOT::Math::PxPyPzEVector zero4Vector = {0., 0., 0., 0.};
362 
363  newPart = m_particles.appendNew(zero4Vector, pdgCode, isFlavored, Particle::EParticleSourceObject::c_NoMDSTSource,
365  if (m_dummyCovMatrix > 0.) newPart->setMomentumVertexErrorMatrix(covariance);
366  if (m_dummyTreatAsInvisible) newPart->writeExtraInfo("treeFitterTreatMeAsInvisible", 1);
367  plist->addParticle(newPart);
368 
369  if (!isSelfConjugatedParticle) {
370  newAntiPart = m_particles.appendNew(zero4Vector, -pdgCode, isFlavored, Particle::EParticleSourceObject::c_NoMDSTSource,
372  if (m_dummyCovMatrix > 0.) newAntiPart->setMomentumVertexErrorMatrix(covariance);
373  if (m_dummyTreatAsInvisible) newAntiPart->writeExtraInfo("treeFitterTreatMeAsInvisible", 1);
374  plist->addParticle(newAntiPart);
375  }
376 
377 }
378 
379 
381 {
382  if (m_ROE2Plists.empty()) // nothing to do
383  return;
384  // Multiple particle lists are not supported
385  auto roe2Plist = m_ROE2Plists[0];
386  string listName = get<c_PListName>(roe2Plist);
387  string antiListName = get<c_AntiPListName>(roe2Plist);
388  int pdgCode = get<c_PListPDGCode>(roe2Plist);
389  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(roe2Plist);
390 
391  StoreObjPtr<ParticleList> plist(listName);
392  // since a particle list in the ParticleLoader always contains all possible objects
393  // we check whether it already exists in this path and can skip any further steps if it does
394  if (plist.isValid())
395  return;
396  plist.create();
397  plist->initialize(pdgCode, listName);
398 
399  if (!isSelfConjugatedParticle) {
400  StoreObjPtr<ParticleList> antiPlist(antiListName);
401  antiPlist.create();
402  antiPlist->initialize(-1 * pdgCode, antiListName);
403  antiPlist->bindAntiParticleList(*(plist));
404  }
405  if (m_sourceParticleListName != "") {
406  // Take related ROEs from a particle list
408  if (!pList.isValid())
409  B2FATAL("ParticleList " << m_sourceParticleListName << " could not be found or is not valid!");
410 
411  for (unsigned int i = 0; i < pList->getListSize(); i++) {
412  RestOfEvent* roe = pList->getParticle(i)->getRelatedTo<RestOfEvent>("ALL");
413  if (!roe) {
414  B2ERROR("ParticleList " << m_sourceParticleListName << " has no associated ROEs!");
415  } else {
416 
417  if (isSelfConjugatedParticle)
418  addROEToParticleList(roe, i, pdgCode, isSelfConjugatedParticle);
419  else if (i < pList->getListSize(false))
420  addROEToParticleList(roe, i, pdgCode, isSelfConjugatedParticle);
421  else
422  addROEToParticleList(roe, i, -1 * pdgCode, isSelfConjugatedParticle);
423  }
424  }
425 
426  } else {
427  // Take all ROE if no particle list provided
428  for (int i = 0; i < m_roes.getEntries(); i++) {
430  }
431  }
432 }
433 
434 void ParticleLoaderModule::addROEToParticleList(RestOfEvent* roe, int mdstIndex, int pdgCode, bool isSelfConjugatedParticle)
435 {
436 
437  Particle* newPart = nullptr;
438  if (!m_useMissing) {
439  // Convert ROE to particle
440  newPart = roe->convertToParticle(m_roeMaskName, pdgCode, isSelfConjugatedParticle);
441  } else {
442  // Create a particle from missing momentum
443  auto* signalSideParticle = roe->getRelatedFrom<Particle>();
445  ROOT::Math::PxPyPzEVector boost4Vector = T.getBeamFourMomentum();
446 
447  ROOT::Math::PxPyPzEVector signal4Vector = signalSideParticle->get4Vector();
448  ROOT::Math::PxPyPzEVector roe4Vector = roe->get4Vector(m_roeMaskName);
449  ROOT::Math::PxPyPzEVector missing4Vector = boost4Vector - signal4Vector - roe4Vector;
450  auto isFlavored = (isSelfConjugatedParticle) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
451  newPart = m_particles.appendNew(missing4Vector, pdgCode, isFlavored, Particle::EParticleSourceObject::c_Undefined, mdstIndex);
452  }
453 
454  roe->addRelationTo(newPart);
455 
456  for (auto roe2Plist : m_ROE2Plists) {
457  string listName = get<c_PListName>(roe2Plist);
458  StoreObjPtr<ParticleList> plist(listName);
459  plist->addParticle(newPart);
460  }
461 }
462 
463 
465 {
466  if (m_V02Plists.empty()) // nothing to do
467  return;
468 
469  // check if the order of the daughters in the decay string (decided by the user) is the same as the v0 daughters' order (fixed)
470  bool matchingDaughtersOrder = true;
473  matchingDaughtersOrder = false;
474 
475  // loop over all ParticleLists
476  for (size_t ilist = 0; ilist < m_V02Plists.size(); ilist++) {
477  auto v02Plist = m_V02Plists[ilist];
478  string listName = get<c_PListName>(v02Plist);
479  string antiListName = get<c_AntiPListName>(v02Plist);
480  int pdgCode = get<c_PListPDGCode>(v02Plist);
481  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(v02Plist);
482 
483  StoreObjPtr<ParticleList> plist(listName);
484  // since a particle list in the ParticleLoader always contains all possible objects
485  // we check whether it already exists in this path and can skip any further steps if it does
486  if (plist.isValid())
487  continue;
488  plist.create();
489  plist->initialize(pdgCode, listName);
490 
491  if (!isSelfConjugatedParticle) {
492  StoreObjPtr<ParticleList> antiPlist(antiListName);
493  antiPlist.create();
494  antiPlist->initialize(-1 * pdgCode, antiListName);
495 
496  antiPlist->bindAntiParticleList(*(plist));
497  }
498 
499  plist->setEditable(true); // :V0 list is originally reserved. we have to set it as editable.
500 
501  // load reconstructed V0s as Kshorts (pi-pi+ combination), Lambdas (p+pi- combinations), and converted photons (e-e+ combinations)
502  for (int i = 0; i < m_v0s.getEntries(); i++) {
503  const V0* v0 = m_v0s[i];
504  Const::ParticleType v0Type = v0->getV0Hypothesis();
505 
506  if (abs(pdgCode) != abs(v0Type.getPDGCode()))
507  continue;
508 
509  // check if the charge of the 2 V0's daughters is opposite
510  if (v0->getTrackFitResults().first->getChargeSign() == v0->getTrackFitResults().second->getChargeSign()) {
511  B2DEBUG(19, "V0 with same charge daughters skipped!");
513  continue;
514  }
515 
519 
520  if (v0Type.getPDGCode() == Const::Kshort.getPDGCode()) { // K0s -> pi+ pi-
521  pTypeP = Const::pion;
522  pTypeM = Const::pion;
523  } else if (v0Type.getPDGCode() == Const::Lambda.getPDGCode()) { // Lambda -> p+ pi-
524  pTypeP = Const::proton;
525  pTypeM = Const::pion;
526  v0FlavorType = Particle::c_Flavored; // K0s are not flavoured, lambdas are
527  } else if (v0Type.getPDGCode() == Const::antiLambda.getPDGCode()) { // anti-Lambda -> pi+ anti-p-
528  pTypeP = Const::pion;
529  pTypeM = Const::proton;
530  v0FlavorType = Particle::c_Flavored;
531  } else if (v0Type.getPDGCode() == Const::photon.getPDGCode()) { // gamma -> e+ e-
532  pTypeP = Const::electron;
533  pTypeM = Const::electron;
534  } else {
535  B2WARNING("Unknown V0 hypothesis!");
536  }
537 
538  // check if, given the initial user's decay descriptor, the current v0 is a particle or an anti-particle.
539  // 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
540  // one particle list and one anti-particle, the v0 daughters' order has to be switched only in one case
541  bool correctOrder = matchingDaughtersOrder;
542  if (abs(v0Type.getPDGCode()) == abs(m_decaydescriptor.getMother()->getPDGCode())
543  && v0Type.getPDGCode() != m_decaydescriptor.getMother()->getPDGCode())
544  correctOrder = !correctOrder;
545 
546  std::pair<Track*, Track*> v0Tracks = v0->getTracks();
547  std::pair<TrackFitResult*, TrackFitResult*> v0TrackFitResults = v0->getTrackFitResults();
548 
549  Particle daugP((v0Tracks.first)->getArrayIndex(), v0TrackFitResults.first, pTypeP);
550  Particle daugM((v0Tracks.second)->getArrayIndex(), v0TrackFitResults.second, pTypeM);
551 
552  const PIDLikelihood* pidP = (v0Tracks.first)->getRelated<PIDLikelihood>();
553  const PIDLikelihood* pidM = (v0Tracks.second)->getRelated<PIDLikelihood>();
554 
555  const auto& mcParticlePWithWeight = (v0Tracks.first)->getRelatedToWithWeight<MCParticle>();
556  const auto& mcParticleMWithWeight = (v0Tracks.second)->getRelatedToWithWeight<MCParticle>();
557 
558  // add V0 daughters to the Particle StoreArray
559  Particle* newDaugP;
560  Particle* newDaugM;
561 
562  if (correctOrder) {
563  newDaugP = m_particles.appendNew(daugP);
564  newDaugM = m_particles.appendNew(daugM);
565  } else {
566  newDaugM = m_particles.appendNew(daugM);
567  newDaugP = m_particles.appendNew(daugP);
568  }
569 
570  // if there are PIDLikelihoods and MCParticles then also add relations to the particles
571  if (pidP)
572  newDaugP->addRelationTo(pidP);
573  if (mcParticlePWithWeight.first)
574  newDaugP->addRelationTo(mcParticlePWithWeight.first, mcParticlePWithWeight.second);
575  newDaugP->addRelationTo(v0TrackFitResults.first);
576 
577  if (pidM)
578  newDaugM->addRelationTo(pidM);
579  if (mcParticleMWithWeight.first)
580  newDaugM->addRelationTo(mcParticleMWithWeight.first, mcParticleMWithWeight.second);
581  newDaugM->addRelationTo(v0TrackFitResults.second);
582 
583  // sum the 4-momenta of the daughters and construct a particle object
584  ROOT::Math::PxPyPzEVector v0Momentum = newDaugP->get4Vector() + newDaugM->get4Vector();
585  Particle v0P(v0Momentum, v0Type.getPDGCode(), v0FlavorType,
586  Particle::EParticleSourceObject::c_V0, v0->getArrayIndex());
588 
589  // add the daughters of the V0 (in the correct order) and don't update
590  // the type to c_Composite (i.e. maintain c_V0)
591  if (correctOrder) {
592  v0P.appendDaughter(newDaugP, false);
593  v0P.appendDaughter(newDaugM, false);
594  } else {
595  v0P.appendDaughter(newDaugM, false);
596  v0P.appendDaughter(newDaugP, false);
597  }
598 
599  // append the particle to the Particle StoreArray and add the new particle to the ParticleList
600  Particle* newPart = m_particles.appendNew(v0P);
601  plist->addParticle(newPart);
602  }
603 
604  plist->setEditable(false); // set the :V0 list as not editable.
605  }
606 }
607 
609 {
610  if (m_Tracks2Plists.empty()) // nothing to do
611  return;
612 
613  // loop over all requested particle lists
614  for (size_t ilist = 0; ilist < m_Tracks2Plists.size(); ilist++) {
615  auto track2Plist = m_Tracks2Plists[ilist];
616  string listName = get<c_PListName>(track2Plist);
617  string antiListName = get<c_AntiPListName>(track2Plist);
618  int pdgCode = get<c_PListPDGCode>(track2Plist);
619  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(track2Plist);
620 
621  StoreObjPtr<ParticleList> plist(listName);
622  // since a particle list in the ParticleLoader always contains all possible objects
623  // we check whether it already exists in this path and can skip any further steps if it does
624  if (plist.isValid())
625  continue;
626  plist.create();
627  plist->initialize(pdgCode, listName);
628 
629  // if cc exists then also create and bind that list
630  if (!isSelfConjugatedParticle) {
631  StoreObjPtr<ParticleList> antiPlist(antiListName);
632  antiPlist.create();
633  antiPlist->initialize(-1 * pdgCode, antiListName);
634 
635  antiPlist->bindAntiParticleList(*(plist));
636  }
637 
638  plist->setEditable(true); // :all list is originally reserved. we have to set it as editable.
639 
640  // the inner loop over all tracks from which Particles
641  // are created, and get sorted in the particle lists
642  for (int i = 0; i < m_tracks.getEntries(); i++) {
643  const Track* track = m_tracks[i];
644  const PIDLikelihood* pid = track->getRelated<PIDLikelihood>();
645  const auto& mcParticleWithWeight = track->getRelatedToWithWeight<MCParticle>();
646 
647  // if a special track hypothesis is requested, use it
648  if (m_trackHypothesis != 0) pdgCode = m_trackHypothesis;
649  Const::ChargedStable type(abs(pdgCode));
650 
651  // load the TrackFitResult for the requested particle or if not available use
652  // the one with the closest mass
653  const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(type);
654 
655  if (!trackFit) { // should never happen with the "closest mass" getter - leave as a sanity check
656  B2WARNING("Track returned null TrackFitResult pointer for ChargedStable::getPDGCode() = " << type.getPDGCode());
657  continue;
658  }
659 
660  if (m_enforceFitHypothesis && (trackFit->getParticleType().getPDGCode() != type.getPDGCode())) {
661  // the required hypothesis does not exist for this track, skip it
662  continue;
663  }
664 
665  // charge zero tracks can appear, filter them and
666  // count number of tracks filtered out
667  int charge = trackFit->getChargeSign();
668  if (charge == 0) {
669  B2DEBUG(19, "Track with charge = 0 skipped!");
670  m_chargeZeroTrackCounts[ilist]++;
671  continue;
672  }
673 
674  // create particle and add it to the Particle list.
675  Particle particle(track->getArrayIndex(), trackFit, type);
676 
677  if (particle.getParticleSource() == Particle::c_Track) { // should always hold but...
678 
679  Particle* newPart = m_particles.appendNew(particle);
680  if (pid)
681  newPart->addRelationTo(pid);
682  if (mcParticleWithWeight.first)
683  newPart->addRelationTo(mcParticleWithWeight.first, mcParticleWithWeight.second);
684  newPart->addRelationTo(trackFit);
685 
686  plist->addParticle(newPart);
687 
688  } // sanity check correct particle type
689  } // loop over tracks
690 
691  plist->setEditable(false); // set the :all list as not editable.
692  } // particle lists
693 }
694 
696 {
697  if (m_ECLKLMClusters2Plists.empty()) // nothing to do
698  return;
699 
700  // loop over all ParticleLists
701  for (auto eclKLMCluster2Plist : m_ECLKLMClusters2Plists) {
702  string listName = get<c_PListName>(eclKLMCluster2Plist);
703  string antiListName = get<c_AntiPListName>(eclKLMCluster2Plist);
704  int pdgCode = get<c_PListPDGCode>(eclKLMCluster2Plist);
705  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(eclKLMCluster2Plist);
706  Const::ParticleType thisType(pdgCode);
707 
708  StoreObjPtr<ParticleList> plist(listName);
709  // since a particle list in the ParticleLoader always contains all possible objects
710  // we check whether it already exists in this path and can skip any further steps if it does
711  if (plist.isValid())
712  continue;
713  plist.create();
714  plist->initialize(pdgCode, listName);
715 
716  // create anti-particle list if necessary
717  if (!isSelfConjugatedParticle) {
718  StoreObjPtr<ParticleList> antiPlist(antiListName);
719  antiPlist.create();
720  antiPlist->initialize(-1 * pdgCode, antiListName);
721 
722  antiPlist->bindAntiParticleList(*(plist));
723  }
724 
725  plist->setEditable(true); // :all list is originally reserved. we have to set it as editable.
726 
727  // load reconstructed neutral ECL clusters as photons or Klongs or neutrons
728  for (int i = 0; i < m_eclclusters.getEntries(); i++) {
729  const ECLCluster* cluster = m_eclclusters[i];
730 
731  if (!isValidECLCluster(cluster, pdgCode, true))
732  continue;
733 
734  // create particle and check it before adding to list
735  Particle particle(cluster, thisType);
736  if (particle.getParticleSource() != Particle::c_ECLCluster) {
737  B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
738  continue;
739  }
740  Particle* newPart = m_particles.appendNew(particle);
741 
742  assignMCParticleFromECLCluster(newPart, cluster);
743 
744  // add particle to list
745  plist->addParticle(newPart);
746  }
747 
748  // load reconstructed KLM clusters as Klongs or neutrons or photons
749  for (int i = 0; i < m_klmclusters.getEntries(); i++) {
750  const KLMCluster* cluster = m_klmclusters[i];
751 
752  if (std::isnan(cluster->getMomentumMag())) {
753  B2DEBUG(19, "Skipping KLMCluster because its momentum is NaN. "
754  "This can happen if the timing calibration is missing or wrong, so that the velocity is calculated to be negative.");
755  continue;
756  }
757 
758  const MCParticle* mcParticle = cluster->getRelated<MCParticle>();
759 
760  // create particle and check its type before adding it to list
761  Particle particle(cluster, pdgCode);
762  if (particle.getParticleSource() != Particle::c_KLMCluster) {
763  B2FATAL("Particle created from KLMCluster does not have KLMCluster type.");
764  }
765  Particle* newPart = m_particles.appendNew(particle);
766 
767  if (mcParticle)
768  newPart->addRelationTo(mcParticle);
769 
770  // add particle to list
771  plist->addParticle(newPart);
772  }
773 
774  plist->setEditable(false); // set the :all list as not editable.
775  } // loop over particle lists
776 }
777 
778 bool ParticleLoaderModule::isValidECLCluster(const ECLCluster* cluster, const int pdgCode, bool onlyNeutral) const
779 {
780  if (!cluster)
781  return false;
782 
783  // ECLClusters can be reconstructed under different hypotheses, for
784  // example photons or neutral hadrons, we only load particles from these
785  // for now
786  if (!cluster->isNeutral() and onlyNeutral)
787  return false;
788 
789  if (not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)
790  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
791  return false;
792 
793  // don't fill photon list with clusters that don't have
794  // the nPhotons hypothesis (ECL people call this N1)
795  if (pdgCode == Const::photon.getPDGCode()
796  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
797  return false;
798 
799  // don't fill a KLong nor a (anti-)neutron list with clusters that don't have the neutral
800  // hadron hypothesis set (ECL people call this N2)
801  if ((pdgCode == Const::Klong.getPDGCode() or abs(pdgCode) == Const::neutron.getPDGCode())
802  and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
803  return false;
804 
805  return true;
806 }
807 
809 {
810  // ECLCluster can be matched to multiple MCParticles
811  // order the relations by weights and set Particle -> multiple MCParticle relation
812  // preserve the weight
813  const RelationVector<MCParticle> mcRelations = cluster->getRelationsTo<MCParticle>();
814 
815  // order relations by weights
816  std::vector<std::pair<double, int>> weightsAndIndices;
817  for (unsigned int iMCParticle = 0; iMCParticle < mcRelations.size(); iMCParticle++) {
818  const MCParticle* relMCParticle = mcRelations[iMCParticle];
819  if (relMCParticle) {
820  double weight = mcRelations.weight(iMCParticle);
821  weightsAndIndices.emplace_back(weight, relMCParticle->getArrayIndex());
822  }
823  }
824 
825  // sort descending by weight
826  std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
827  ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
828 
829  // set relations to mcparticles
830  for (auto& weightsAndIndex : weightsAndIndices) {
831  const MCParticle* relMCParticle = m_mcparticles[weightsAndIndex.second];
832  double weight = weightsAndIndex.first;
833 
834  // TODO: study this further and avoid hard-coded values
835  // set the relation only if the MCParticle(reconstructed Particle)'s
836  // energy contribution to this cluster amounts to at least 30(20)%
837  if (relMCParticle)
838  if (weight / newPart->getECLClusterEnergy() > 0.20
839  && weight / relMCParticle->getEnergy() > 0.30)
840  newPart->addRelationTo(relMCParticle, weight);
841  }
842 
843 }
844 
846 {
847  if (m_ChargedCluster2Plists.empty()) // nothing to do
848  return;
849 
850  // loop over all ParticleLists
851  for (auto chargedCluster2Plist : m_ChargedCluster2Plists) {
852 
853  string listName = get<c_PListName>(chargedCluster2Plist);
854  string antiListName = get<c_AntiPListName>(chargedCluster2Plist);
855  int pdgCode = get<c_PListPDGCode>(chargedCluster2Plist);
856  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(chargedCluster2Plist);
857  Const::ParticleType thisType(pdgCode);
858 
859  StoreObjPtr<ParticleList> plist(listName);
860  // since a particle list in the ParticleLoader always contains all possible objects
861  // we check whether it already exists in this path and can skip any further steps if it does
862  if (plist.isValid())
863  continue;
864  plist.create();
865  plist->initialize(pdgCode, listName);
866 
867  // create anti-particle list if necessary
868  if (!isSelfConjugatedParticle) {
869  StoreObjPtr<ParticleList> antiPlist(antiListName);
870  antiPlist.create();
871  antiPlist->initialize(-1 * pdgCode, antiListName);
872 
873  antiPlist->bindAntiParticleList(*(plist));
874  }
875 
877  if (!sourceList.isValid())
878  B2FATAL("ParticleList " << m_sourceParticleListName << " could not be found or is not valid!");
879 
880  for (unsigned int iPart = 0; iPart < sourceList->getListSize(); iPart++) {
881 
882  const Particle* sourcePart = sourceList->getParticle(iPart);
883  const Track* sourceTrack = sourceList->getParticle(iPart)->getTrack();
884  if (!sourceTrack)
885  continue;
886 
887  // ECL clusters
889 
890  const ECLCluster* cluster = sourcePart->getECLCluster();
891  if (isValidECLCluster(cluster, pdgCode, false)) {
892  Particle particle(cluster, thisType);
893  if (particle.getParticleSource() != Particle::c_ECLCluster) {
894  B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
895  }
896  Particle* newPart = m_particles.appendNew(particle);
897  assignMCParticleFromECLCluster(newPart, cluster);
898  plist->addParticle(newPart);
899  }
900  } else {
901 
902  // loop over all clusters matched to this track
903  const RelationVector<ECLCluster> clusters = sourceTrack->getRelationsTo<ECLCluster>();
904  for (unsigned int iCluster = 0; iCluster < clusters.size(); iCluster++) {
905  const ECLCluster* cluster = clusters[iCluster];
906  if (!isValidECLCluster(cluster, pdgCode, false))
907  continue; // go to next iCluster
908 
909  Particle particle(cluster, thisType);
910  if (particle.getParticleSource() != Particle::c_ECLCluster) {
911  B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
912  }
913  Particle* newPart = m_particles.appendNew(particle);
914  assignMCParticleFromECLCluster(newPart, cluster);
915  plist->addParticle(newPart);
916  }
917  }
918 
919  // KLM clusters
920  const KLMCluster* cluster = sourcePart->getKLMCluster();
921  if (!cluster) continue; // go to next iPart
922 
923  if (std::isnan(cluster->getMomentumMag())) {
924  B2DEBUG(19, "Skipping KLMCluster because its momentum is NaN. "
925  "This can happen if the timing calibration is missing or wrong, so that the velocity is calculated to be negative.");
926  continue;
927  }
928 
929  // create particle and check its type before adding it to list
930  Particle particle(cluster, pdgCode);
931  if (particle.getParticleSource() != Particle::c_KLMCluster) {
932  B2FATAL("Particle created from KLMCluster does not have KLMCluster type.");
933  }
934  Particle* newPart = m_particles.appendNew(particle);
935 
936  const MCParticle* mcParticle = cluster->getRelated<MCParticle>();
937  if (mcParticle) newPart->addRelationTo(mcParticle);
938 
939  plist->addParticle(newPart);
940  }
941 
942  } // loop over particle lists
943 }
944 
946 {
947  if (m_MCParticles2Plists.empty()) // nothing to do
948  return;
949 
950  // create all lists
951  for (auto mcParticle2Plist : m_MCParticles2Plists) {
952  string listName = get<c_PListName>(mcParticle2Plist);
953  string antiListName = get<c_AntiPListName>(mcParticle2Plist);
954  int pdgCode = get<c_PListPDGCode>(mcParticle2Plist);
955  bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(mcParticle2Plist);
956 
957  StoreObjPtr<ParticleList> plist(listName);
958  if (plist.isValid())
959  continue;
960  plist.create();
961  plist->initialize(pdgCode, listName);
962 
963  if (!isSelfConjugatedParticle) {
964  StoreObjPtr<ParticleList> antiPlist(antiListName);
965  antiPlist.create();
966  antiPlist->initialize(-1 * pdgCode, antiListName);
967 
968  antiPlist->bindAntiParticleList(*(plist));
969  }
970 
971  for (int i = 0; i < m_mcparticles.getEntries(); i++) {
972  const MCParticle* mcParticle = m_mcparticles[i];
973 
974  if (abs(pdgCode) != abs(mcParticle->getPDG()))
975  continue;
976 
978  continue;
979 
980  Particle particle(mcParticle);
981  Particle* newPart = m_particles.appendNew(particle);
982  newPart->addRelationTo(mcParticle);
983 
984  //append the whole bottom part of the decay tree to this particle
986 
987  plist->addParticle(newPart);
988  }
989 
990  }
991 }
992 
994 {
995  bool result = false;
996 
997  // is particle type = charged final state particle?
998  if (Const::chargedStableSet.find(abs(pdgCode)) != Const::invalidParticle)
999  return true;
1000 
1001  if (abs(pdgCode) == abs(Const::photon.getPDGCode()))
1002  return true;
1003 
1004  if (abs(pdgCode) == abs(Const::Kshort.getPDGCode()))
1005  return true;
1006 
1007  if (abs(pdgCode) == abs(Const::Klong.getPDGCode()))
1008  return true;
1009 
1010  if (abs(pdgCode) == abs(Const::Lambda.getPDGCode()))
1011  return true;
1012 
1013  if (abs(pdgCode) == abs(Const::neutron.getPDGCode()))
1014  return true;
1015 
1016  return result;
1017 }
1018 
1020 {
1021  auto* mcmother = mother->getRelated<MCParticle>();
1022 
1023  if (!mcmother)
1024  return;
1025 
1026  vector<MCParticle*> mcdaughters = mcmother->getDaughters();
1027 
1028  for (auto& mcdaughter : mcdaughters) {
1029  if (!mcdaughter->hasStatus(MCParticle::c_PrimaryParticle) and m_skipNonPrimaryDaughters) continue;
1030  Particle particle(mcdaughter);
1031  Particle* daughter = m_particles.appendNew(particle);
1032  daughter->addRelationTo(mcdaughter);
1033  mother->appendDaughter(daughter, false);
1034 
1035  if (mcdaughter->getNDaughters() > 0)
1036  appendDaughtersRecursive(daughter);
1037  }
1038 }
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:424
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:670
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:669
static const ParticleType antiLambda
Anti-Lambda particle.
Definition: Const.h:671
static const ChargedStable proton
proton particle
Definition: Const.h:654
static const ParticleType invalidParticle
Invalid particle, used internally.
Definition: Const.h:672
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:668
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.
int getProperty() const
return property 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.
int getProperty() const
return property of the particle.
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.
bool isValidECLCluster(const ECLCluster *cluster, const int pdgCode, bool onlyNeutral) const
Checks if the given ECLCluster is valid for the pdgCode.
std::vector< PList > m_ChargedCluster2Plists
Collection of PLists that will collect Particles created from charged-cluster.
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
bool m_useOnlyMostEnergeticECLCluster
If true, only the most energetic ECLCluster is used.
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
int m_properties
Particle property to be assigned only on V0s.
void chargedClustersToParticles()
Loads ECLCluster and KLMCluster objects that are being matched with Track as Particle to StoreArray<P...
void assignMCParticleFromECLCluster(Particle *newPart, const ECLCluster *cluster) const
Assigns the MCParticle relation to the newPart.
bool m_useROEs
Switch to load ROE as Particle.
bool m_loadChargedCluster
Switch to load charged-cluster
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 setProperty(const int properties)
sets m_properties
Definition: Particle.h:345
const KLMCluster * getKLMCluster() const
Returns the pointer to the KLMCluster object that was used to create this Particle (ParticleType == c...
Definition: Particle.cc:930
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:680
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
Definition: Particle.cc:895
void writeExtraInfo(const std::string &name, const double value)
Sets the user defined extraInfo.
Definition: Particle.cc:1309
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:516
void setMomentumVertexErrorMatrix(const TMatrixFSym &errMatrix)
Sets 7x7 error matrix.
Definition: Particle.cc:397
EParticleSourceObject getParticleSource() const
Returns particle source as defined with enum EParticleSourceObject.
Definition: Particle.h:449
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:923
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.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
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