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