#include <TClonesArray.h>
#include <TObjArray.h>
#include <TPDGCode.h>
#include <TMCProcess.h>
#include <TParticle.h>
#include <TParticlePDG.h>
#include <TDatabasePDG.h>
#include <TTree.h>
#include <TDirectory.h>
#include "AliLog.h"
#include "AliStack.h"
ClassImp(AliStack)
AliStack::AliStack():
fParticles("TParticle", 1000),
fParticleMap(),
fParticleFileMap(0),
fParticleBuffer(0),
fCurrentTrack(0),
fTreeK(0),
fNtrack(0),
fNprimary(0),
fCurrent(-1),
fCurrentPrimary(-1),
fHgwmk(0),
fLoadPoint(0),
fTrackLabelMap(0)
{
}
AliStack::AliStack(Int_t size, const char* ):
fParticles("TParticle",1000),
fParticleMap(size),
fParticleFileMap(0),
fParticleBuffer(0),
fCurrentTrack(0),
fTreeK(0),
fNtrack(0),
fNprimary(0),
fCurrent(-1),
fCurrentPrimary(-1),
fHgwmk(0),
fLoadPoint(0),
fTrackLabelMap(0)
{
}
AliStack::AliStack(const AliStack& st):
TVirtualMCStack(st),
fParticles("TParticle",1000),
fParticleMap(*(st.Particles())),
fParticleFileMap(st.fParticleFileMap),
fParticleBuffer(0),
fCurrentTrack(0),
fTreeK((TTree*)(st.fTreeK->Clone())),
fNtrack(st.GetNtrack()),
fNprimary(st.GetNprimary()),
fCurrent(-1),
fCurrentPrimary(-1),
fHgwmk(0),
fLoadPoint(0),
fTrackLabelMap(0)
{
}
void AliStack::Copy(TObject&) const
{
AliFatal("Not implemented!");
}
AliStack::~AliStack()
{
fParticles.Clear();
}
void AliStack::PushTrack(Int_t done, Int_t parent, Int_t pdg, const Float_t *pmom,
const Float_t *vpos, const Float_t *polar, Float_t tof,
TMCProcess mech, Int_t &ntr, Float_t weight, Int_t is)
{
TParticlePDG* pmc = TDatabasePDG::Instance()->GetParticle(pdg);
if (pmc) {
Float_t mass = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
Float_t e=TMath::Sqrt(mass*mass+pmom[0]*pmom[0]+
pmom[1]*pmom[1]+pmom[2]*pmom[2]);
PushTrack(done, parent, pdg, pmom[0], pmom[1], pmom[2], e,
vpos[0], vpos[1], vpos[2], tof, polar[0], polar[1], polar[2],
mech, ntr, weight, is);
} else {
AliWarning(Form("Particle type %d not defined in PDG Database !", pdg));
AliWarning("Particle skipped !");
}
}
void AliStack::PushTrack(Int_t done, Int_t parent, Int_t pdg,
Double_t px, Double_t py, Double_t pz, Double_t e,
Double_t vx, Double_t vy, Double_t vz, Double_t tof,
Double_t polx, Double_t poly, Double_t polz,
TMCProcess mech, Int_t &ntr, Double_t weight, Int_t is)
{
const Int_t kFirstDaughter=-1;
const Int_t kLastDaughter=-1;
TParticle* particle
= new(fParticles[fLoadPoint++])
TParticle(pdg, is, parent, -1, kFirstDaughter, kLastDaughter,
px, py, pz, e, vx, vy, vz, tof);
particle->SetPolarisation(polx, poly, polz);
particle->SetWeight(weight);
particle->SetUniqueID(mech);
if(!done) {
particle->SetBit(kDoneBit);
} else {
particle->SetBit(kTransportBit);
}
particle->SetBit(kDaughtersBit);
fParticleMap.AddAtAndExpand(particle, fNtrack);
if(parent>=0) {
particle = GetParticleMapEntry(parent);
if (particle) {
particle->SetLastDaughter(fNtrack);
if(particle->GetFirstDaughter()<0) particle->SetFirstDaughter(fNtrack);
}
else {
AliError(Form("Parent %d does not exist",parent));
}
} else {
fHgwmk = fNtrack;
fNprimary = fHgwmk+1;
fCurrentPrimary++;
}
ntr = fNtrack++;
}
TParticle* AliStack::PopNextTrack(Int_t& itrack)
{
TParticle* track = GetNextParticle();
if (track) {
itrack = fCurrent;
track->SetBit(kDoneBit);
}
else
itrack = -1;
fCurrentTrack = track;
return track;
}
TParticle* AliStack::PopPrimaryForTracking(Int_t i)
{
TParticle* particle = Particle(i);
if (!particle->TestBit(kDoneBit)) {
fCurrentTrack = particle;
return particle;
}
else
return 0;
}
Bool_t AliStack::PurifyKine()
{
int nkeep = fHgwmk + 1, parent, i;
TParticle *part, *father;
fTrackLabelMap.Set(fParticleMap.GetLast()+1);
if(fHgwmk+1 == fNtrack) return kFALSE;
for(i=0; i<fNtrack; i++) {
if(i<=fHgwmk) fTrackLabelMap[i]=i ;
else {
fTrackLabelMap[i] = -99;
if((part=GetParticleMapEntry(i))) {
if (KeepPhysics(part)) KeepTrack(i);
part->ResetBit(kDaughtersBit);
part->SetFirstDaughter(-1);
part->SetLastDaughter(-1);
}
}
}
part = GetParticleMapEntry(fHgwmk+1);
fParticleMap.At(part->GetFirstMother())->ResetBit(kDaughtersBit);
for(i=fHgwmk+1; i<fNtrack; i++) {
if(fParticleMap.At(i)->TestBit(kKeepBit)) {
fTrackLabelMap[i]=nkeep;
if(i!=nkeep) fParticleMap[nkeep]=fParticleMap.At(i);
part = GetParticleMapEntry(nkeep);
if((parent=part->GetFirstMother())>fHgwmk) {
if(fTrackLabelMap[parent]==-99) Fatal("PurifyKine","fTrackLabelMap[%d] = -99!\n",parent);
else part->SetFirstMother(fTrackLabelMap[parent]);}
nkeep++;
}
}
for (i=fHgwmk+1; i<nkeep; i++) {
part = GetParticleMapEntry(i);
parent = part->GetFirstMother();
if(parent>=0) {
father = GetParticleMapEntry(parent);
if(father->TestBit(kDaughtersBit)) {
if(i<father->GetFirstDaughter()) father->SetFirstDaughter(i);
if(i>father->GetLastDaughter()) father->SetLastDaughter(i);
} else {
father->SetFirstDaughter(i);
father->SetLastDaughter(i);
father->SetBit(kDaughtersBit);
}
}
}
if(nkeep > fParticleFileMap.GetSize()) fParticleFileMap.Set(Int_t (nkeep*1.5));
for (i=fHgwmk+1; i<nkeep; ++i) {
fParticleBuffer = GetParticleMapEntry(i);
fParticleFileMap[i]=static_cast<Int_t>(TreeK()->GetEntries());
TreeK()->Fill();
fParticleMap[i]=fParticleBuffer=0;
}
for (i = nkeep; i < fNtrack; ++i) fParticleMap[i]=0;
Int_t toshrink = fNtrack-fHgwmk-1;
fLoadPoint-=toshrink;
for(i=fLoadPoint; i<fLoadPoint+toshrink; ++i) fParticles.RemoveAt(i);
fNtrack=nkeep;
fHgwmk=nkeep-1;
return kTRUE;
}
Bool_t AliStack::ReorderKine()
{
if(fHgwmk+1 == fNtrack) return kFALSE;
Int_t nNew = fNtrack - fHgwmk - 1;
if (nNew > 0) {
Int_t i, j;
TArrayI map1(nNew);
TParticle** tmp = new TParticle*[nNew];
for (i = 0; i < nNew; i++) {
if (fParticleMap.At(fHgwmk + 1 + i)) {
tmp[i] = GetParticleMapEntry(fHgwmk + 1 + i);
} else {
tmp[i] = 0x0;
}
map1[i] = -99;
}
Int_t loadPoint = fHgwmk + 1;
for (i = -1; i < nNew-1; i++) {
Int_t ipa;
TParticle* parP;
if (i == -1) {
ipa = tmp[0]->GetFirstMother();
parP = GetParticleMapEntry(ipa);
} else {
ipa = (fHgwmk + 1 + i);
if (!tmp[i]) continue;
if (tmp[i]->GetFirstDaughter() == -1) continue;
parP = tmp[i];
}
Int_t idaumin = parP->GetFirstDaughter() - fHgwmk - 1;
Int_t idaumax = parP->GetLastDaughter() - fHgwmk - 1;
parP->SetFirstDaughter(-1);
parP->SetLastDaughter(-1);
for (j = idaumin; j <= idaumax; j++) {
if (!tmp[j]) continue;
if (map1[j] != -99) continue;
Int_t jpa = tmp[j]->GetFirstMother();
if (jpa == ipa) {
fParticleMap[loadPoint] = tmp[j];
parP->SetLastDaughter(loadPoint);
if (parP->GetFirstDaughter() == -1) parP->SetFirstDaughter(loadPoint);
if (i != -1) {
tmp[j]->SetFirstMother(map1[i]);
}
map1[j] = loadPoint;
loadPoint++;
}
}
}
delete[] tmp;
fTrackLabelMap.Set(fNtrack);
for (i = 0; i < fNtrack; i ++) {
if (i <= fHgwmk) {
fTrackLabelMap[i] = i;
} else{
fTrackLabelMap[i] = map1[i - fHgwmk -1];
}
}
}
return kTRUE;
}
Bool_t AliStack::KeepPhysics(const TParticle* part)
{
Bool_t keep = kFALSE;
Int_t parent = part->GetFirstMother();
if (parent >= 0 && parent <= fHgwmk) {
TParticle* father = GetParticleMapEntry(parent);
Int_t kf = father->GetPdgCode();
kf = TMath::Abs(kf);
Int_t kfl = kf;
if (kfl > 10) kfl/=100;
if (kfl > 10) kfl/=10;
if (kfl > 10) kfl/=10;
if (kfl >= 4) {
keep = kTRUE;
}
if ((part->GetUniqueID()) == kPPair) keep = kTRUE;
}
if ((part->GetUniqueID() == kPDecay) && (parent >= 0)) {
TParticle* father = GetParticleMapEntry(parent);
Int_t imo = parent;
while((imo > fHgwmk) && (father->GetUniqueID() == kPDecay)) {
imo = father->GetFirstMother();
father = GetParticleMapEntry(imo);
}
if ((imo <= fHgwmk)) keep = kTRUE;
}
return keep;
}
void AliStack::FinishEvent()
{
if (!TreeK()) {
return;
}
CleanParents();
if(TreeK()->GetEntries() ==0) {
fParticleFileMap.Set(fHgwmk+1);
}
Bool_t allFilled = kFALSE;
TParticle *part;
for(Int_t i=0; i<fHgwmk+1; ++i) {
if((part=GetParticleMapEntry(i))) {
fParticleBuffer = part;
fParticleFileMap[i]= static_cast<Int_t>(TreeK()->GetEntries());
TreeK()->Fill();
fParticleBuffer=0;
fParticleMap.AddAt(0,i);
if (allFilled) AliWarning(Form("Why != 0 part # %d?\n",i));
}
else
{
if(!allFilled) allFilled = kTRUE;
}
}
}
void AliStack::FlagTrack(Int_t track)
{
TParticle *particle;
Int_t curr=track;
while(1) {
particle = GetParticleMapEntry(curr);
if(particle->TestBit(kKeepBit)) return;
particle->SetBit(kKeepBit);
if((curr=particle->GetFirstMother())==-1) return;
}
}
void AliStack::KeepTrack(Int_t track)
{
fParticleMap.At(track)->SetBit(kKeepBit);
}
void AliStack::Clean(Int_t size)
{
fNtrack=0;
fNprimary=0;
fHgwmk=0;
fLoadPoint=0;
fCurrent = -1;
ResetArrays(size);
}
void AliStack::Reset(Int_t size)
{
Clean(size);
delete fParticleBuffer; fParticleBuffer = 0;
fTreeK = 0x0;
}
void AliStack::ResetArrays(Int_t size)
{
fParticles.Clear();
fParticleMap.Clear();
if (size>0) fParticleMap.Expand(size);
}
void AliStack::SetHighWaterMark(Int_t)
{
fHgwmk = fNtrack-1;
fCurrentPrimary=fHgwmk;
fNprimary = fHgwmk+1;
}
TParticle* AliStack::Particle(Int_t i)
{
if(!fParticleMap.At(i)) {
Int_t nentries = fParticles.GetEntriesFast();
Int_t entry = TreeKEntry(i);
if (entry != fParticleFileMap[i]) {
AliFatal(Form(
"!! The algorithmic way and map are different: !!\n entry: %d map: %d",
entry, fParticleFileMap[i]));
}
TreeK()->GetEntry(entry);
new (fParticles[nentries]) TParticle(*fParticleBuffer);
fParticleMap.AddAt(fParticles[nentries],i);
}
return GetParticleMapEntry(i);
}
TParticle* AliStack::ParticleFromTreeK(Int_t id) const
{
Int_t entry;
if ((entry = TreeKEntry(id)) < 0) return 0;
if (fTreeK->GetEntry(entry)<=0) return 0;
return fParticleBuffer;
}
Int_t AliStack::TreeKEntry(Int_t id) const
{
Int_t entry;
if (id<fNprimary)
entry = id+fNtrack-fNprimary;
else
entry = id-fNprimary;
return entry;
}
Int_t AliStack::GetCurrentParentTrackNumber() const
{
TParticle* current = GetParticleMapEntry(fCurrent);
if (current)
return current->GetFirstMother();
else {
AliWarning("Current track not found in the stack");
return -1;
}
}
Int_t AliStack::GetPrimary(Int_t id)
{
int current, parent;
parent=id;
while (1) {
current=parent;
parent=Particle(current)->GetFirstMother();
if(parent<0) return current;
}
}
void AliStack::DumpPart (Int_t i) const
{
GetParticleMapEntry(i)->Print();
}
void AliStack::DumpPStack ()
{
Int_t i;
printf("\n\n=======================================================================\n");
for (i=0;i<fNtrack;i++)
{
TParticle* particle = Particle(i);
if (particle) {
printf("-> %d ",i); particle->Print();
printf("--------------------------------------------------------------\n");
}
else
Warning("DumpPStack", "No particle with id %d.", i);
}
printf("\n=======================================================================\n\n");
}
void AliStack::DumpLoadedStack() const
{
printf(
"\n\n=======================================================================\n");
for (Int_t i=0;i<fNtrack;i++)
{
TParticle* particle = GetParticleMapEntry(i);
if (particle) {
printf("-> %d ",i); particle->Print();
printf("--------------------------------------------------------------\n");
}
else {
printf("-> %d Particle not loaded.\n",i);
printf("--------------------------------------------------------------\n");
}
}
printf(
"\n=======================================================================\n\n");
}
void AliStack::SetCurrentTrack(Int_t track)
{
fCurrent = track;
if (fCurrent < fNprimary) fCurrentTrack = Particle(track);
}
void AliStack::CleanParents()
{
TParticle *part;
int i;
for(i=0; i<fHgwmk+1; i++) {
part = GetParticleMapEntry(i);
if(part) if(!part->TestBit(kDaughtersBit)) {
part->SetFirstDaughter(-1);
part->SetLastDaughter(-1);
}
}
}
TParticle* AliStack::GetNextParticle()
{
TParticle* particle = 0;
for(Int_t i=fNtrack-1; i>fHgwmk; i--) {
particle = GetParticleMapEntry(i);
if ((particle) && (!particle->TestBit(kDoneBit))) {
fCurrent=i;
return particle;
}
}
while (fCurrentPrimary>=0) {
fCurrent = fCurrentPrimary;
particle = GetParticleMapEntry(fCurrentPrimary--);
if ((particle) && (!particle->TestBit(kDoneBit))) {
return particle;
}
}
fCurrent = -1;
return particle;
}
void AliStack::ConnectTree(TTree* tree)
{
fTreeK = tree;
AliDebug(1, "Connecting TreeK");
if (fTreeK == 0x0)
{
if (TreeK() == 0x0)
{
AliFatal("Parameter is NULL");
return;
}
return;
}
AliDebug(2, Form("Tree name is %s",fTreeK->GetName()));
if (fTreeK->GetDirectory())
{
AliDebug(2, Form("and dir is %s",fTreeK->GetDirectory()->GetName()));
}
else
AliWarning("DIR IS NOT SET !!!");
TBranch *branch=fTreeK->GetBranch("Particles");
if(branch == 0x0)
{
branch = fTreeK->Branch("Particles", &fParticleBuffer, 4000);
AliDebug(2, "Creating Branch in Tree");
}
else
{
AliDebug(2, "Branch Found in Tree");
branch->SetAddress(&fParticleBuffer);
}
if (branch->GetDirectory())
{
AliDebug(1, Form("Branch Dir Name is %s",branch->GetDirectory()->GetName()));
}
else
AliWarning("Branch Dir is NOT SET");
}
Bool_t AliStack::GetEvent()
{
Int_t size = (Int_t)TreeK()->GetEntries();
ResetArrays(size);
return kTRUE;
}
Bool_t AliStack::IsStable(Int_t pdg) const
{
if(pdg>1000000000)return kTRUE;
const Int_t kNstable = 18;
Int_t i;
Int_t pdgStable[kNstable] = {
kGamma,
kElectron,
kMuonPlus,
kPiPlus,
kKPlus,
kK0Short,
kK0Long,
kProton,
kNeutron,
kLambda0,
kSigmaMinus,
kSigmaPlus,
3312,
3322,
3334,
kNuE,
kNuMu,
kNuTau
};
Bool_t isStable = kFALSE;
for (i = 0; i < kNstable; i++) {
if (pdg == TMath::Abs(pdgStable[i])) {
isStable = kTRUE;
break;
}
}
return isStable;
}
Bool_t AliStack::IsPhysicalPrimary(Int_t index)
{
TParticle* p = Particle(index);
Int_t ist = p->GetStatusCode();
if (ist > 1) return kFALSE;
Int_t pdg = TMath::Abs(p->GetPdgCode());
if (!IsStable(pdg)) return kFALSE;
if (index < GetNprimary()) {
return kTRUE;
} else {
Int_t imo = p->GetFirstMother();
TParticle* pm = Particle(imo);
Int_t mpdg = TMath::Abs(pm->GetPdgCode());
if ((mpdg == 3212) && (imo < GetNprimary())) return kTRUE;
if ((mpdg == kPi0) && (imo < GetNprimary())) return kTRUE;
Int_t mfl = Int_t (mpdg / TMath::Power(10, Int_t(TMath::Log10(mpdg))));
if (mfl < 4) return kFALSE;
if (imo < GetNprimary()) {
return kTRUE;
}
while (imo >= GetNprimary()) {
imo = pm->GetFirstMother();
pm = Particle(imo);
}
mpdg = TMath::Abs(pm->GetPdgCode());
mfl = Int_t (mpdg / TMath::Power(10, Int_t(TMath::Log10(mpdg))));
if (mfl < 4) {
return kFALSE;
} else {
return kTRUE;
}
}
}
Bool_t AliStack::IsSecondaryFromWeakDecay(Int_t index) {
TParticle* particle = Particle(index);
Int_t uniqueID = particle->GetUniqueID();
if(IsPhysicalPrimary(index)) return kFALSE;
Int_t mfl = 0;
Int_t indexMoth = particle->GetFirstMother();
if(indexMoth < 0) return kFALSE;
TParticle* moth = Particle(indexMoth);
Float_t codemoth = (Float_t)TMath::Abs(moth->GetPdgCode());
mfl = Int_t (codemoth / TMath::Power(10, Int_t(TMath::Log10(codemoth))));
if(mfl == 3 && uniqueID == kPDecay) return kTRUE;
if(codemoth == 211 && uniqueID == kPDecay) return kTRUE;
if(codemoth == 13 && uniqueID == kPDecay) return kTRUE;
return kFALSE;
}
Bool_t AliStack::IsSecondaryFromMaterial(Int_t index) {
if(IsPhysicalPrimary(index)) return kFALSE;
if(IsSecondaryFromWeakDecay(index)) return kFALSE;
TParticle* particle = Particle(index);
Int_t indexMoth = particle->GetFirstMother();
if(indexMoth < 0) return kFALSE;
return kTRUE;
}