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