Project
Loading...
Searching...
No Matches
Stack.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#include "DetectorsBase/Stack.h"
21
22#include "FairDetector.h" // for FairDetector
23#include <fairlogger/Logger.h> // for FairLogger
24#include "FairRootManager.h"
28
29#include "TLorentzVector.h" // for TLorentzVector
30#include "TParticle.h" // for TParticle
31#include "TRefArray.h" // for TRefArray
32#include "TVirtualMC.h" // for VMC
33#include "TMCProcess.h" // for VMC Particle Production Process
34
35#include <algorithm>
36#include <cassert>
37#include <cstddef> // for NULL
38#include <cmath>
39#include <unordered_map>
41
42using std::cout;
43using std::endl;
44using std::pair;
45using namespace o2::data;
46
47namespace
48{
49// a TParticle copied from a per-thread prototype per PDG code, avoiding the ROOT-locked PDG lookup
50TParticle makeParticle(int pdg, int status, int mother1, int mother2, int daughter1, int daughter2,
51 double px, double py, double pz, double e, double vx, double vy, double vz, double t)
52{
53 thread_local std::unordered_map<int, TParticle> prototypes;
54 auto it = prototypes.find(pdg);
55 if (it == prototypes.end()) {
56 TParticle p(pdg, status, mother1, mother2, daughter1, daughter2, px, py, pz, e, vx, vy, vz, t);
57 if (p.GetPDG(1)) { // unknown codes may still be added to TDatabasePDG later
58 prototypes.emplace(pdg, p);
59 }
60 return p;
61 }
62 TParticle p(it->second); // the copy keeps the PDG record and the mass
63 p.SetStatusCode(status);
64 p.SetFirstMother(mother1);
65 p.SetLastMother(mother2);
66 p.SetFirstDaughter(daughter1);
67 p.SetLastDaughter(daughter2);
68 p.SetMomentum(px, py, pz, e);
69 p.SetProductionVertex(vx, vy, vz, t);
70 return p;
71}
72} // namespace
73
74// small helper function to append to vector at arbitrary position
75template <typename T, typename I>
76void insertInVector(std::vector<T>& v, I index, T e)
77{
78 auto currentsize = v.size();
79 if (index >= currentsize) {
80 const auto newsize = std::max(index + 1, (I)(1 + currentsize * 1.2));
81 v.resize(newsize, T(-1));
82 }
83 // new size must at least be as large as index
84 // assert(index < v.size());
85 v[index] = e;
86}
87
90 mStack(),
91 mParticles(),
92 mTracks(new std::vector<o2::MCTrack>),
93 mTrackIDtoParticlesEntry(1000000, -1),
94 mIndexMap(),
95 mIndexOfCurrentTrack(-1),
96 mIndexOfCurrentPrimary(-1),
97 mNumberOfPrimaryParticles(0),
98 mNumberOfEntriesInParticles(0),
99 mNumberOfEntriesInTracks(0),
100 mNumberOfPrimariesforTracking(0),
101 mNumberOfPrimariesPopped(0),
102 mStoreMothers(kTRUE),
103 mStoreSecondaries(kTRUE),
104 mMinHits(1),
105 mEnergyCut(0.),
106 mTrackRefs(new std::vector<o2::TrackReference>),
107 mIsG4Like(false)
108{
109 auto vmc = TVirtualMC::GetMC();
110 if (vmc) {
111 mIsG4Like = !(vmc->SecondariesAreOrdered());
112 }
113
115 TransportFcn transportPrimary;
116 if (param.transportPrimary.compare("none") == 0) {
117 transportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) {
118 return false;
119 };
120 } else if (param.transportPrimary.compare("all") == 0) {
121 transportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) {
122 return true;
123 };
124 } else if (param.transportPrimary.compare("barrel") == 0) {
125 transportPrimary = [](const TParticle& p, const std::vector<TParticle>& particles) {
126 return (std::fabs(p.Eta()) < 2.0);
127 };
128 } else if (param.transportPrimary.compare("external") == 0) {
129 transportPrimary = o2::conf::GetFromMacro<o2::data::Stack::TransportFcn>(param.transportPrimaryFileName,
130 param.transportPrimaryFuncName,
131 "o2::data::Stack::TransportFcn", "stack_transport_primary");
132 if (!transportPrimary) {
133 LOG(fatal) << "Failed to retrieve external \'transportPrimary\' function: problem with configuration ";
134 }
135 LOG(info) << "Successfully retrieve external \'transportPrimary\' frunction: " << param.transportPrimaryFileName;
136 } else {
137 LOG(fatal) << "unsupported \'trasportPrimary\' mode: " << param.transportPrimary;
138 }
139
140 if (param.transportPrimaryInvert) {
141 mTransportPrimary = [transportPrimary](const TParticle& p, const std::vector<TParticle>& particles) { return !transportPrimary(p, particles); };
142 } else {
143 mTransportPrimary = transportPrimary;
144 }
145}
146
147Stack::Stack(const Stack& rhs)
148 : FairGenericStack(rhs),
149 mStack(),
150 mParticles(),
151 mTrackIDtoParticlesEntry(rhs.mTrackIDtoParticlesEntry.size(), -1),
152 mTracks(nullptr),
153 mIndexMap(),
154 mIndexOfCurrentTrack(-1),
155 mIndexOfCurrentPrimary(-1),
156 mNumberOfPrimaryParticles(0),
157 mNumberOfEntriesInParticles(0),
158 mNumberOfEntriesInTracks(0),
159 mNumberOfPrimariesforTracking(0),
160 mNumberOfPrimariesPopped(0),
161 mStoreMothers(rhs.mStoreMothers),
162 mStoreSecondaries(rhs.mStoreSecondaries),
163 mPruneKinematics(rhs.mPruneKinematics),
164 mMinHits(rhs.mMinHits),
165 mEnergyCut(rhs.mEnergyCut),
166 mCleanupThreshold(rhs.mCleanupThreshold),
167 mIsG4Like(rhs.mIsG4Like),
168 mIsExternalMode(rhs.mIsExternalMode),
169 mDoTrackSeeding(rhs.mDoTrackSeeding),
170 mTransportPrimary(rhs.mTransportPrimary),
171 mTrackRefs(new std::vector<o2::TrackReference>)
172{
173 LOG(debug) << "copy constructor called";
174 mTracks = new std::vector<MCTrack>();
175}
176
177Stack::~Stack()
178{
179 if (mTracks) {
180 delete mTracks;
181 }
182}
183
184Stack& Stack::operator=(const Stack& rhs)
185{
186 LOG(fatal) << "operator= called";
187 // check assignment to self
188 if (this == &rhs) {
189 return *this;
190 }
191
192 // base class assignment
194 mTracks = new std::vector<MCTrack>(rhs.mTracks->size());
195 mIndexOfCurrentTrack = -1;
196 mIndexOfCurrentPrimary = -1;
197 mNumberOfPrimaryParticles = 0;
198 mNumberOfEntriesInParticles = 0;
199 mNumberOfEntriesInTracks = 0;
200 mNumberOfPrimariesforTracking = 0;
201 mNumberOfPrimariesPopped = 0;
202 mStoreMothers = rhs.mStoreMothers;
203 mStoreSecondaries = rhs.mStoreSecondaries;
204 mMinHits = rhs.mMinHits;
205 mEnergyCut = rhs.mEnergyCut;
206 mIsG4Like = rhs.mIsG4Like;
207
208 return *this;
209}
210
211void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e,
212 Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz,
213 TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is)
214{
215 PushTrack(toBeDone, parentId, pdgCode, px, py, pz, e, vx, vy, vz, time, polx, poly, polz, proc, ntr, weight, is, -1);
216}
217
218void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e,
219 Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz,
220 TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondparentId)
221{
222 PushTrack(toBeDone, parentId, pdgCode, px, py, pz, e, vx, vy, vz, time, polx, poly, polz, proc, ntr, weight, is, secondparentId, -1, -1, proc);
223}
224
225void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e,
226 Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz,
227 TMCProcess proc, Int_t& ntr, Double_t weight, Int_t is, Int_t secondparentId, Int_t daughter1Id, Int_t daughter2Id,
228 TMCProcess proc2)
229{
230 // printf("Pushing %s toBeDone %5d parentId %5d pdgCode %5d is %5d entries %5d \n",
231 // proc == kPPrimary ? "Primary: " : "Secondary: ",
232 // toBeDone, parentId, pdgCode, is, mNumberOfEntriesInParticles);
233
234 //
235 // This method is called
236 //
237 // - during serial simulation directly from the event generator
238 // - during parallel simulation to fill the stack of the primary generator device
239 // - in all cases to push a secondary particle
240 //
241 //
242 // Create new TParticle and add it to the TParticle array
243
244 Int_t trackId = mNumberOfEntriesInParticles;
245 // Set track variable
246 ntr = trackId;
247 // Int_t daughter1Id = -1;
248 // Int_t daughter2Id = -1;
249 Int_t iStatus = (proc == kPPrimary) ? is : trackId;
250 TParticle p = makeParticle(pdgCode, iStatus, parentId, secondparentId, daughter1Id, daughter2Id, px, py, pz, e, vx, vy, vz, time);
251 p.SetPolarisation(polx, poly, polz);
252 p.SetWeight(weight);
253 p.SetUniqueID(proc); // using the unique ID to transfer process ID
254 p.SetBit(ParticleStatus::kPrimary, proc == kPPrimary ? 1 : 0); // set primary bit
255 p.SetBit(ParticleStatus::kToBeDone, toBeDone == 1 ? 1 : 0); // set to be done bit
256 mNumberOfEntriesInParticles++;
257
258 insertInVector(mTrackIDtoParticlesEntry, trackId, (int)(mParticles.size()));
259
260 handleTransportPrimary(p); // handle selective transport of primary particles
261
262 // Push particle on the stack if toBeDone is set
263 if (p.TestBit(ParticleStatus::kPrimary)) {
264 // This is a particle from the primary particle generator
265 //
266 // SetBit is used to pass information about the primary particle to the stack during transport.
267 // Sime particles have already decayed or are partons from a shower. They are needed for the
268 // event history in the stack, but not for transport.
269 //
270
271 // primary particles might have been pushed with a second creation process
272 // in case we pushed a secondary track of a previous simulation to be continued.
273 // We save therefore in the UniqueID the correct process
274 // while the particle will still be treated as a primary given its bit settings
275 p.SetUniqueID(proc2);
276
277 mIndexMap[trackId] = trackId;
278 p.SetBit(ParticleStatus::kKeep, 1);
279 if (p.TestBit(ParticleStatus::kToBeDone)) {
280 mNumberOfPrimariesforTracking++;
281 }
282 mNumberOfPrimaryParticles++;
283 mPrimaryParticles.push_back(p);
284 mTracks->emplace_back(p);
285 } else {
286 mParticles.emplace_back(p);
287 mCurrentParticle0 = p;
288 }
289 mStack.push(p);
290}
291
292void Stack::handleTransportPrimary(TParticle& p)
293{
294 // this function tests whether we really want to transport
295 // this particle and sets the relevant bits accordingly
296
297 if (!p.TestBit(ParticleStatus::kToBeDone) || !p.TestBit(ParticleStatus::kPrimary)) {
298 return;
299 }
300
301 if (!mTransportPrimary(p, mPrimaryParticles)) {
302 p.SetBit(ParticleStatus::kToBeDone, 0);
303 p.SetBit(ParticleStatus::kInhibited, 1);
304 }
305}
306
307void Stack::PushTrack(int toBeDone, TParticle& p)
308{
309 // printf("stack -> Pushing Primary toBeDone %5d %5d parentId %5d pdgCode %5d is %5d entries %5d \n", toBeDone, p.TestBit(ParticleStatus::kToBeDone), p.GetFirstMother(), p.GetPdgCode(), p.GetStatusCode(), mNumberOfEntriesInParticles);
310
311 // This method is called
312 //
313 // - during parallel simulation to push primary particles (called by the stack itself)
314 if (p.TestBit(ParticleStatus::kPrimary)) {
315 // one to one mapping for primaries
316 mIndexMap[mNumberOfPrimaryParticles] = mNumberOfPrimaryParticles;
317 mNumberOfPrimaryParticles++;
318 mPrimaryParticles.push_back(p);
319 // Push particle on the stack
320 if (p.TestBit(ParticleStatus::kToBeDone)) {
321 mNumberOfPrimariesforTracking++;
322 }
323 mStack.push(p);
324 mTracks->emplace_back(p);
325 }
326}
327
331void Stack::SetCurrentTrack(Int_t iTrack)
332{
333 mIndexOfCurrentTrack = iTrack;
334 if (iTrack < mPrimaryParticles.size()) {
335 auto& p = mPrimaryParticles[iTrack];
336 mCurrentParticle = p;
337 mIndexOfCurrentPrimary = iTrack;
338 } else {
339 mCurrentParticle = mCurrentParticle0;
340 }
341}
342
343// calculates a hash based on particle properties
344// hash may serve as seed for this track
345ULong_t getHash(TParticle const& p)
346{
347 auto asLong = [](double x) {
348 return (ULong_t) * (reinterpret_cast<ULong_t*>(&x));
349 };
350
351 ULong_t hash;
352 o2::MCTrackT<double> track(p);
353
354 hash = asLong(track.GetStartVertexCoordinatesX());
355 hash ^= asLong(track.GetStartVertexCoordinatesY());
356 hash ^= asLong(track.GetStartVertexCoordinatesZ());
357 hash ^= asLong(track.GetStartVertexCoordinatesT());
358 hash ^= asLong(track.GetStartVertexMomentumX());
359 hash ^= asLong(track.GetStartVertexMomentumY());
360 hash ^= asLong(track.GetStartVertexMomentumZ());
361 hash += (ULong_t)track.GetPdgCode();
362 return hash;
363}
364
365TParticle* Stack::PopNextTrack(Int_t& iTrack)
366{
367
368 // This functions is mainly used by Geant3?
369 Int_t nprod = (int)(mParticles.size());
370
371 // If end of stack: Return empty pointer
372 if (mStack.empty()) {
373 iTrack = -1;
374 return nullptr;
375 }
376 Bool_t found = kFALSE;
377
378 TParticle* nextParticle = nullptr;
379 while (!found && !mStack.empty()) {
380 // get next particle from stack
381 mCurrentParticle = mStack.top();
382 // remove particle from the top
383 mStack.pop();
384 // test if primary to be transported
385 if (mCurrentParticle.TestBit(ParticleStatus::kToBeDone)) {
386 if (mCurrentParticle.TestBit(ParticleStatus::kPrimary)) {
387 // particle is primary and needs to be tracked -> indicates that previous particle finished
388 mNumberOfPrimariesPopped++;
389 mIndexOfCurrentPrimary = mStack.size();
390 mIndexOfCurrentTrack = mIndexOfCurrentPrimary;
391 } else {
392 mIndexOfCurrentTrack = mCurrentParticle.GetStatusCode();
393 }
394 iTrack = mIndexOfCurrentTrack;
395 if (mDoTrackSeeding) {
396 auto hash = getHash(mCurrentParticle);
397 // LOG(info) << "SEEDING NEW TRACK USING HASH" << hash;
398 // init seed per track
399 o2::base::simRandom()->SetSeed(hash);
401 // NOTE: THE BETTER PLACE WOULD BE IN PRETRACK HOOK BUT THIS DOES NOT SEEM TO WORK
402 // WORKS ONLY WITH G3 SINCE G4 DOES NOT CALL THIS FUNCTION
403 } // .trackSeed ?
404 nextParticle = &mCurrentParticle;
405 found = kTRUE;
406 } else {
407 iTrack = -1;
408 nextParticle = nullptr;
409 }
410 } // while
411 return nextParticle;
412}
413
414TParticle* Stack::PopPrimaryForTracking(Int_t iPrim)
415{
416 // This function is used by Geant4 to setup their own internal stack
417 // printf("PopPrimary for tracking %5d %5d \n", iPrim, mNumberOfPrimaryParticles);
418 // Remark: Contrary to what the interface name is suggesting
419 // this is not a pop operation (but rather a get)
420
421 // Test for index
422 if (iPrim < 0 || iPrim >= mNumberOfPrimaryParticles) {
423 LOG(fatal) << "Stack::PopPrimaryForTracking: Stack: Primary index out of range! " << iPrim << " ";
424 return nullptr;
425 }
426 // Return the iPrim-th TParticle from the fParticle array. This should be
427 // a primary.
428 auto particle = &mPrimaryParticles[iPrim];
429 if (particle->TestBit(ParticleStatus::kToBeDone)) {
430 return particle;
431 } else {
432 return nullptr;
433 }
434}
435
436void Stack::updateEventStats()
437{
438 if (mMCEventStats) {
439 mMCEventStats->setNHits(mHitCounter);
440 mMCEventStats->setNTransportedTracks(mNumberOfEntriesInParticles);
441 mMCEventStats->setNKeptTracks(mTracks->size());
442 }
443}
444
445void Stack::FillTrackArray()
446{
449 LOG(info) << "Stack: " << mTracks->size() << " out of " << mNumberOfEntriesInParticles << " stored \n";
450}
451
452void Stack::FinishPrimary()
453{
454 // Here transport of a primary and all its secondaries is finished
455 // we can do some cleanup of the memory structures
456 mPrimariesDone++;
457 LOG(debug) << "Finish primary hook " << mPrimariesDone;
458 // preserve particles and theire ancestors that produced hits
459
460 auto selected = selectTracks();
461
462 // loop over current particle buffer
463 // - build index map indicesKept
464 // - update mother index information
465 int indexOld = 0;
466 int indexNew = 0;
467 int indexoffset = mTracks->size();
468 int neglected = 0;
469 std::vector<int> indicesKept((int)(mParticles.size()));
470 std::vector<MCTrack> tmpTracks;
471 Int_t ic = 0;
472
473 // mTrackIDtoParticlesEntry
474 // trackID to mTrack -> index in mParticles
475 //
476 // indicesKept
477 // index in mParticles -> index in mTrack - highWaterMark
478 //
479 // mReorderIndices
480 // old (mTrack-highWaterMark) -> new (mTrack-highWaterMark)
481 //
482
483 for (auto& particle : mParticles) {
484 if (particle.getStore() || !mPruneKinematics) {
485 // map the global track index to the new persistent index
486 auto imother = particle.getMotherTrackId();
487 // here mother is relative to the mParticles array
488 if (imother >= 0) {
489 // daughter of a secondary: obtain index from lookup table
490 imother = indicesKept[imother];
491 particle.SetMotherTrackId(imother);
492 }
493 // at this point we have the correct mother index in mParticles or
494 // a negative one which is a pointer to a primary
495 tmpTracks.emplace_back(particle);
496 indicesKept[indexOld] = indexNew;
497 indexNew++;
498 } else {
499 indicesKept[indexOld] = -1;
500 neglected++;
501 }
502 indexOld++;
503 mTracksDone++;
504 }
505 Int_t ntr = (int)(tmpTracks.size());
506 std::vector<int> reOrderedIndices(ntr);
507 std::vector<int> invreOrderedIndices(ntr);
508 for (Int_t i = 0; i < ntr; i++) {
509 invreOrderedIndices[i] = i;
510 reOrderedIndices[i] = i;
511 }
512
513 if (mIsG4Like) {
514 ReorderKine(tmpTracks, reOrderedIndices);
515 for (Int_t i = 0; i < ntr; i++) {
516 Int_t index = reOrderedIndices[i];
517 invreOrderedIndices[index] = i;
518 }
519 }
520 for (Int_t i = 0; i < ntr; i++) {
521 Int_t index = reOrderedIndices[i];
522 auto& particle = tmpTracks[index];
523 Int_t imo = particle.getMotherTrackId();
524 Int_t imo0 = imo;
525 if (imo >= 0) {
526 imo = invreOrderedIndices[imo];
527 }
528 imo += indexoffset;
529 particle.SetMotherTrackId(imo);
530 mTracks->emplace_back(particle);
531 auto& mother = mTracks->at(imo);
532 if (mother.getFirstDaughterTrackId() == -1) {
533 mother.SetFirstDaughterTrackId((int)(mTracks->size()) - 1);
534 }
535 mother.SetLastDaughterTrackId((int)(mTracks->size()) - 1);
536 }
537
538 //
539 // Update index map
540 //
541 Int_t imax = mNumberOfEntriesInParticles;
542 Int_t imin = imax - mParticles.size();
543 for (Int_t idTrack = imin; idTrack < imax; idTrack++) {
544 Int_t index1 = mTrackIDtoParticlesEntry[idTrack];
545 Int_t index2 = indicesKept[index1];
546 if (index2 == -1) {
547 continue;
548 }
549 Int_t index3 = (mIsG4Like) ? invreOrderedIndices[index2] : index2;
550 mIndexMap[idTrack] = index3 + indexoffset;
551 }
552
553 // we can now clear the particles buffer!
554 reOrderedIndices.clear();
555 invreOrderedIndices.clear();
556 mParticles.clear();
557 tmpTracks.clear();
558 mTransportedIDs.clear();
559 mTrackIDtoParticlesEntry.clear();
560 mIndexOfPrimaries.clear();
561}
562
563void Stack::UpdateTrackIndex(TRefArray* detList)
564{
565 // we can avoid any updating in case no tracks have been filtered out
566 // check this like this
567 if (mIndexMap.size() == 0) {
568 LOG(info) << "No TrackIndex update necessary\n";
569 return;
570 }
571
572 // we are getting the detectorlist from FairRoot as TRefArray
573 // at each call, but this list never changes so we cache it here
574 // as the right type to avoid repeated dynamic casts
575 if (mActiveDetectors.size() == 0) {
576 if (detList == nullptr) {
577 LOG(fatal) << "No detList passed to Stack";
578 }
579 auto iter = detList->MakeIterator();
580 while (auto det = iter->Next()) {
581 auto o2det = dynamic_cast<o2::base::Detector*>(det);
582 if (o2det) {
583 mActiveDetectors.emplace_back(o2det);
584 } else {
585 LOG(info) << "Found nonconforming detector " << det->GetName();
586 }
587 }
588 }
589
590 LOG(debug) << "Stack::UpdateTrackIndex: Stack: Updating track indices...";
591 Int_t nColl = 0;
592
593 // update track references
594 // use some caching since repeated trackIDs
595 for (auto& ref : *mTrackRefs) {
596 const auto id = ref.getTrackID();
597 auto iter = mIndexMap.find(id);
598 if (iter == mIndexMap.end()) {
599 LOG(info) << "Invalid trackref ... needs to be rmoved \n";
600 ref.setTrackID(-1);
601 } else {
602 ref.setTrackID(iter->second);
603 }
604 }
605
606 // sort trackrefs according to new track index
607 // then according to track length
608 std::sort(mTrackRefs->begin(), mTrackRefs->end(), [](const o2::TrackReference& a, const o2::TrackReference& b) {
609 if (a.getTrackID() == b.getTrackID()) {
610 return a.getLength() < b.getLength();
611 }
612 return a.getTrackID() < b.getTrackID();
613 });
614
615 for (auto det : mActiveDetectors) {
616 // update the track indices by delegating to specialized detector functions
617 det->updateHitTrackIndices(mIndexMap);
618 } // List of active detectors
619
620 LOG(debug) << "Stack::UpdateTrackIndex: ...stack and " << nColl << " collections updated.";
621}
622
623void Stack::Reset()
624{
625
626 mIndexOfCurrentTrack = -1;
627 mNumberOfPrimaryParticles = mNumberOfEntriesInParticles = mNumberOfEntriesInTracks = 0;
628 while (!mStack.empty()) {
629 mStack.pop();
630 }
631 mParticles.clear();
632 mTracks->clear();
633 if (!mIsExternalMode && (mPrimariesDone != mNumberOfPrimariesforTracking)) {
634 LOG(fatal) << "Inconsistency in primary particles treated " << mPrimariesDone << " vs expected "
635 << mNumberOfPrimariesforTracking << "\n(This points to a flaw in the stack logic)";
636 }
637 mPrimariesDone = 0;
638 mNumberOfPrimariesforTracking = 0;
639 mNumberOfPrimariesPopped = 0;
640 mPrimaryParticles.clear();
641 mTrackRefs->clear();
642 mTrackIDtoParticlesEntry.clear();
643 mIndexMap.clear();
644 mHitCounter = 0;
645}
646
647void Stack::Register()
648{
649 FairRootManager::Instance()->RegisterAny("MCTrack", mTracks, kTRUE);
650 FairRootManager::Instance()->RegisterAny("TrackRefs", mTrackRefs, kTRUE);
651}
652
653void Stack::Print(Int_t iVerbose) const
654{
655 cout << "-I- Stack: Number of primaries = " << mNumberOfPrimaryParticles << endl;
656 cout << " Total number of particles = " << mNumberOfEntriesInParticles << endl;
657 cout << " Number of tracks in output = " << mNumberOfEntriesInTracks << endl;
658 if (iVerbose) {
659 for (auto& track : *mTracks) {
660 track.Print();
661 }
662 }
663}
664
665void Stack::Print(Option_t* option) const
666{
667 Int_t verbose = 0;
668 if (option) {
669 verbose = 1;
670 }
671 Print(verbose);
672}
673
674void Stack::addHit(int iDet)
675{
676 // translate detector ID to bit id
677 const auto bitID = o2::base::Detector::getDetId2HitBitIndex()[iDet];
678
679 if (mIndexOfCurrentTrack < mNumberOfPrimaryParticles) {
680 auto& part = mTracks->at(mIndexOfCurrentTrack);
681 part.setHit(bitID);
682
683 } else {
684 Int_t iTrack = mTrackIDtoParticlesEntry[mIndexOfCurrentTrack];
685 auto& part = mParticles[iTrack];
686 part.setHit(bitID);
687 }
688 mCurrentParticle.SetBit(ParticleStatus::kHasHits, 1);
689 mHitCounter++;
690}
691void Stack::modifiesHit(int iDet)
692{
693 // flag only; hit mask, kHasHits and hit counter stay untouched
694 if (mIndexOfCurrentTrack < mNumberOfPrimaryParticles) {
695 mTracks->at(mIndexOfCurrentTrack).setContributesToAHit();
696 } else {
697 Int_t iTrack = mTrackIDtoParticlesEntry[mIndexOfCurrentTrack];
698 mParticles[iTrack].setContributesToAHit();
699 }
700}
701void Stack::addHit(int iDet, Int_t iTrack)
702{
703 mHitCounter++;
704 auto& part = mParticles[iTrack];
705 // fetch the bit encoding for hits
706 const auto bitID = o2::base::Detector::getDetId2HitBitIndex()[iDet];
707 part.setHit(bitID);
708 mCurrentParticle.SetBit(ParticleStatus::kHasHits, 1);
709}
710
711Int_t Stack::GetCurrentParentTrackNumber() const
712{
713 TParticle* currentPart = GetCurrentTrack();
714 if (currentPart) {
715 return currentPart->GetFirstMother();
716 } else {
717 return -1;
718 }
719}
720
721bool Stack::selectTracks()
722{
723 bool tracksdiscarded = false;
724 // Check particles in the fParticle array
725 int prim = -1; // counter how many primaries seen (mainly to constrain search in motherindex remapping)
726 LOG(debug) << "Stack: Entering track selection on " << mParticles.size() << " tracks";
727 for (auto& thisPart : mParticles) {
728 Bool_t store = kTRUE;
729 // Get track parameters
730 Bool_t isPrimary = (thisPart.getProcess() == 0);
731 Int_t iMother = thisPart.getMotherTrackId();
732 auto& mother = mParticles[iMother];
733 Bool_t motherIsPrimary = (iMother < mNumberOfPrimaryParticles);
734
735 if (isPrimary) {
736 prim++;
737 // for primaries we are done quickly
738 // in fact the primary has already been stored
739 // so this should not happen
740 store = kTRUE;
741 } else {
742 // for other particles we potentially need to correct the mother indices
743 if (!motherIsPrimary) {
744 // the mapping is from the index in the stack to the index in mParticles
745 thisPart.SetMotherTrackId(mTrackIDtoParticlesEntry[iMother]);
746 } else {
747 // for a secondary which is a direct decendant of a primary use a negative index which will be restored later
748 thisPart.SetMotherTrackId(iMother - (int)(mTracks->size()));
749 }
750 // no secondaries; also done
751 if (!mStoreSecondaries) {
752 store = kFALSE;
753 tracksdiscarded = true;
754 } else {
755 // Calculate number of hits created by this track
756 // Note: we only distinguish between no hit and more than 0 hits
757 int nHits = thisPart.hasHits();
758 // Check for cuts (store primaries in any case)
759 if (nHits < mMinHits) {
760 store = kFALSE;
761 tracksdiscarded = true;
762 }
763 // only if we have non-trival energy cut
764 if (mEnergyCut > 0.) {
765 Double_t energy = thisPart.GetEnergy();
766 Double_t mass = thisPart.GetMass();
767 Double_t eKin = energy - mass;
768 if (eKin < mEnergyCut) {
769 store = kFALSE;
770 tracksdiscarded = true;
771 }
772 }
773 if (keepPhysics(thisPart)) {
774 store = kTRUE;
775 tracksdiscarded = false;
776 }
777 }
778 }
779
780 store = store || thisPart.getStore();
781 thisPart.setStore(store);
782 }
783
784 // If flag is set, flag recursively mothers of selected tracks
785 //
786 if (mStoreMothers) {
787 for (auto& particle : mParticles) {
788 if (particle.getStore()) {
789 Int_t iMother = particle.getMotherTrackId();
790 while (iMother >= 0) {
791 auto& mother = mParticles[iMother];
792 mother.setStore(true);
793 iMother = mother.getMotherTrackId();
794 } // while mother
795 } // store ?
796 } // particle loop
797 }
798
799 return !tracksdiscarded;
800}
801
802bool Stack::isPrimary(const MCTrack& part)
803{
805 if (part.getProcess() == kPPrimary || part.getMotherTrackId() < 0) {
806 return true;
807 }
809 return false;
810}
811
812bool Stack::isFromPrimaryDecayChain(const MCTrack& part)
813{
818 if (part.getProcess() != kPDecay) {
819 return false;
820 }
822 auto imother = part.getMotherTrackId();
823 auto mother = mParticles[imother];
824 if (isPrimary(mother)) {
825 return true;
826 }
828 return isFromPrimaryDecayChain(mother);
829}
830
831bool Stack::isFromPrimaryPairProduction(const MCTrack& part)
832{
838 if (part.getProcess() != kPPair) {
839 return false;
840 }
842 auto imother = part.getMotherTrackId();
843 auto mother = mParticles[imother];
844 if (isPrimary(mother)) {
845 return true;
846 }
848 return isFromPrimaryDecayChain(mother);
849}
850
851bool Stack::keepPhysics(const MCTrack& part)
852{
853 //
854 // Some particles have to kept on the stack for reasons motivated
855 // by physics analysis. Decision is put here.
856 //
857
858 if (isPrimary(part)) {
859 return true;
860 }
861 if (isFromPrimaryDecayChain(part)) {
862 return true;
863 }
864 if (isFromPrimaryPairProduction(part)) {
865 return true;
866 }
867
868 return false;
869}
870
871TClonesArray* Stack::GetListOfParticles()
872{
873 LOG(fatal) << "Stack::GetListOfParticles interface not implemented\n";
874 return nullptr;
875}
876
877bool Stack::isTrackDaughterOf(int trackid, int parentid) const
878{
879 // a daughter trackid should be larger than parentid
880 if (trackid < parentid) {
881 return false;
882 }
883
884 if (trackid == parentid) {
885 return true;
886 }
887
888 auto mother = getMotherTrackId(trackid);
889 while (mother != -1) {
890 if (mother == parentid) {
891 return true;
892 }
893 mother = getMotherTrackId(mother);
894 }
895 return false;
896}
897
898void Stack::fillParentIDs(std::vector<int>& parentids) const
899{
900 parentids.clear();
901 int mother = mIndexOfCurrentTrack;
902 do {
903 if (mother != -1) {
904 parentids.push_back(mother);
905 }
906 mother = getMotherTrackId(mother);
907 } while (mother != -1);
908}
909
910void Stack::ReorderKine(std::vector<MCTrack>& particles, std::vector<int>& reOrderedIndices)
911{
912 //
913 // Particles are ordered in a way that descendants of a particle appear next to each other.
914 // This has the advantage that their position in the stack can be identified by two number,
915 // for example the index of the first and last descentant.
916 // The result of the ordering is returned via the look-up table reOrderedIndices
917 //
918
919 Int_t ntr = (int)(particles.size());
920 std::vector<bool> done(ntr, false);
921
922 int indexoffset = mTracks->size();
923 Int_t index = 0;
924 Int_t imoOld = 0;
925 for (Int_t i = 0; i < ntr; i++) {
926 reOrderedIndices[i] = i;
927 }
928
929 for (Int_t i = -1; i < ntr; i++) {
930 if (i != -1) {
931 // secondaries
932 if (!done[i]) {
933 reOrderedIndices[index] = i;
934 index++;
935 done[i] = true;
936 }
937 imoOld = i;
938 } else {
939 // current primary
940 imoOld = mIndexOfCurrentPrimary - indexoffset;
941 }
942 for (Int_t j = i + 1; j < ntr; j++) {
943 if (!done[j]) {
944 if ((particles[j]).getMotherTrackId() == imoOld) {
945 reOrderedIndices[index] = j;
946 index++;
947 done[j] = true;
948 } // child found
949 } // done
950 } // j
951 } // i
952}
953
954FairGenericStack* Stack::CloneStack() const { return new o2::data::Stack(*this); }
955
Definition of the Detector class.
Definition of the Stack class.
uint32_t hash
std::ostringstream debug
int16_t time
Definition RawEventData.h:4
int32_t i
bool done
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone Processing proc_rtc Replace constant variables static by constexpr expressions false
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone proc
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone Processing proc_rtc Replace constant variables static by constexpr expressions Compile RTC in deterministic with NO_FAST_MATH flags and GPUCA_DETERMINISTIC_MODE define Use RTC to optimize GPU code h configStandalone Processing proc_rtctech Use a file lock to serialize access to the cache folder Print launch bounds used for RTC code as debugging option
ClassImp(IdPath)
Definition of the MCTrack class.
@ kKeep
@ kHasHits
@ kInhibited
@ kPrimary
@ kToBeDone
uint32_t j
Definition RawData.h:0
void insertInVector(std::vector< T > &v, I index, T e)
Definition Stack.cxx:76
ULong_t getHash(TParticle const &p)
Definition Stack.cxx:345
FairGenericStack & operator=(const FairGenericStack &)
void RegisterAny(const char *name, T *&obj, Bool_t toFile)
static FairRootManager * Instance()
int getProcess() const
get the production process (id) of this track
Definition MCTrack.h:230
Int_t getMotherTrackId() const
Definition MCTrack.h:73
static std::vector< int > const & getDetId2HitBitIndex()
Definition Detector.h:244
static VMCSeederService const & instance()
void ReorderKine(std::vector< MCTrack > &particles, std::vector< int > &reOrderedIndices)
Definition Stack.cxx:910
int getMotherTrackId(int) const
Allow to query the direct mother track ID of an arbitrary trackID managed by stack.
Definition Stack.h:351
virtual void Print(Int_t iVerbose=0) const
Definition Stack.cxx:653
TParticle * GetCurrentTrack() const override
Definition Stack.h:125
void PushTrack(Int_t toBeDone, Int_t parentID, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e, Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, TMCProcess proc, Int_t &ntr, Double_t weight, Int_t is) override
Definition Stack.cxx:211
std::function< bool(const TParticle &p, const std::vector< TParticle > &particles)> TransportFcn
Definition Stack.h:246
GLint GLenum GLint x
Definition glcorearb.h:403
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLuint index
Definition glcorearb.h:781
GLuint GLuint GLfloat weight
Definition glcorearb.h:5477
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum GLfloat param
Definition glcorearb.h:271
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLint ref
Definition glcorearb.h:291
TRandom * simRandom()
Definition SimRandom.cxx:22
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Stack & operator=(Stack &)=delete
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"