using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include "TClonesArray.h"
#include "PData.h"
#include "PUtils.h"
#include "PReaction.h"
#include "PDecayChannel.h"
#include "PDecayManager.h"
#include "TStopwatch.h"
ClassImp(PDecayManager)
static char ret[200];
Int_t PReactionList::maxID = 0;
PDecayManager::PDecayManager() {
makeStaticData();
makeDistributionManager()->ExecAll("init");
Int_t key = makeDataBase()->GetEntry("std_set");
if (key<0)
Warning("PDecayManager()", "std_set not found");
Int_t listkey = -1;
while (makeDataBase()->MakeListIterator(key, "snpart", "slink" ,&listkey)) {
PDecayChannel *ch = new PDecayChannel();
makeDataBase()->SetParamTObj(listkey, "decaychannel", ch);
}
decaychannel_param = makeDataBase()->GetParamTObj("decaychannel");
UsedParticles = new PNextList<PParticle>;
UsedParticleArrays = new PNextList<PParticle*>;
UsedChannels = new PNextList<PChannel>;
ReactionList = new PNextList<PReactionList>;
CurrentReactionListPointer = NULL;
verbose = 0;
userSelection = NULL;
nTrigCond = 0;
fHGeant = kFALSE;
fWriteIndex = kFALSE;
fPythia = NULL;
maxFileSize = 0;
tauMax = -1.;
pdist = makeDistributionManager();
Info("PDecayManager()", "(%s)", PRINT_CTOR);
fileoutput_pos = 0;
bulkdecay_pos = pro_bulkdecay_pos = 0;
}
PDecayManager::~PDecayManager() {
printf("decay manager destructor ok\n");
UsedParticles->Delete(); delete UsedParticles;
UsedParticleArrays->Delete(); delete UsedParticleArrays;
UsedChannels->Delete(); delete UsedChannels;
ReactionList->Delete(); delete ReactionList;
}
void PDecayManager::SetVerbose(Int_t v) {
verbose = v;
}
void PDecayManager::AddChannel(Int_t id, PDecayChannel *n) {
if (!makeStaticData()->IsParticleValid(id)) {
Warning("AddChannel", "id %i s unvalid", id);
return;
} else {
Int_t key = makeDataBase()->GetEntryInt("pid", id);
PDecayChannel *ch;
TObject *o;
if (key < 0) return;
if (!makeDataBase()->GetParamTObj(key, "decaychannel", &o)) return;
ch = (PDecayChannel*)o;
if (ch == NULL) {
makeDataBase()->SetParamTObj(key, "decaychannel", ch);
} else
ch->AddChannel(n);
}
}
void PDecayManager::AddChannel(PParticle *p, PDecayChannel *n) {
if (p) AddChannel(p->ID(), n);
}
void PDecayManager::AddChannel(const char *p, PDecayChannel *n) {
AddChannel(makeStaticData()->GetParticleID(p), n);
}
PDecayChannel *PDecayManager::GetChannel(Int_t id) const {
Int_t key = makeStaticData()->GetParticleKey(id);
if (key < 0) {
Warning("GetChannel", "id %i not found in data base", id);
return NULL;
}
TObject *ch;
if (!makeDataBase()->GetParamTObj(key, decaychannel_param, &ch)) {
Warning("GetChannel", "no decaychannel found for ID: %i", id);
return NULL;
}
return (PDecayChannel*) ch;
}
PDecayChannel *PDecayManager::GetChannel(PParticle *p) const {
if (p) return GetChannel(p->ID());
return NULL;
}
PDecayChannel *PDecayManager::GetChannel(char *p) const {
if (p) return GetChannel(makeStaticData()->GetParticleID(p));
return NULL;
}
void PDecayManager::SetDefault(Int_t id, Int_t recursive) {
if (!makeStaticData()->IsParticleValid(id)) return;
Clear(id);
PDecayChannel *c = GetChannel(id);
if (!c) {
Warning("SetDefault", "Channel not present");
}
const char *name = GetName(id);
if (verbose) cout << endl << "Setting defaults for particle #" << id << ", "
<< name << endl;
if (verbose) {
cout << "Information found:" << endl;
makeStaticData()->PrintParticle(id);
}
Int_t key = makeDataBase()->GetEntryInt("pid", id);
Int_t listkey = -1;
Int_t tid[11];
while (makeDataBase()->MakeListIterator(key, "pnmodes", "link", &listkey)) {
tid[0] = 10;
makeStaticData()->GetDecayModeByKey(listkey, tid);
int *pos;
makeDataBase()->GetParamInt(listkey, "didx", &pos);
Double_t weight = makeStaticData()->GetDecayBR(*pos);
c->AddChannel(weight, tid[0], &tid[1]);
if (recursive) {
for (int i=0; i<tid[0]; i++)
SetDefault(tid[i+1]);
}
}
}
void PDecayManager::SetDefault(PParticle *p,Int_t recursive) {
if (p) SetDefault(p->ID(), recursive);
}
void PDecayManager::SetDefault(const char *p,Int_t recursive) {
SetDefault(makeStaticData()->GetParticleID(p), recursive);
}
void PDecayManager::Clear(Int_t id) {
Int_t key = makeDataBase()->GetEntryInt("pid", id);
TObject *ch;
if (!makeDataBase()->GetParamTObj(key, "decaychannel", &ch)) return;
if (ch == NULL) return;
PDecayChannel *ch2 = new PDecayChannel();
if (!makeDataBase()->SetParamTObj(key, "decaychannel", ch2)) return;
delete (PDecayChannel*) ch;
}
void PDecayManager::Clear(PParticle *p) {
Clear(p->ID());
}
void PDecayManager::MyClear(char *p) {
Clear(makeStaticData()->GetParticleID(p));
}
void PDecayManager::InitReaction(PParticle *start, PDecayChannel *CurrentChannel) {
if (UsedParticles) {
UsedParticles->Delete();
delete UsedParticles;
UsedParticles = new PNextList<PParticle>;
}
if (UsedParticleArrays) {
UsedParticleArrays->Delete();
delete UsedParticleArrays;
UsedParticleArrays = new PNextList<PParticle*>;
}
if (UsedChannels) {
UsedChannels->Delete();
delete UsedChannels;
UsedChannels = new PNextList<PChannel>;
}
if (ReactionList) {
ReactionList->Delete();
delete ReactionList;
ReactionList = new PNextList<PReactionList>;
}
CurrentReactionNumber = 0;
CurrentReactionListPointer = NULL;
if (verbose) cout << endl << "processing decay:" << endl;
if (!CurrentChannel) CurrentChannel = GetChannel(start);
Int_t copyFlag = ( start->IsFireball() || start->IsFileInput() )
? 0 : 1;
Int_t nReac1 = 0, nReac2 = 0;
while (CurrentChannel) {
PReactionList *tempRL = new PReactionList;
ConstructPChannel(start, CurrentChannel, tempRL, copyFlag);
ReactionList->Add(tempRL);
nReac1++;
CurrentChannel = CurrentChannel->GetNext();
}
Int_t MoreToDo = 1;
while (MoreToDo) {
MoreToDo = 0;
PNextList<PReactionList> *x = ReactionList;
while (x) {
PReactionList* tempRL = x->Curr;
PChannel* tempPC = tempRL->ToDo->Pop();
while (tempPC) {
MoreToDo = 1;
tempRL->Finished->Push(tempPC);
Int_t i, loop;
Int_t NOP = tempPC->GetNumPar();
PParticle **LOP = tempPC->GetParticles();
PDecayChannel **pdc = new PDecayChannel*[NOP];
for(i=0; i<NOP; i++)
pdc[i] = GetChannel(LOP[i+1]);
loop = 0;
while (pdc[NOP-1]) {
PReactionList *newRL = tempRL->Clone();
for (i=0; i<NOP; i++) {
ConstructPChannel(LOP[i+1], pdc[i], tempRL);
if ( (!i) || (loop) ) {
loop = 0;
pdc[i] = pdc[i]->GetNext();
if ( (i<(NOP-1)) && !pdc[i] ) {
pdc[i] = GetChannel(LOP[i+1]);
loop = 1;
}
}
}
if (pdc[NOP-1]) {
ReactionList->Add(newRL);
nReac2++;
tempRL = newRL;
} else
delete newRL;
}
tempPC = tempRL->ToDo->Pop();
}
x = x->Next;
}
}
NumberOfReactions = nReac1 + nReac2;
}
void PDecayManager::ConstructPChannel(PParticle *p, PDecayChannel *c1,
PReactionList *RL, Int_t CopyFlag) {
Double_t CurrentWeight = c1->GetWeight();
if (CurrentWeight<1.0e-20) return;
RL->ReactionWeight *= CurrentWeight;
Int_t NumOfProducts;
Int_t* ListOfProducts = c1->GetDaughters(NumOfProducts);
PParticle** array = new PParticle*[NumOfProducts+1];
UsedParticleArrays->Add(array);
if (CopyFlag)
array[0] = p->Clone();
else
array[0] = p;
for (Int_t i=0; i<NumOfProducts; i++) {
Int_t id = ListOfProducts[i];
array[i+1] = new PParticle(id);
UsedParticles->Add(array[i+1]);
}
PChannel *tempPC = new PChannel(array, NumOfProducts);
UsedChannels->Add(tempPC);
RL->ToDo->Push(tempPC);
if (verbose) {
cout << "Next channel for " << p->Name() << ", weight: " << setw(8) << setprecision(2);
cout.setf(ios::scientific);
cout << RL->ReactionWeight << setprecision(0) << endl;
tempPC->Print();
}
pdist->from_pdecaymanager = 1;
pdist->Attach(tempPC);
}
PReaction *PDecayManager::GetNextReaction(int wf, const char *name, int f0,
int f1, int f2, int f3,
TTree *tt) {
char *filename;
if (verbose) cout << "Selecting next reaction:" << endl;
if (ListForReaction) delete [] ListForReaction;
if (CurrentReaction) delete CurrentReaction;
if (!ReactionList) {
if (verbose) cout << " No initialization done." << endl;
return NULL;
}
if (!CurrentReactionListPointer) CurrentReactionListPointer = ReactionList;
else CurrentReactionListPointer = CurrentReactionListPointer->Next;
if (!CurrentReactionListPointer) {
if (verbose) cout << " No reaction left." << endl;
return NULL;
}
CurrentReactionNumber++;
if (verbose) cout << endl << "This is reaction #" << CurrentReactionNumber << endl;
filename = new char[1024];
if (f3 == 2) sprintf(filename,"%s",name);
else sprintf(filename, "%s_%03d", name, CurrentReactionNumber);
PReactionList *tempRL = CurrentReactionListPointer->Curr->Clone();
Int_t NumOfChannels = tempRL->Finished->Count;
ListForReaction = new PChannel*[NumOfChannels];
for (Int_t i=NumOfChannels-1; i>=0; i--) {
ListForReaction[i] = tempRL->Finished->Pop();
}
CurrentWeight = tempRL->ReactionWeight;
if (verbose) cout << " Weight of reaction is " << CurrentWeight << endl;
if (wf)
(ListForReaction[0]->GetParticles())[0]->SetW(CurrentWeight);
CurrentReaction = new PReaction(ListForReaction, filename, NumOfChannels,
f0, f1, f2, f3, tt);
CurrentReaction->SetHGeant(fHGeant);
CurrentReaction->SetWriteIndex(fWriteIndex);
if (maxFileSize > 0) CurrentReaction->SetMaxFileSize(maxFileSize);
if (fPythia) CurrentReaction->SetPythia(fPythia);
if (userSelection) {
CurrentReaction->SetUserSelection(userSelection);
CurrentReaction->SetTrigCond(nTrigCond);
}
if (tauMax >= 0.) {
CurrentReaction->SetDecayAll(tauMax);
}
for (int i=0; i<bulkdecay_pos; i++)
CurrentReaction->AddBulk(bulk[i]);
for (int i=0; i<pro_bulkdecay_pos; i++)
CurrentReaction->AddPrologueBulk(pro_bulk[i]);
delete tempRL;
return CurrentReaction;
}
PReaction *PDecayManager::GetNextReaction(const char *name, int f0,
int f1, int f2, int f3,
TTree *tt) {
return GetNextReaction(0, name, f0, f1, f2, f3, tt);
}
Int_t PDecayManager::Loop(int num, int wf, const char *name, int f0,
int f1, int f2, int f3, int rf) {
if (rf==1 && f3==1) f3 = 2;
Int_t rStart, rStop, rEntries;
char* rDescription = new char[1024];
Double_t rWeight = 0.;
Int_t SumOfEvents = 0;
Double_t WeightSum = 0;
char* filename = new char[1024];
sprintf(filename, "%s.root", name);
TFile *f = NULL;
TTree *td = NULL, *ti = NULL;
CurrentReaction = NULL;
ListForReaction = NULL;
if(!fHGeant) {
f = new TFile(filename,"RECREATE");
f->SetCompressionLevel(1);
}
td = new TTree("data", "Event data");
sprintf(filename, "%s.evt", name);
if (f3 == 2) PReaction::asciif = fopen(filename, "w");
PReaction::globalEventCounter = 0;
if (rf == 1) {
PReaction *pReactionArray[NumberOfReactions];
double rWeights[NumberOfReactions];
Double_t wsave[NumberOfReactions];
for (int i=0; i<NumberOfReactions; i++) {
CurrentReaction = NULL;
ListForReaction = NULL;
pReactionArray[i] = GetNextReaction(wf, name, f0, f1, f2, f3, td);
wsave[i] = GetCurrentWeight();
WeightSum += wsave[i];
rWeights[i] = WeightSum;
}
for (int i=0; i<NumberOfReactions; i++) {
cout << endl << "Reaction " << i+1 << " -------------- with weight: "
<< wsave[i] << endl;
pReactionArray[i]->Print();
}
for (int i=0; i<NumberOfReactions; i++) rWeights[i]/=WeightSum;
cout << endl << "Do " << num << " events now..." << endl;
TStopwatch timer;
timer.Start();
int percentevents = (num/100) * (*makeStaticData()->GetBatchValue("_system_printout_percent")),
cpc = 1, ipc = cpc*percentevents;
double t0 = timer.RealTime();
timer.Continue();
double *events = makeStaticData()->GetBatchValue("_system_total_event_number");
(*makeStaticData()->GetBatchValue("_system_total_events_to_sample")) = num;
int system_printout_percent = int(*makeStaticData()->GetBatchValue("_system_printout_percent"));
for (int i=0; i<num; i++) {
double rand = PUtils::sampleFlat();
int ind = PUtils::FindIndex(NumberOfReactions, rWeights, rand);
pReactionArray[ind]->InitChannels();
pReactionArray[ind]->DisableWeightReset();
pReactionArray[ind]->loop(1, 0, 0);
if ((*events) == ipc) {
printf(" %i%c done in %f sec\n", cpc*system_printout_percent,
'%', timer.RealTime()-t0);
cpc++;
ipc = cpc*percentevents;
timer.Continue();
}
}
SumOfEvents = num;
} else {
ti = new TTree("info", "Run information");
ti->Branch("rStart", &rStart, "rStart/I");
ti->Branch("rStop", &rStop, "rStop/I");
ti->Branch("rEntries", &rEntries, "rEntries/I");
ti->Branch("rWeight", &rWeight, "rWeight/D");
ti->Branch("rDescription", (void*)rDescription, "rDescription/C");
PReaction *r = GetNextReaction(wf, name, f0, f1, f2, f3, td);
while (r) {
rStart = SumOfEvents + 1;
if (verbose) r->Print();
rWeight = GetCurrentWeight();
WeightSum += rWeight;
if (verbose) cout << " Weight of this channel is " << rWeight << endl;
if (f3 == 1) PReaction::globalEventCounter = 0;
if (wf) rEntries = r->loop(num,1);
else rEntries = r->loop((Int_t)(num*rWeight + 0.5), 0);
SumOfEvents += rEntries;
rStop = SumOfEvents;
CurrentReaction = NULL;
r = GetNextReaction(wf, name, f0, f1, f2, f3, td);
if (ti) ti->Fill();
}
}
if (f) {
f = td->GetCurrentFile();
f->Write();
f->Close();
delete f;
}
if (f3 == 2) fclose(PReaction::asciif);
delete [] filename;
delete [] rDescription;
if (verbose) cout << "Sum of weights is " << WeightSum << endl;
return SumOfEvents;
}
Double_t PDecayManager::GetCurrentWeight() {
return CurrentWeight;
}
void PDecayManager::MyPrint() const {
cout << "Particle Decay List:" << endl;
cout << "--------------------" << endl;
Int_t key = makeDataBase()->GetEntry("std_set");
if (key < 0)
Warning("MyPrint", "std_set not found");
Int_t listkey = -1;
while (makeDataBase()->MakeListIterator(key, "snpart", "slink", &listkey)) {
int id = makeStaticData()->GetParticleIDByKey(listkey);
if (id < 1000) Print(id);
}
PrintReactionList();
}
void PDecayManager::Print(Int_t id) const {
if (!makeStaticData()->IsParticleValid(id)) return;
PDecayChannel *DC = GetChannel(id);
if (!DC) return;
if (DC->GetWeight()) {
cout.setf(ios::left);
cout.width(20);
cout << GetName(id);
DC->Print();
cout << endl;
}
return;
}
void PDecayManager::Print(PParticle *p) const {
if (p) Print(p->ID());
return;
}
void PDecayManager::MyPrint(char *p) const {
if (p) Print(makeStaticData()->GetParticleID(p));
return;
}
void PDecayManager::PrintReactionList() const {
PNextList<PReactionList> *x = ReactionList;
Int_t Entry = 0;
while(x) {
if ( x->Curr ) {
PReactionList *RL = x->Curr->Clone();
Entry++;
cout << "-----" << endl;
cout << "Decay chain #" << Entry << ", probability "
<< RL->ReactionWeight << endl;
PrintReactionListEntry(RL,cout);
delete RL;
}
x = x->Next;
}
}
void PDecayManager::PrintReactionListEntry(PReactionList *RL,
ostream &os) const{
Int_t count = RL->Finished->Count;
PChannel **temp = new PChannel*[count];
for (Int_t i=count-1; i>=0; i--) {
temp[i] = RL->Finished->Pop();
}
PrintChain((temp[0]->GetParticles())[0], temp, count, os);
delete [] temp;
}
void PDecayManager::PrintChain(PParticle *p, PChannel **l, Int_t c,
ostream &os) const {
static Int_t indent = 0;
indent += 2;
for (Int_t i=0; i<c; i++) {
Int_t pcount = l[i]->GetNumPar();
PParticle **plist = l[i]->GetParticles();
if (p == plist[0]) {
if (i == 0) indent = 2;
os.width(indent) ;
os << " ";
os.setf(ios::left);
os << setw(12) << GetName(p->ID())
<< setw(0) << " --> ";
for (Int_t k=1; k<=pcount; k++) {
os << GetName((plist[k])->ID()) << " ";
}
os << endl;
for (Int_t k=1; k<=pcount; k++) {
PrintChain(plist[k], l, c, os);
}
}
}
indent -= 2;
}
const char *PDecayManager::GetName(Int_t id) const {
if (id <=0 )
return "???";
if (id < 1000)
return (char*)makeStaticData()->GetParticleName(id);
char temp[200];
Int_t Upper = id/1000;
Int_t Lower = id - 1000*Upper;
sprintf(ret, "%s ", makeStaticData()->GetParticleName(Lower));
id = Upper;
while (id) {
Upper = id/1000;
Lower = id - 1000*Upper;
sprintf(temp, "%s + %s", makeStaticData()->GetParticleName(Lower),ret);
strcpy(ret, temp);
id = Upper;
}
return ret;
}
Bool_t PDecayManager::AddBulk(PBulkInterface *mybulk) {
if (bulkdecay_pos == MAX_BULKDECAY ) {
Error("AddBulk", "MAX_BULKDECAY reached");
return kFALSE;
}
if (bulkdecay_pos && (bulk[bulkdecay_pos-1]->GetPriority() > mybulk->GetPriority())) {
bulk[bulkdecay_pos] = bulk[bulkdecay_pos-1];
bulk[bulkdecay_pos-1] = mybulk;
bulkdecay_pos++;
} else
bulk[bulkdecay_pos++] = mybulk;
return kTRUE;
}
Bool_t PDecayManager::AddPrologueBulk(PBulkInterface *mybulk) {
if (pro_bulkdecay_pos == MAX_BULKDECAY ) {
Error("AddPrologueBulk", "MAX_BULKDECAY reached");
return kFALSE;
}
if (pro_bulkdecay_pos && (pro_bulk[pro_bulkdecay_pos-1]->GetPriority() > mybulk->GetPriority())) {
pro_bulk[pro_bulkdecay_pos] = pro_bulk[pro_bulkdecay_pos-1];
pro_bulk[pro_bulkdecay_pos-1] = mybulk;
pro_bulkdecay_pos++;
} else
pro_bulk[pro_bulkdecay_pos++] = mybulk;
return kTRUE;
}