22#include "FairDetector.h"
23#include <fairlogger/Logger.h>
24#include "FairRootManager.h"
29#include "TLorentzVector.h"
32#include "TVirtualMC.h"
33#include "TMCProcess.h"
46template <
typename T,
typename I>
49 auto currentsize =
v.size();
50 if (
index >= currentsize) {
51 const auto newsize = std::max(
index + 1, (I)(1 + currentsize * 1.2));
52 v.resize(newsize, T(-1));
64 mTrackIDtoParticlesEntry(1000000, -1),
66 mIndexOfCurrentTrack(-1),
67 mIndexOfCurrentPrimary(-1),
68 mNumberOfPrimaryParticles(0),
69 mNumberOfEntriesInParticles(0),
70 mNumberOfEntriesInTracks(0),
71 mNumberOfPrimariesforTracking(0),
72 mNumberOfPrimariesPopped(0),
74 mStoreSecondaries(kTRUE),
80 auto vmc = TVirtualMC::GetMC();
82 mIsG4Like = !(vmc->SecondariesAreOrdered());
87 if (
param.transportPrimary.compare(
"none") == 0) {
88 transportPrimary = [](
const TParticle& p,
const std::vector<TParticle>& particles) {
91 }
else if (
param.transportPrimary.compare(
"all") == 0) {
92 transportPrimary = [](
const TParticle& p,
const std::vector<TParticle>& particles) {
95 }
else if (
param.transportPrimary.compare(
"barrel") == 0) {
96 transportPrimary = [](
const TParticle& p,
const std::vector<TParticle>& particles) {
97 return (std::fabs(p.Eta()) < 2.0);
99 }
else if (
param.transportPrimary.compare(
"external") == 0) {
100 transportPrimary = o2::conf::GetFromMacro<o2::data::Stack::TransportFcn>(
param.transportPrimaryFileName,
101 param.transportPrimaryFuncName,
102 "o2::data::Stack::TransportFcn",
"stack_transport_primary");
103 if (!mTransportPrimary) {
104 LOG(fatal) <<
"Failed to retrieve external \'transportPrimary\' function: problem with configuration ";
106 LOG(info) <<
"Successfully retrieve external \'transportPrimary\' frunction: " <<
param.transportPrimaryFileName;
108 LOG(fatal) <<
"unsupported \'trasportPrimary\' mode: " <<
param.transportPrimary;
111 if (
param.transportPrimaryInvert) {
112 mTransportPrimary = [transportPrimary](
const TParticle& p,
const std::vector<TParticle>& particles) {
return !transportPrimary; };
114 mTransportPrimary = transportPrimary;
124 mIndexOfCurrentTrack(-1),
125 mIndexOfCurrentPrimary(-1),
126 mNumberOfPrimaryParticles(0),
127 mNumberOfEntriesInParticles(0),
128 mNumberOfEntriesInTracks(0),
129 mNumberOfPrimariesforTracking(0),
130 mNumberOfPrimariesPopped(0),
131 mStoreMothers(rhs.mStoreMothers),
132 mStoreSecondaries(rhs.mStoreSecondaries),
133 mMinHits(rhs.mMinHits),
134 mEnergyCut(rhs.mEnergyCut),
136 mIsG4Like(rhs.mIsG4Like)
138 LOG(
debug) <<
"copy constructor called";
139 mTracks =
new std::vector<MCTrack>();
151 LOG(fatal) <<
"operator= called";
158 FairGenericStack::operator=(rhs);
159 mTracks =
new std::vector<MCTrack>(rhs.mTracks->size());
160 mIndexOfCurrentTrack = -1;
161 mIndexOfCurrentPrimary = -1;
162 mNumberOfPrimaryParticles = 0;
163 mNumberOfEntriesInParticles = 0;
164 mNumberOfEntriesInTracks = 0;
165 mNumberOfPrimariesforTracking = 0;
166 mNumberOfPrimariesPopped = 0;
167 mStoreMothers = rhs.mStoreMothers;
168 mStoreSecondaries = rhs.mStoreSecondaries;
169 mMinHits = rhs.mMinHits;
170 mEnergyCut = rhs.mEnergyCut;
171 mIsG4Like = rhs.mIsG4Like;
176void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e,
177 Double_t vx, Double_t vy, Double_t vz, Double_t
time, Double_t polx, Double_t poly, Double_t polz,
178 TMCProcess proc, Int_t& ntr, Double_t
weight, Int_t is)
180 PushTrack(toBeDone, parentId, pdgCode, px, py, pz, e, vx, vy, vz,
time, polx, poly, polz, proc, ntr,
weight, is, -1);
183void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e,
184 Double_t vx, Double_t vy, Double_t vz, Double_t
time, Double_t polx, Double_t poly, Double_t polz,
185 TMCProcess proc, Int_t& ntr, Double_t
weight, Int_t is, Int_t secondparentId)
187 PushTrack(toBeDone, parentId, pdgCode, px, py, pz, e, vx, vy, vz,
time, polx, poly, polz, proc, ntr,
weight, is, secondparentId, -1, -1, proc);
190void Stack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e,
191 Double_t vx, Double_t vy, Double_t vz, Double_t
time, Double_t polx, Double_t poly, Double_t polz,
192 TMCProcess proc, Int_t& ntr, Double_t
weight, Int_t is, Int_t secondparentId, Int_t daughter1Id, Int_t daughter2Id,
209 Int_t trackId = mNumberOfEntriesInParticles;
214 Int_t iStatus = (proc == kPPrimary) ? is : trackId;
215 TParticle p(pdgCode, iStatus, parentId, secondparentId, daughter1Id, daughter2Id, px, py, pz, e, vx, vy, vz,
time);
216 p.SetPolarisation(polx, poly, polz);
221 mNumberOfEntriesInParticles++;
223 insertInVector(mTrackIDtoParticlesEntry, trackId, (
int)(mParticles.size()));
225 handleTransportPrimary(p);
240 p.SetUniqueID(proc2);
242 mIndexMap[trackId] = trackId;
245 mNumberOfPrimariesforTracking++;
247 mNumberOfPrimaryParticles++;
248 mPrimaryParticles.push_back(p);
249 mTracks->emplace_back(p);
251 mParticles.emplace_back(p);
252 mCurrentParticle0 = p;
257void Stack::handleTransportPrimary(TParticle& p)
266 if (!mTransportPrimary(p, mPrimaryParticles)) {
272void Stack::PushTrack(
int toBeDone, TParticle& p)
281 mIndexMap[mNumberOfPrimaryParticles] = mNumberOfPrimaryParticles;
282 mNumberOfPrimaryParticles++;
283 mPrimaryParticles.push_back(p);
286 mNumberOfPrimariesforTracking++;
289 mTracks->emplace_back(p);
296void Stack::SetCurrentTrack(Int_t iTrack)
298 mIndexOfCurrentTrack = iTrack;
299 if (iTrack < mPrimaryParticles.size()) {
300 auto& p = mPrimaryParticles[iTrack];
301 mCurrentParticle = p;
302 mIndexOfCurrentPrimary = iTrack;
304 mCurrentParticle = mCurrentParticle0;
312 auto asLong = [](
double x) {
313 return (ULong_t) * (
reinterpret_cast<ULong_t*
>(&
x));
330TParticle* Stack::PopNextTrack(Int_t& iTrack)
334 Int_t nprod = (
int)(mParticles.size());
337 if (mStack.empty()) {
341 Bool_t found = kFALSE;
343 TParticle* nextParticle =
nullptr;
344 while (!found && !mStack.empty()) {
346 mCurrentParticle = mStack.top();
353 mNumberOfPrimariesPopped++;
354 mIndexOfCurrentPrimary = mStack.size();
355 mIndexOfCurrentTrack = mIndexOfCurrentPrimary;
357 mIndexOfCurrentTrack = mCurrentParticle.GetStatusCode();
359 iTrack = mIndexOfCurrentTrack;
360 if (mDoTrackSeeding) {
361 auto hash =
getHash(mCurrentParticle);
364 gRandom->SetSeed(hash);
369 nextParticle = &mCurrentParticle;
373 nextParticle =
nullptr;
379TParticle* Stack::PopPrimaryForTracking(Int_t iPrim)
387 if (iPrim < 0 || iPrim >= mNumberOfPrimaryParticles) {
388 LOG(fatal) <<
"Stack::PopPrimaryForTracking: Stack: Primary index out of range! " << iPrim <<
" ";
393 auto particle = &mPrimaryParticles[iPrim];
401void Stack::updateEventStats()
404 mMCEventStats->
setNHits(mHitCounter);
410void Stack::FillTrackArray()
414 LOG(info) <<
"Stack: " << mTracks->size() <<
" out of " << mNumberOfEntriesInParticles <<
" stored \n";
417void Stack::FinishPrimary()
422 LOG(
debug) <<
"Finish primary hook " << mPrimariesDone;
425 auto selected = selectTracks();
432 int indexoffset = mTracks->size();
434 std::vector<int> indicesKept((
int)(mParticles.size()));
435 std::vector<MCTrack> tmpTracks;
448 for (
auto& particle : mParticles) {
449 if (particle.getStore() || !mPruneKinematics) {
451 auto imother = particle.getMotherTrackId();
455 imother = indicesKept[imother];
456 particle.SetMotherTrackId(imother);
460 tmpTracks.emplace_back(particle);
461 indicesKept[indexOld] = indexNew;
464 indicesKept[indexOld] = -1;
470 Int_t ntr = (
int)(tmpTracks.size());
471 std::vector<int> reOrderedIndices(ntr);
472 std::vector<int> invreOrderedIndices(ntr);
473 for (Int_t
i = 0;
i < ntr;
i++) {
474 invreOrderedIndices[
i] =
i;
475 reOrderedIndices[
i] =
i;
480 for (Int_t
i = 0;
i < ntr;
i++) {
481 Int_t
index = reOrderedIndices[
i];
482 invreOrderedIndices[
index] =
i;
485 for (Int_t
i = 0;
i < ntr;
i++) {
486 Int_t
index = reOrderedIndices[
i];
487 auto& particle = tmpTracks[
index];
488 Int_t imo = particle.getMotherTrackId();
491 imo = invreOrderedIndices[imo];
494 particle.SetMotherTrackId(imo);
495 mTracks->emplace_back(particle);
496 auto& mother = mTracks->at(imo);
497 if (mother.getFirstDaughterTrackId() == -1) {
498 mother.SetFirstDaughterTrackId((
int)(mTracks->size()) - 1);
500 mother.SetLastDaughterTrackId((
int)(mTracks->size()) - 1);
506 Int_t imax = mNumberOfEntriesInParticles;
507 Int_t imin = imax - mParticles.size();
508 for (Int_t idTrack = imin; idTrack < imax; idTrack++) {
509 Int_t index1 = mTrackIDtoParticlesEntry[idTrack];
510 Int_t index2 = indicesKept[index1];
514 Int_t index3 = (mIsG4Like) ? invreOrderedIndices[index2] : index2;
515 mIndexMap[idTrack] = index3 + indexoffset;
519 reOrderedIndices.clear();
520 invreOrderedIndices.clear();
523 mTransportedIDs.clear();
524 mTrackIDtoParticlesEntry.clear();
525 mIndexOfPrimaries.clear();
528void Stack::UpdateTrackIndex(TRefArray* detList)
532 if (mIndexMap.size() == 0) {
533 LOG(info) <<
"No TrackIndex update necessary\n";
540 if (mActiveDetectors.size() == 0) {
541 if (detList ==
nullptr) {
542 LOG(fatal) <<
"No detList passed to Stack";
544 auto iter = detList->MakeIterator();
545 while (
auto det = iter->Next()) {
548 mActiveDetectors.emplace_back(o2det);
550 LOG(info) <<
"Found nonconforming detector " << det->GetName();
555 LOG(
debug) <<
"Stack::UpdateTrackIndex: Stack: Updating track indices...";
560 for (
auto&
ref : *mTrackRefs) {
561 const auto id =
ref.getTrackID();
562 auto iter = mIndexMap.find(
id);
563 if (iter == mIndexMap.end()) {
564 LOG(info) <<
"Invalid trackref ... needs to be rmoved \n";
567 ref.setTrackID(iter->second);
574 if (a.getTrackID() == b.getTrackID()) {
575 return a.getLength() < b.getLength();
577 return a.getTrackID() <
b.getTrackID();
580 for (
auto det : mActiveDetectors) {
582 det->updateHitTrackIndices(mIndexMap);
585 LOG(
debug) <<
"Stack::UpdateTrackIndex: ...stack and " << nColl <<
" collections updated.";
591 mIndexOfCurrentTrack = -1;
592 mNumberOfPrimaryParticles = mNumberOfEntriesInParticles = mNumberOfEntriesInTracks = 0;
593 while (!mStack.empty()) {
598 if (!mIsExternalMode && (mPrimariesDone != mNumberOfPrimariesforTracking)) {
599 LOG(fatal) <<
"Inconsistency in primary particles treated " << mPrimariesDone <<
" vs expected "
600 << mNumberOfPrimariesforTracking <<
"\n(This points to a flaw in the stack logic)";
603 mNumberOfPrimariesforTracking = 0;
604 mNumberOfPrimariesPopped = 0;
605 mPrimaryParticles.clear();
607 mTrackIDtoParticlesEntry.clear();
611void Stack::Register()
613 FairRootManager::Instance()->RegisterAny(
"MCTrack", mTracks, kTRUE);
614 FairRootManager::Instance()->RegisterAny(
"TrackRefs", mTrackRefs, kTRUE);
617void Stack::Print(Int_t iVerbose)
const
619 cout <<
"-I- Stack: Number of primaries = " << mNumberOfPrimaryParticles << endl;
620 cout <<
" Total number of particles = " << mNumberOfEntriesInParticles << endl;
621 cout <<
" Number of tracks in output = " << mNumberOfEntriesInTracks << endl;
623 for (
auto& track : *mTracks) {
629void Stack::Print(Option_t* option)
const
638void Stack::addHit(
int iDet)
643 if (mIndexOfCurrentTrack < mNumberOfPrimaryParticles) {
644 auto& part = mTracks->at(mIndexOfCurrentTrack);
648 Int_t iTrack = mTrackIDtoParticlesEntry[mIndexOfCurrentTrack];
649 auto& part = mParticles[iTrack];
655void Stack::addHit(
int iDet, Int_t iTrack)
658 auto& part = mParticles[iTrack];
665Int_t Stack::GetCurrentParentTrackNumber()
const
669 return currentPart->GetFirstMother();
675bool Stack::selectTracks()
677 bool tracksdiscarded =
false;
680 LOG(
debug) <<
"Stack: Entering track selection on " << mParticles.size() <<
" tracks";
681 for (
auto& thisPart : mParticles) {
682 Bool_t store = kTRUE;
684 Bool_t isPrimary = (thisPart.getProcess() == 0);
685 Int_t iMother = thisPart.getMotherTrackId();
686 auto& mother = mParticles[iMother];
687 Bool_t motherIsPrimary = (iMother < mNumberOfPrimaryParticles);
697 if (!motherIsPrimary) {
699 thisPart.SetMotherTrackId(mTrackIDtoParticlesEntry[iMother]);
702 thisPart.SetMotherTrackId(iMother - (
int)(mTracks->size()));
705 if (!mStoreSecondaries) {
707 tracksdiscarded =
true;
711 int nHits = thisPart.hasHits();
713 if (nHits < mMinHits) {
715 tracksdiscarded =
true;
718 if (mEnergyCut > 0.) {
719 Double_t energy = thisPart.GetEnergy();
720 Double_t mass = thisPart.GetMass();
721 Double_t eKin = energy - mass;
722 if (eKin < mEnergyCut) {
724 tracksdiscarded =
true;
727 if (keepPhysics(thisPart)) {
729 tracksdiscarded =
false;
734 store = store || thisPart.getStore();
735 thisPart.setStore(store);
741 for (
auto& particle : mParticles) {
742 if (particle.getStore()) {
743 Int_t iMother = particle.getMotherTrackId();
744 while (iMother >= 0) {
745 auto& mother = mParticles[iMother];
746 mother.setStore(
true);
747 iMother = mother.getMotherTrackId();
753 return !tracksdiscarded;
756bool Stack::isPrimary(
const MCTrack& part)
766bool Stack::isFromPrimaryDecayChain(
const MCTrack& part)
777 auto mother = mParticles[imother];
778 if (isPrimary(mother)) {
782 return isFromPrimaryDecayChain(mother);
785bool Stack::isFromPrimaryPairProduction(
const MCTrack& part)
797 auto mother = mParticles[imother];
798 if (isPrimary(mother)) {
802 return isFromPrimaryDecayChain(mother);
805bool Stack::keepPhysics(
const MCTrack& part)
812 if (isPrimary(part)) {
815 if (isFromPrimaryDecayChain(part)) {
818 if (isFromPrimaryPairProduction(part)) {
825TClonesArray* Stack::GetListOfParticles()
827 LOG(fatal) <<
"Stack::GetListOfParticles interface not implemented\n";
831bool Stack::isTrackDaughterOf(
int trackid,
int parentid)
const
834 if (trackid < parentid) {
838 if (trackid == parentid) {
843 while (mother != -1) {
844 if (mother == parentid) {
852void Stack::fillParentIDs(std::vector<int>& parentids)
const
855 int mother = mIndexOfCurrentTrack;
858 parentids.push_back(mother);
861 }
while (mother != -1);
864void Stack::ReorderKine(std::vector<MCTrack>& particles, std::vector<int>& reOrderedIndices)
873 Int_t ntr = (
int)(particles.size());
874 std::vector<bool>
done(ntr,
false);
876 int indexoffset = mTracks->size();
879 for (Int_t
i = 0;
i < ntr;
i++) {
880 reOrderedIndices[
i] =
i;
883 for (Int_t
i = -1;
i < ntr;
i++) {
887 reOrderedIndices[
index] =
i;
894 imoOld = mIndexOfCurrentPrimary - indexoffset;
896 for (Int_t
j =
i + 1;
j < ntr;
j++) {
899 reOrderedIndices[
index] =
j;
Definition of the Detector class.
Definition of the Stack class.
Definition of the MCTrack class.
void insertInVector(std::vector< T > &v, I index, T e)
ULong_t getHash(TParticle const &p)
int getProcess() const
get the production process (id) of this track
Double_t GetStartVertexMomentumZ() const
Double_t GetStartVertexMomentumX() const
Double_t GetStartVertexCoordinatesY() const
Double_t GetStartVertexCoordinatesZ() const
Double_t GetStartVertexMomentumY() const
Double_t GetStartVertexCoordinatesT() const
Double_t GetStartVertexCoordinatesX() const
Int_t GetPdgCode() const
Accessors.
Int_t getMotherTrackId() const
static std::vector< int > const & getDetId2HitBitIndex()
static VMCSeederService const & instance()
static const StackParam & Instance()
void ReorderKine(std::vector< MCTrack > &particles, std::vector< int > &reOrderedIndices)
int getMotherTrackId(int) const
Allow to query the direct mother track ID of an arbitrary trackID managed by stack.
virtual void Print(Int_t iVerbose=0) const
TParticle * GetCurrentTrack() const override
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
std::function< bool(const TParticle &p, const std::vector< TParticle > &particles)> TransportFcn
GLuint GLuint GLfloat weight
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"