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