Belle II Software development
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
23using namespace std;
24using namespace Belle2;
25
26//-----------------------------------------------------------------
27// Register module
28//-----------------------------------------------------------------
29
30REG_MODULE(ParticleLoader);
31
32//-----------------------------------------------------------------
33// Implementation
34//-----------------------------------------------------------------
35
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
121 m_particleExtraInfoMap.registerInDataStore();
122 m_eventExtraInfo.registerInDataStore();
123 //register relations if these things exists
126 }
127 if (m_pidlikelihoods.isOptional()) {
129 }
130 if (m_trackfitresults.isOptional()) {
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())
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)
297 else if (m_useDummy)
299 else if (m_useMCParticles)
301 else if (m_loadChargedCluster)
303 else {
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++)
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
437void 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];
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())
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!");
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
781bool 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:589
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:408
int getPDGCode() const
PDG code.
Definition: Const.h:473
static const ParticleType neutron
neutron particle
Definition: Const.h:675
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:679
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:618
static const ChargedStable pion
charged pion particle
Definition: Const.h:661
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:678
static const ParticleType antiLambda
Anti-Lambda particle.
Definition: Const.h:680
static const ChargedStable proton
proton particle
Definition: Const.h:663
static const ParticleType invalidParticle
Invalid particle, used internally.
Definition: Const.h:681
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:677
static const ParticleType photon
photon particle
Definition: Const.h:673
static const ChargedStable electron
electron particle
Definition: Const.h:659
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 DecayDescriptor * getDaughter(int i) const
return i-th daughter (0 based index).
int getNDaughters() const
return number of direct daughters.
int getProperty() const
return property of the particle.
const DecayDescriptorParticle * getMother() const
return mother.
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:29
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:374
const KLMCluster * getKLMCluster() const
Returns the pointer to the KLMCluster object that was used to create this Particle (ParticleType == c...
Definition: Particle.cc:926
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:676
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
Definition: Particle.cc:891
void writeExtraInfo(const std::string &name, const double value)
Sets the user defined extraInfo.
Definition: Particle.cc:1308
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:547
void setMomentumVertexErrorMatrix(const TMatrixFSym &errMatrix)
Sets 7x7 error matrix.
Definition: Particle.cc:393
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:919
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.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
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
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
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< Track *, Track * > getTracks() const
Get pair of yhe Tracks, that are part of the V0 particle.
Definition: V0.h:45
std::pair< TrackFitResult *, TrackFitResult * > getTrackFitResults() const
Get pair of the TrackFitResults, that are part of the V0 particle.
Definition: V0.h:58
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.
STL namespace.