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/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
122 m_particleExtraInfoMap.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, and (anti-)neutrons
166 if (m_useROEs or m_useDummy or m_useMCParticles or m_loadChargedCluster or abs(pdgCode) == abs(Const::neutron.getPDGCode()))
167 listName = mother->getFullName();
168 // Kinks get the label "kink"
169 else if (nProducts == 1)
170 listName = mother->getName() + ":kink";
171 // V0s get the label "V0"
172 else if (nProducts > 1)
173 listName = mother->getName() + ":V0";
174
175 string antiListName = ParticleListName::antiParticleListName(listName);
176 bool isSelfConjugatedParticle = (listName == antiListName);
177
178 StoreObjPtr<ParticleList> particleList(listName);
179 // if the particle list doesn't exist, we have to register it
180 if (!particleList.isOptional()) {
182 particleList.registerInDataStore(flags);
183 // Neutrons are not self-conjugated, but we cannot distinguish particle from anti-particle
184 if (!isSelfConjugatedParticle and (abs(pdgCode) != abs(Const::neutron.getPDGCode()) or m_useMCParticles)) {
185 StoreObjPtr<ParticleList> antiParticleList(antiListName);
186 antiParticleList.registerInDataStore(flags);
187 }
188 } else if (m_useMCParticles) {
189 B2WARNING("ParticleList " << listName << " already exists and will not be created again. " <<
190 "Please note that the given options (addDaughters, skipNonPrimaryDaughters, skipNonPrimary, skipInitial) do not apply to "
191 << listName);
192 } else if (m_loadChargedCluster) {
193 B2WARNING("ParticleList " << listName << " already exists and will not be created again. " <<
194 "Please note that the given option, useOnlyMostEnergeticECLCluster, does not apply to "
195 << listName);
196 }
197
198 if (not isValidPDGCode(pdgCode) and (m_useMCParticles == false and m_useROEs == false and m_useDummy == false))
199 B2ERROR("Invalid particle type requested to be loaded. Set a valid decayString module parameter.");
200
201 // if we're not loading MCParticles and we are loading K0S, Lambdas, or photons --> ee then this decaystring is a V0
202 bool mdstSourceIsV0 = false;
203 if (!m_useMCParticles &&
204 (abs(pdgCode) == abs(Const::Kshort.getPDGCode()) || abs(pdgCode) == abs(Const::Lambda.getPDGCode())
205 || (abs(pdgCode) == abs(Const::photon.getPDGCode()) && m_addDaughters == true)))
206 mdstSourceIsV0 = true;
207
208 // if we're not loading MCParticles, and we are loading kaon/pion/muon/charged sigmas with one daughter,
209 // then this decaystring is a kink
210 bool mdstSourceIsKink = false;
211 if (!m_useMCParticles && nProducts == 1 &&
212 (abs(pdgCode) == abs(Const::kaon.getPDGCode()) || abs(pdgCode) == abs(Const::pion.getPDGCode())
213 || abs(pdgCode) == abs(Const::muon.getPDGCode()) || abs(pdgCode) == abs(3222) || abs(pdgCode) == abs(3112)))
214 mdstSourceIsKink = true;
215
216 if (mdstSourceIsV0) {
217 if (nProducts == 2) {
218 m_properties = m_decaydescriptor.getProperty() | mother->getProperty(); // only used for V0s
220 B2ERROR("MDST source of the particle list is V0, the two daughters should have opposite charge");
221 } else {
222 B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString " << decayString
223 << ". MDST source of the particle list is V0, DecayString should contain exactly two daughters, as well as the mother particle.");
224 }
225 } else {
226 if (!mdstSourceIsKink && nProducts > 0) {
227 if (m_useROEs or m_useDummy) {
228 B2INFO("ParticleLoaderModule: Replacing the source particle list name by " <<
230 << " all other daughters will be ignored.");
232 } else {
233 B2ERROR("ParticleLoaderModule::initialize Invalid input DecayString " << decayString
234 << ". DecayString should not contain any daughters, only the mother particle.");
235 }
236 }
237 }
238
240 B2ERROR("The sourceParticleListName is not given. The charged ParticleList is required for the chargedCluster loading.");
241
242 // add PList to corresponding collection of Lists
243 if (isSelfConjugatedParticle or (abs(pdgCode) == Const::neutron.getPDGCode() and not m_useMCParticles))
244 B2INFO(" o) creating ParticleList with name: " << listName);
245 else
246 B2INFO(" o) creating (anti-)ParticleList with name: " << listName << " (" << antiListName << ")");
247 if (m_useROEs) {
248 B2INFO(" -> MDST source: RestOfEvents");
249 m_ROE2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
250 } else if (m_useDummy) {
251 B2INFO(" -> MDST source: No MDST source");
252 m_Dummies2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
253 } else if (m_useMCParticles) {
254 B2INFO(" -> MDST source: MCParticles");
255 m_MCParticles2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
256 } else if (m_loadChargedCluster) {
257 if (abs(pdgCode) == abs(Const::photon.getPDGCode()) || abs(pdgCode) == abs(Const::Klong.getPDGCode())
258 || abs(pdgCode) == abs(Const::neutron.getPDGCode())) {
259 m_ChargedCluster2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
260 B2INFO(" -> MDST source: ECLClusters and KLMClusters being matched with Tracks");
261 } else {
262 B2ERROR("The Particle type must be gamma, K_L0, or (anti-)n0 for the loadChargedCluster option.");
263 }
264 } else {
265 bool chargedFSP = Const::chargedStableSet.contains(Const::ParticleType(abs(pdgCode)));
266 if (chargedFSP) {
267 if (!mdstSourceIsKink) {
268 B2INFO(" -> MDST source: Tracks");
269 m_Tracks2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
270 } else {
271 B2INFO(" -> MDST source: Kinks");
272 m_Kink2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
273 }
274 }
275
276 if (abs(pdgCode) == abs(Const::photon.getPDGCode())) {
277 if (m_addDaughters == false) {
278 m_ECLKLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
279 B2INFO(" -> MDST source: ECLClusters and KLMClusters");
280 } else {
281 B2INFO(" -> MDST source: V0");
282 m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
283 }
284 }
285
286 if (abs(pdgCode) == abs(Const::Kshort.getPDGCode())) {
287 B2INFO(" -> MDST source: V0");
288 m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
289 }
290
291 if (abs(pdgCode) == abs(Const::Klong.getPDGCode()) || abs(pdgCode) == abs(Const::neutron.getPDGCode())) {
292 B2INFO(" -> MDST source: exclusively KLMClusters or exclusively ECLClusters (matching between those not used)");
293 m_ECLKLMClusters2Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
294 }
295
296 if (abs(pdgCode) == abs(Const::Lambda.getPDGCode())) {
297 B2INFO(" -> MDST source: V0");
298 m_V02Plists.emplace_back(pdgCode, listName, antiListName, isSelfConjugatedParticle);
299 }
300 }
301 }
302 }
303
304
305 m_chargeZeroTrackCounts = std::vector<int>(m_Tracks2Plists.size(), 0);
306 m_sameChargeDaughtersV0Counts = std::vector<int>(m_V02Plists.size(), 0);
307}
308
310{
311 if (not m_particleExtraInfoMap) {
312 m_particleExtraInfoMap.create();
313 }
314
315 if (m_useROEs)
317 else if (m_useDummy)
319 else if (m_useMCParticles)
321 else if (m_loadChargedCluster)
323 else {
328
329 }
330}
331
333{
334 // report track errors integrated
335 for (size_t i = 0; i < m_Tracks2Plists.size(); i++)
336 if (m_chargeZeroTrackCounts[i] > 0) {
337 auto track2Plist = m_Tracks2Plists[i];
338 B2WARNING("There were " << m_chargeZeroTrackCounts[i]
339 << " tracks skipped because of zero charge for "
340 << get<c_PListName>(track2Plist));
341 }
342 // report V0 errors integrated
343 for (size_t i = 0; i < m_V02Plists.size(); i++)
345 auto v02Plist = m_V02Plists[i];
346 B2WARNING("There were " << m_sameChargeDaughtersV0Counts[i]
347 << " v0s skipped because of same charge daughters for "
348 << get<c_PListName>(v02Plist));
349 }
350}
351
352
354{
355 if (m_Dummies2Plists.empty()) // nothing to do
356 return;
357 if (m_Dummies2Plists.size() != 1)
358 B2ERROR("ParticleLoaderModule::dummyToParticles Multiple particle lists are not supported!");
359 auto dummy2Plist = m_Dummies2Plists[0];
360 string dummyListName = get<c_PListName>(dummy2Plist);
361 string antiDummyListName = get<c_AntiPListName>(dummy2Plist);
362 int pdgCode = get<c_PListPDGCode>(dummy2Plist);
363 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(dummy2Plist);
364
365 StoreObjPtr<ParticleList> plist(dummyListName);
366 plist.create();
367 plist->initialize(pdgCode, dummyListName);
368
369 if (!isSelfConjugatedParticle) {
370 StoreObjPtr<ParticleList> antiPlist(antiDummyListName);
371 antiPlist.create();
372 antiPlist->initialize(-1 * pdgCode, antiDummyListName);
373 antiPlist->bindAntiParticleList(*(plist));
374 }
375
376 TMatrixFSym covariance(7);
377 for (int row = 0; row < 7; ++row) { //diag
378 covariance(row, row) = m_dummyCovMatrix;
379 }
380
381 Particle* newPart = nullptr;
382 Particle* newAntiPart = nullptr;
383
384 auto isFlavored = (isSelfConjugatedParticle) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
385
386 ROOT::Math::PxPyPzEVector zero4Vector = {0., 0., 0., 0.};
387
388 newPart = m_particles.appendNew(zero4Vector, pdgCode, isFlavored, Particle::EParticleSourceObject::c_NoMDSTSource,
390 if (m_dummyCovMatrix > 0.) newPart->setMomentumVertexErrorMatrix(covariance);
391 if (m_dummyTreatAsInvisible) newPart->writeExtraInfo("treeFitterTreatMeAsInvisible", 1);
392 plist->addParticle(newPart);
393
394 if (!isSelfConjugatedParticle) {
395 newAntiPart = m_particles.appendNew(zero4Vector, -pdgCode, isFlavored, Particle::EParticleSourceObject::c_NoMDSTSource,
397 if (m_dummyCovMatrix > 0.) newAntiPart->setMomentumVertexErrorMatrix(covariance);
398 if (m_dummyTreatAsInvisible) newAntiPart->writeExtraInfo("treeFitterTreatMeAsInvisible", 1);
399 plist->addParticle(newAntiPart);
400 }
401
402}
403
404
406{
407 if (m_ROE2Plists.empty()) // nothing to do
408 return;
409 // Multiple particle lists are not supported
410 auto roe2Plist = m_ROE2Plists[0];
411 string listName = get<c_PListName>(roe2Plist);
412 string antiListName = get<c_AntiPListName>(roe2Plist);
413 int pdgCode = get<c_PListPDGCode>(roe2Plist);
414 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(roe2Plist);
415
416 StoreObjPtr<ParticleList> plist(listName);
417 // since a particle list in the ParticleLoader always contains all possible objects
418 // we check whether it already exists in this path and can skip any further steps if it does
419 if (plist.isValid())
420 return;
421 plist.create();
422 plist->initialize(pdgCode, listName);
423
424 if (!isSelfConjugatedParticle) {
425 StoreObjPtr<ParticleList> antiPlist(antiListName);
426 antiPlist.create();
427 antiPlist->initialize(-1 * pdgCode, antiListName);
428 antiPlist->bindAntiParticleList(*(plist));
429 }
430 if (m_sourceParticleListName != "") {
431 // Take related ROEs from a particle list
433 if (!pList.isValid())
434 B2FATAL("ParticleList " << m_sourceParticleListName << " could not be found or is not valid!");
435
436 for (unsigned int i = 0; i < pList->getListSize(); i++) {
437 RestOfEvent* roe = pList->getParticle(i)->getRelatedTo<RestOfEvent>("ALL");
438 if (!roe) {
439 B2ERROR("ParticleList " << m_sourceParticleListName << " has no associated ROEs!");
440 } else {
441
442 if (isSelfConjugatedParticle)
443 addROEToParticleList(roe, i, pdgCode, isSelfConjugatedParticle);
444 else if (i < pList->getListSize(false))
445 addROEToParticleList(roe, i, pdgCode, isSelfConjugatedParticle);
446 else
447 addROEToParticleList(roe, i, -1 * pdgCode, isSelfConjugatedParticle);
448 }
449 }
450
451 } else {
452 // Take all ROE if no particle list provided
453 for (int i = 0; i < m_roes.getEntries(); i++) {
455 }
456 }
457}
458
459void ParticleLoaderModule::addROEToParticleList(RestOfEvent* roe, int mdstIndex, int pdgCode, bool isSelfConjugatedParticle)
460{
461
462 Particle* newPart = nullptr;
463 if (!m_useMissing) {
464 // Convert ROE to particle
465 newPart = roe->convertToParticle(m_roeMaskName, pdgCode, isSelfConjugatedParticle);
466 } else {
467 // Create a particle from missing momentum
468 auto* signalSideParticle = roe->getRelatedFrom<Particle>();
470 ROOT::Math::PxPyPzEVector boost4Vector = T.getBeamFourMomentum();
471
472 ROOT::Math::PxPyPzEVector signal4Vector = signalSideParticle->get4Vector();
473 ROOT::Math::PxPyPzEVector roe4Vector = roe->get4Vector(m_roeMaskName);
474 ROOT::Math::PxPyPzEVector missing4Vector = boost4Vector - signal4Vector - roe4Vector;
475 auto isFlavored = (isSelfConjugatedParticle) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
476 newPart = m_particles.appendNew(missing4Vector, pdgCode, isFlavored, Particle::EParticleSourceObject::c_Undefined, mdstIndex);
477 }
478
479 roe->addRelationTo(newPart);
480
481 for (auto roe2Plist : m_ROE2Plists) {
482 string listName = get<c_PListName>(roe2Plist);
483 StoreObjPtr<ParticleList> plist(listName);
484 plist->addParticle(newPart);
485 }
486}
487
488
490{
491 if (m_V02Plists.empty()) // nothing to do
492 return;
493
494 // check if the order of the daughters in the decay string (decided by the user) is the same as the v0 daughters' order (fixed)
495 bool matchingDaughtersOrder = true;
498 matchingDaughtersOrder = false;
499
500 // loop over all ParticleLists
501 for (size_t ilist = 0; ilist < m_V02Plists.size(); ilist++) {
502 auto v02Plist = m_V02Plists[ilist];
503 string listName = get<c_PListName>(v02Plist);
504 string antiListName = get<c_AntiPListName>(v02Plist);
505 int pdgCode = get<c_PListPDGCode>(v02Plist);
506 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(v02Plist);
507
508 StoreObjPtr<ParticleList> plist(listName);
509 // since a particle list in the ParticleLoader always contains all possible objects
510 // we check whether it already exists in this path and can skip any further steps if it does
511 if (plist.isValid())
512 continue;
513 plist.create();
514 plist->initialize(pdgCode, listName);
515
516 if (!isSelfConjugatedParticle) {
517 StoreObjPtr<ParticleList> antiPlist(antiListName);
518 antiPlist.create();
519 antiPlist->initialize(-1 * pdgCode, antiListName);
520
521 antiPlist->bindAntiParticleList(*(plist));
522 }
523
524 plist->setEditable(true); // :V0 list is originally reserved. we have to set it as editable.
525
526 // load reconstructed V0s as Kshorts (pi-pi+ combination), Lambdas (p+pi- combinations), and converted photons (e-e+ combinations)
527 for (int i = 0; i < m_v0s.getEntries(); i++) {
528 const V0* v0 = m_v0s[i];
530
531 if (abs(pdgCode) != abs(v0Type.getPDGCode()))
532 continue;
533
534 // check if the charge of the 2 V0's daughters is opposite
535 if (v0->getTrackFitResults().first->getChargeSign() == v0->getTrackFitResults().second->getChargeSign()) {
536 B2DEBUG(19, "V0 with same charge daughters skipped!");
538 continue;
539 }
540
544
545 if (v0Type.getPDGCode() == Const::Kshort.getPDGCode()) { // K0s -> pi+ pi-
546 pTypeP = Const::pion;
547 pTypeM = Const::pion;
548 } else if (v0Type.getPDGCode() == Const::Lambda.getPDGCode()) { // Lambda -> p+ pi-
549 pTypeP = Const::proton;
550 pTypeM = Const::pion;
551 v0FlavorType = Particle::c_Flavored; // K0s are not flavoured, lambdas are
552 } else if (v0Type.getPDGCode() == Const::antiLambda.getPDGCode()) { // anti-Lambda -> pi+ anti-p-
553 pTypeP = Const::pion;
554 pTypeM = Const::proton;
555 v0FlavorType = Particle::c_Flavored;
556 } else if (v0Type.getPDGCode() == Const::photon.getPDGCode()) { // gamma -> e+ e-
557 pTypeP = Const::electron;
558 pTypeM = Const::electron;
559 } else {
560 B2WARNING("Unknown V0 hypothesis!");
561 }
562
563 // check if, given the initial user's decay descriptor, the current v0 is a particle or an anti-particle.
564 // 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
565 // one particle list and one anti-particle, the v0 daughters' order has to be switched only in one case
566 bool correctOrder = matchingDaughtersOrder;
567 if (abs(v0Type.getPDGCode()) == abs(m_decaydescriptor.getMother()->getPDGCode())
569 correctOrder = !correctOrder;
570
571 std::pair<Track*, Track*> v0Tracks = v0->getTracks();
572 std::pair<TrackFitResult*, TrackFitResult*> v0TrackFitResults = v0->getTrackFitResults();
573
574 Particle daugP((v0Tracks.first)->getArrayIndex(), v0TrackFitResults.first, pTypeP);
575 Particle daugM((v0Tracks.second)->getArrayIndex(), v0TrackFitResults.second, pTypeM);
576
577 const PIDLikelihood* pidP = (v0Tracks.first)->getRelated<PIDLikelihood>();
578 const PIDLikelihood* pidM = (v0Tracks.second)->getRelated<PIDLikelihood>();
579
580 const auto& mcParticlePWithWeight = (v0Tracks.first)->getRelatedToWithWeight<MCParticle>();
581 const auto& mcParticleMWithWeight = (v0Tracks.second)->getRelatedToWithWeight<MCParticle>();
582
583 // add V0 daughters to the Particle StoreArray
584 Particle* newDaugP;
585 Particle* newDaugM;
586
587 if (correctOrder) {
588 newDaugP = m_particles.appendNew(daugP);
589 newDaugM = m_particles.appendNew(daugM);
590 } else {
591 newDaugM = m_particles.appendNew(daugM);
592 newDaugP = m_particles.appendNew(daugP);
593 }
594
595 // if there are PIDLikelihoods and MCParticles then also add relations to the particles
596 if (pidP)
597 newDaugP->addRelationTo(pidP);
598 if (mcParticlePWithWeight.first)
599 newDaugP->addRelationTo(mcParticlePWithWeight.first, mcParticlePWithWeight.second);
600 newDaugP->addRelationTo(v0TrackFitResults.first);
601
602 if (pidM)
603 newDaugM->addRelationTo(pidM);
604 if (mcParticleMWithWeight.first)
605 newDaugM->addRelationTo(mcParticleMWithWeight.first, mcParticleMWithWeight.second);
606 newDaugM->addRelationTo(v0TrackFitResults.second);
607
608 // sum the 4-momenta of the daughters and construct a particle object
609 ROOT::Math::PxPyPzEVector v0Momentum = newDaugP->get4Vector() + newDaugM->get4Vector();
610 Particle v0P(v0Momentum, v0Type.getPDGCode(), v0FlavorType,
611 Particle::EParticleSourceObject::c_V0, v0->getArrayIndex());
613
614 // add the daughters of the V0 (in the correct order) and don't update
615 // the type to c_Composite (i.e. maintain c_V0)
616 if (correctOrder) {
617 v0P.appendDaughter(newDaugP, false);
618 v0P.appendDaughter(newDaugM, false);
619 } else {
620 v0P.appendDaughter(newDaugM, false);
621 v0P.appendDaughter(newDaugP, false);
622 }
623
624 // append the particle to the Particle StoreArray and add the new particle to the ParticleList
625 Particle* newPart = m_particles.appendNew(v0P);
626 plist->addParticle(newPart);
627 }
628
629 plist->setEditable(false); // set the :V0 list as not editable.
630 }
631}
632
634{
635
636 if (m_Kink2Plists.empty()) // nothing to do
637 return;
638
639 // loop over all ParticleLists
640 for (size_t ilist = 0; ilist < m_Kink2Plists.size(); ilist++) {
641 auto kink2Plist = m_Kink2Plists[ilist];
642 string listName = get<c_PListName>(kink2Plist);
643 string antiListName = get<c_AntiPListName>(kink2Plist);
644 int pdgCode = get<c_PListPDGCode>(kink2Plist);
645 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(kink2Plist);
646
647 StoreObjPtr<ParticleList> plist(listName);
648 // since a particle list in the ParticleLoader always contains all possible objects
649 // we check whether it already exists in this path and can skip any further steps if it does
650 if (plist.isValid())
651 continue;
652 plist.create();
653 plist->initialize(pdgCode, listName);
654
655 if (!isSelfConjugatedParticle) {
656 StoreObjPtr<ParticleList> antiPlist(antiListName);
657 antiPlist.create();
658 antiPlist->initialize(-1 * pdgCode, antiListName);
659
660 antiPlist->bindAntiParticleList(*(plist));
661 }
662
663 plist->setEditable(true); // :kink list is originally reserved. we have to set it as editable.
664
665 // load reconstructed Kinks according to requested mother hypothesis
666 for (int i = 0; i < m_kinks.getEntries(); i++) {
667 const Kink* kink = m_kinks[i];
668
669 Const::ChargedStable motherType(abs(pdgCode));
670 const Track* motherTrack = kink->getMotherTrack();
671 const TrackFitResult* motherTrackFit = kink->getMotherTrackFitResultStart();
672
673 int motherCharge = motherTrackFit->getChargeSign();
674 if (motherCharge == 0) {
675 B2DEBUG(19, "Kink track with charge = 0 skipped!");
676 continue;
677 }
678
679 const auto& motherMCParticleWithWeight = motherTrack->getRelatedToWithWeight<MCParticle>();
680 const PIDLikelihood* motherPID = motherTrack->getRelated<PIDLikelihood>();
681
682 // a particle object creation from kink mother with the correct option
683 Particle kinkP(kink, motherType, kink->getTrackFitResultIndexMotherStart());
684
685 // append the particle to the Particle StoreArray
686 Particle* newPart = m_particles.appendNew(kinkP);
687
688 if (motherPID)
689 newPart->addRelationTo(motherPID);
690 if (motherMCParticleWithWeight.first)
691 newPart->addRelationTo(motherMCParticleWithWeight.first, motherMCParticleWithWeight.second);
692 newPart->writeExtraInfo("kinkDaughterPDGCode", m_decaydescriptor.getDaughter(0)->getMother()->getPDGCode());
693
694 // add the new particle to the ParticleList
695 plist->addParticle(newPart);
696 }
697
698 plist->setEditable(false); // set the :kink list as not editable.
699 }
700}
701
703{
704 if (m_Tracks2Plists.empty()) // nothing to do
705 return;
706
707 // loop over all requested particle lists
708 for (size_t ilist = 0; ilist < m_Tracks2Plists.size(); ilist++) {
709 auto track2Plist = m_Tracks2Plists[ilist];
710 string listName = get<c_PListName>(track2Plist);
711 string antiListName = get<c_AntiPListName>(track2Plist);
712 int pdgCode = get<c_PListPDGCode>(track2Plist);
713 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(track2Plist);
714
715 StoreObjPtr<ParticleList> plist(listName);
716 // since a particle list in the ParticleLoader always contains all possible objects
717 // we check whether it already exists in this path and can skip any further steps if it does
718 if (plist.isValid())
719 continue;
720 plist.create();
721 plist->initialize(pdgCode, listName);
722
723 // if cc exists then also create and bind that list
724 if (!isSelfConjugatedParticle) {
725 StoreObjPtr<ParticleList> antiPlist(antiListName);
726 antiPlist.create();
727 antiPlist->initialize(-1 * pdgCode, antiListName);
728
729 antiPlist->bindAntiParticleList(*(plist));
730 }
731
732 plist->setEditable(true); // :all list is originally reserved. we have to set it as editable.
733
734 // the inner loop over all tracks from which Particles
735 // are created, and get sorted in the particle lists
736 for (int i = 0; i < m_tracks.getEntries(); i++) {
737 const Track* track = m_tracks[i];
738 const PIDLikelihood* pid = track->getRelated<PIDLikelihood>();
739 const auto& mcParticleWithWeight = track->getRelatedToWithWeight<MCParticle>();
740
741 // if a special track hypothesis is requested, use it
742 if (m_trackHypothesis != 0) pdgCode = m_trackHypothesis;
743 Const::ChargedStable type(abs(pdgCode));
744
745 // load the TrackFitResult for the requested particle or if not available use
746 // the one with the closest mass
747 const TrackFitResult* trackFit = track->getTrackFitResultWithClosestMass(type);
748
749 if (!trackFit) { // should never happen with the "closest mass" getter - leave as a sanity check
750 B2WARNING("Track returned null TrackFitResult pointer for ChargedStable::getPDGCode() = " << type.getPDGCode());
751 continue;
752 }
753
754 if (m_enforceFitHypothesis && (trackFit->getParticleType().getPDGCode() != type.getPDGCode())) {
755 // the required hypothesis does not exist for this track, skip it
756 continue;
757 }
758
759 // charge zero tracks can appear, filter them and
760 // count number of tracks filtered out
761 int charge = trackFit->getChargeSign();
762 if (charge == 0) {
763 B2DEBUG(19, "Track with charge = 0 skipped!");
765 continue;
766 }
767
768 // create particle and add it to the Particle list.
769 Particle particle(track->getArrayIndex(), trackFit, type);
770
771 if (particle.getParticleSource() == Particle::c_Track) { // should always hold but...
772
773 Particle* newPart = m_particles.appendNew(particle);
774 if (pid)
775 newPart->addRelationTo(pid);
776 if (mcParticleWithWeight.first)
777 newPart->addRelationTo(mcParticleWithWeight.first, mcParticleWithWeight.second);
778 newPart->addRelationTo(trackFit);
779
780 plist->addParticle(newPart);
781
782 } // sanity check correct particle type
783 } // loop over tracks
784
785 plist->setEditable(false); // set the :all list as not editable.
786 } // particle lists
787}
788
790{
791 if (m_ECLKLMClusters2Plists.empty()) // nothing to do
792 return;
793
794 // loop over all ParticleLists
795 for (auto eclKLMCluster2Plist : m_ECLKLMClusters2Plists) {
796 string listName = get<c_PListName>(eclKLMCluster2Plist);
797 int pdgCode = get<c_PListPDGCode>(eclKLMCluster2Plist);
798 Const::ParticleType thisType(pdgCode);
799
800 StoreObjPtr<ParticleList> plist(listName);
801 // since a particle list in the ParticleLoader always contains all possible objects
802 // we check whether it already exists in this path and can skip any further steps if it does
803 if (plist.isValid())
804 continue;
805 plist.create();
806 plist->initialize(pdgCode, listName);
807
808 plist->setEditable(true); // :all list is originally reserved. we have to set it as editable.
809
810 // load reconstructed neutral ECL clusters as photons or Klongs or neutrons
811 for (int i = 0; i < m_eclclusters.getEntries(); i++) {
812 const ECLCluster* cluster = m_eclclusters[i];
813
814 if (!isValidECLCluster(cluster, pdgCode, true))
815 continue;
816
817 // create particle and check it before adding to list
818 Particle particle(cluster, thisType);
819 if (particle.getParticleSource() != Particle::c_ECLCluster) {
820 B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
821 continue;
822 }
823 Particle* newPart = m_particles.appendNew(particle);
824
825 assignMCParticleFromECLCluster(newPart, cluster);
826
827 // add particle to list
828 plist->addParticle(newPart);
829 }
830
831 // load reconstructed KLM clusters as Klongs or neutrons or photons
832 for (int i = 0; i < m_klmclusters.getEntries(); i++) {
833 const KLMCluster* cluster = m_klmclusters[i];
834
835 if (std::isnan(cluster->getMomentumMag())) {
836 B2DEBUG(19, "Skipping KLMCluster because its momentum is NaN. "
837 "This can happen if the timing calibration is missing or wrong, so that the velocity is calculated to be negative.");
838 continue;
839 }
840
841 const MCParticle* mcParticle = cluster->getRelated<MCParticle>();
842
843 // create particle and check its type before adding it to list
844 Particle particle(cluster, pdgCode);
845 if (particle.getParticleSource() != Particle::c_KLMCluster) {
846 B2FATAL("Particle created from KLMCluster does not have KLMCluster type.");
847 }
848 Particle* newPart = m_particles.appendNew(particle);
849
850 if (mcParticle)
851 newPart->addRelationTo(mcParticle);
852
853 // add particle to list
854 plist->addParticle(newPart);
855 }
856
857 plist->setEditable(false); // set the :all list as not editable.
858 } // loop over particle lists
859}
860
861bool ParticleLoaderModule::isValidECLCluster(const ECLCluster* cluster, const int pdgCode, bool onlyNeutral) const
862{
863 if (!cluster)
864 return false;
865
866 // ECLClusters can be reconstructed under different hypotheses, for
867 // example photons or neutral hadrons, we only load particles from these
868 // for now
869 if (!cluster->isNeutral() and onlyNeutral)
870 return false;
871
872 if (not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)
873 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
874 return false;
875
876 // don't fill photon list with clusters that don't have
877 // the nPhotons hypothesis (ECL people call this N1)
878 if (pdgCode == Const::photon.getPDGCode()
879 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons))
880 return false;
881
882 // don't fill a KLong nor a (anti-)neutron list with clusters that don't have the neutral
883 // hadron hypothesis set (ECL people call this N2)
884 if ((pdgCode == Const::Klong.getPDGCode() or abs(pdgCode) == Const::neutron.getPDGCode())
885 and not cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_neutralHadron))
886 return false;
887
888 return true;
889}
890
892{
893 // ECLCluster can be matched to multiple MCParticles
894 // order the relations by weights and set Particle -> multiple MCParticle relation
895 // preserve the weight
896 const RelationVector<MCParticle> mcRelations = cluster->getRelationsTo<MCParticle>();
897
898 // order relations by weights
899 std::vector<std::pair<double, int>> weightsAndIndices;
900 for (unsigned int iMCParticle = 0; iMCParticle < mcRelations.size(); iMCParticle++) {
901 const MCParticle* relMCParticle = mcRelations[iMCParticle];
902 if (relMCParticle) {
903 double weight = mcRelations.weight(iMCParticle);
904 weightsAndIndices.emplace_back(weight, relMCParticle->getArrayIndex());
905 }
906 }
907
908 // sort descending by weight
909 std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
910 ValueIndexPairSorting::higherPair<decltype(weightsAndIndices)::value_type>);
911
912 // set relations to mcparticles
913 for (auto& weightsAndIndex : weightsAndIndices) {
914 const MCParticle* relMCParticle = m_mcparticles[weightsAndIndex.second];
915 double weight = weightsAndIndex.first;
916
917 // TODO: study this further and avoid hard-coded values
918 // set the relation only if the MCParticle(reconstructed Particle)'s
919 // energy contribution to this cluster amounts to at least 30(20)%
920 if (relMCParticle)
921 if (weight / newPart->getECLClusterEnergy() > 0.20
922 && weight / relMCParticle->getEnergy() > 0.30)
923 newPart->addRelationTo(relMCParticle, weight);
924 }
925
926}
927
929{
930 if (m_ChargedCluster2Plists.empty()) // nothing to do
931 return;
932
933 // loop over all ParticleLists
934 for (auto chargedCluster2Plist : m_ChargedCluster2Plists) {
935
936 string listName = get<c_PListName>(chargedCluster2Plist);
937 string antiListName = get<c_AntiPListName>(chargedCluster2Plist);
938 int pdgCode = get<c_PListPDGCode>(chargedCluster2Plist);
939 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(chargedCluster2Plist);
940 Const::ParticleType thisType(pdgCode);
941
942 StoreObjPtr<ParticleList> plist(listName);
943 // since a particle list in the ParticleLoader always contains all possible objects
944 // we check whether it already exists in this path and can skip any further steps if it does
945 if (plist.isValid())
946 continue;
947 plist.create();
948 plist->initialize(pdgCode, listName);
949
950 // create anti-particle list if necessary
951 if (!isSelfConjugatedParticle) {
952 StoreObjPtr<ParticleList> antiPlist(antiListName);
953 antiPlist.create();
954 antiPlist->initialize(-1 * pdgCode, antiListName);
955
956 antiPlist->bindAntiParticleList(*(plist));
957 }
958
960 if (!sourceList.isValid())
961 B2FATAL("ParticleList " << m_sourceParticleListName << " could not be found or is not valid!");
962
963 for (unsigned int iPart = 0; iPart < sourceList->getListSize(); iPart++) {
964
965 const Particle* sourcePart = sourceList->getParticle(iPart);
966 const Track* sourceTrack = sourceList->getParticle(iPart)->getTrack();
967 if (!sourceTrack)
968 continue;
969
970 // ECL clusters
972
973 const ECLCluster* cluster = sourcePart->getECLCluster();
974 if (isValidECLCluster(cluster, pdgCode, false)) {
975 Particle particle(cluster, thisType);
976 if (particle.getParticleSource() != Particle::c_ECLCluster) {
977 B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
978 }
979 Particle* newPart = m_particles.appendNew(particle);
980 assignMCParticleFromECLCluster(newPart, cluster);
981 plist->addParticle(newPart);
982 }
983 } else {
984
985 // loop over all clusters matched to this track
986 const RelationVector<ECLCluster> clusters = sourceTrack->getRelationsTo<ECLCluster>();
987 for (unsigned int iCluster = 0; iCluster < clusters.size(); iCluster++) {
988 const ECLCluster* cluster = clusters[iCluster];
989 if (!isValidECLCluster(cluster, pdgCode, false))
990 continue; // go to next iCluster
991
992 Particle particle(cluster, thisType);
993 if (particle.getParticleSource() != Particle::c_ECLCluster) {
994 B2FATAL("Particle created from ECLCluster does not have ECLCluster type.");
995 }
996 Particle* newPart = m_particles.appendNew(particle);
997 assignMCParticleFromECLCluster(newPart, cluster);
998 plist->addParticle(newPart);
999 }
1000 }
1001
1002 // KLM clusters
1003 const KLMCluster* cluster = sourcePart->getKLMCluster();
1004 if (!cluster) continue; // go to next iPart
1005
1006 if (std::isnan(cluster->getMomentumMag())) {
1007 B2DEBUG(19, "Skipping KLMCluster because its momentum is NaN. "
1008 "This can happen if the timing calibration is missing or wrong, so that the velocity is calculated to be negative.");
1009 continue;
1010 }
1011
1012 // create particle and check its type before adding it to list
1013 Particle particle(cluster, pdgCode);
1014 if (particle.getParticleSource() != Particle::c_KLMCluster) {
1015 B2FATAL("Particle created from KLMCluster does not have KLMCluster type.");
1016 }
1017 Particle* newPart = m_particles.appendNew(particle);
1018
1019 const MCParticle* mcParticle = cluster->getRelated<MCParticle>();
1020 if (mcParticle) newPart->addRelationTo(mcParticle);
1021
1022 plist->addParticle(newPart);
1023 }
1024
1025 } // loop over particle lists
1026}
1027
1029{
1030 if (m_MCParticles2Plists.empty()) // nothing to do
1031 return;
1032
1033 // create all lists
1034 for (auto mcParticle2Plist : m_MCParticles2Plists) {
1035 string listName = get<c_PListName>(mcParticle2Plist);
1036 string antiListName = get<c_AntiPListName>(mcParticle2Plist);
1037 int pdgCode = get<c_PListPDGCode>(mcParticle2Plist);
1038 bool isSelfConjugatedParticle = get<c_IsPListSelfConjugated>(mcParticle2Plist);
1039
1040 StoreObjPtr<ParticleList> plist(listName);
1041 if (plist.isValid())
1042 continue;
1043 plist.create();
1044 plist->initialize(pdgCode, listName);
1045
1046 if (!isSelfConjugatedParticle) {
1047 StoreObjPtr<ParticleList> antiPlist(antiListName);
1048 antiPlist.create();
1049 antiPlist->initialize(-1 * pdgCode, antiListName);
1050
1051 antiPlist->bindAntiParticleList(*(plist));
1052 }
1053
1054 for (int i = 0; i < m_mcparticles.getEntries(); i++) {
1055 const MCParticle* mcParticle = m_mcparticles[i];
1056
1057 if (abs(pdgCode) != abs(mcParticle->getPDG()))
1058 continue;
1059
1061 continue;
1062
1063 if (m_skipInitial and mcParticle->isInitial())
1064 continue;
1065
1066 Particle particle(mcParticle);
1067 Particle* newPart = m_particles.appendNew(particle);
1068 newPart->addRelationTo(mcParticle);
1069
1070 //append the whole bottom part of the decay tree to this particle
1072
1073 plist->addParticle(newPart);
1074 }
1075
1076 }
1077}
1078
1080{
1081 bool result = false;
1082
1083 // is particle type = charged final state particle?
1084 if (Const::chargedStableSet.find(abs(pdgCode)) != Const::invalidParticle)
1085 return true;
1086
1087 if (abs(pdgCode) == abs(Const::photon.getPDGCode()))
1088 return true;
1089
1090 if (abs(pdgCode) == abs(Const::Kshort.getPDGCode()))
1091 return true;
1092
1093 if (abs(pdgCode) == abs(Const::Klong.getPDGCode()))
1094 return true;
1095
1096 if (abs(pdgCode) == abs(Const::Lambda.getPDGCode()))
1097 return true;
1098
1099 if (abs(pdgCode) == abs(Const::neutron.getPDGCode()))
1100 return true;
1101
1102 return result;
1103}
1104
1106{
1107 auto* mcmother = mother->getRelated<MCParticle>();
1108
1109 if (!mcmother)
1110 return;
1111
1112 vector<MCParticle*> mcdaughters = mcmother->getDaughters();
1113
1114 for (auto& mcdaughter : mcdaughters) {
1115 if (!mcdaughter->hasStatus(MCParticle::c_PrimaryParticle) and m_skipNonPrimaryDaughters) continue;
1116 Particle particle(mcdaughter);
1117 Particle* daughter = m_particles.appendNew(particle);
1118 daughter->addRelationTo(mcdaughter);
1119 mother->appendDaughter(daughter, false);
1120
1121 if (mcdaughter->getNDaughters() > 0)
1122 appendDaughtersRecursive(daughter);
1123 }
1124}
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:421
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.
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
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
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.
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
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: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:301
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:438
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:95
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:110
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
Const::ParticleType getParticleType() const
Getter for ParticleType of the mass hypothesis of the track fit.
Class that bundles various TrackFitResults.
Definition: Track.h:25
Object holding information for V0s.
Definition: V0.h: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.