//========================================================// //Macro that reads the output of the hydro calculations //(Therminator) using the format that can be found at //arXiv:1102.0273 //Author: Panos.Christakoglou@nikhef.nl //========================================================// //========================================================// //Event structure struct StructEvent { UInt_t eventID;//unique identifier of the event (random number) UInt_t entries;//number of particles of each event UInt_t entriesprev;//set to 0 by default }; //========================================================// //========================================================// //Particle structure //Primordial particles: fathereid==-1 ==> //pid==fatherpid==rootpid struct StructParticle { Float_t mass;//the mass of the particle (in GeV) Float_t t;//the time coordinate of the particle in fm/c Float_t x;//the spacial coordinate x in fm/c Float_t y;//the spacial coordinate y in fm/c Float_t z;//the spacial coordinate z in fm/c Float_t e;//the energy in GeV Float_t px;//the x-coordinate of the particle's momentum in GeV Float_t py;//the y-coordinate of the particle's momentum in GeV Float_t pz;//the z-coordinate of the particle's momentum in GeV Int_t decayed;//decay flag (1: decayed, 0: no decay) Int_t pid;//PDG of particle Int_t fatherpid;//PDG of parent Int_t rootpid;//root (primordial) particle PDG number Int_t eid;//sequence number in the event Int_t fathereid;//parent sequence number in the event UInt_t eventid;//unique identifier of the event (random number) }; //========================================================// //========================================================// //Balance function analysis variables Bool_t gRunShuffling=kFALSE; Bool_t gRunMixing=kTRUE; Bool_t gRunMixingWithEventPlane=kFALSE; Double_t gEtaMin = -0.8; Double_t gEtaMax = 0.8; Double_t gPtMin = 0.2; Double_t gPtMax = 20.0; //========================================================// void runBalanceFunctionOnHydro(TString aEventDir = ".", Int_t aEventFiles = 9) { //Macro that reads the themrinator events //Author: Panos.Christakoglou@nikhef.nl // Time: TStopwatch timer; timer.Start(); //========================================================// //Load the aliroot libraries gSystem->Load("libSTEERBase.so"); gSystem->Load("libESD.so"); gSystem->Load("libAOD.so"); gSystem->Load("libANALYSIS.so"); gSystem->Load("libANALYSISalice.so"); gSystem->Load("libEventMixing.so"); gSystem->Load("libCORRFW.so"); gSystem->Load("libPWGTools.so"); gSystem->Load("libPWGCFebye.so"); //========================================================// //========================================================// //Configure the bf objects AliBalancePsi *bf = new AliBalancePsi(); bf->SetAnalysisLevel("MC"); bf->SetShuffle(gRunShuffling); bf->SetEventClass("EventPlane"); bf->SetDeltaEtaMax(TMath::Abs(gEtaMax-gEtaMin)); bf->InitHistograms(); AliBalancePsi *bfs = 0x0; if(gRunShuffling) { bfs = new AliBalancePsi(); bfs->SetAnalysisLevel("MC"); bfs->SetEventClass("EventPlane"); bfs->SetDeltaEtaMax(TMath::Abs(gEtaMax-gEtaMin)); bfs->InitHistograms(); } AliBalancePsi *bfm = 0x0; if(gRunMixing) { bfm = new AliBalancePsi(); bfm->SetAnalysisLevel("MC"); bfm->SetShuffle(gRunShuffling); bfm->SetEventClass("EventPlane"); bfm->SetDeltaEtaMax(TMath::Abs(gEtaMax-gEtaMin)); bfm->InitHistograms(); } //========================================================// //========================================================// //Output objects //QA list fList = new TList(); fList->SetName("listQA"); fList->SetOwner(); //Balance Function list TList *fListBF = new TList(); fListBF->SetName("listBF"); fListBF->SetOwner(); fListBF->Add(bf->GetHistNp()); fListBF->Add(bf->GetHistNn()); fListBF->Add(bf->GetHistNpn()); fListBF->Add(bf->GetHistNnn()); fListBF->Add(bf->GetHistNpp()); fListBF->Add(bf->GetHistNnp()); //Balance function list: shuffling TList *fListBFS = 0x0; if(gRunShuffling) { fListBFS = new TList(); fListBFS->SetName("listBFShuffled"); fListBFS->SetOwner(); fListBFS->Add(bfs->GetHistNp()); fListBFS->Add(bfs->GetHistNn()); fListBFS->Add(bfs->GetHistNpn()); fListBFS->Add(bfs->GetHistNnn()); fListBFS->Add(bfs->GetHistNpp()); fListBFS->Add(bfs->GetHistNnp()); } //Balance function list: event mixing TList *fListBFM = 0x0; if(gRunMixing) { fListBFM = new TList(); fListBFM->SetName("listBFMixed"); fListBFM->SetOwner(); fListBFM->Add(bfm->GetHistNp()); fListBFM->Add(bfm->GetHistNn()); fListBFM->Add(bfm->GetHistNpn()); fListBFM->Add(bfm->GetHistNnn()); fListBFM->Add(bfm->GetHistNpp()); fListBFM->Add(bfm->GetHistNnp()); } //========================================================// //========================================================// //Event Mixing if(gRunMixing){ Int_t trackDepth = 50000; Int_t poolsize = 1000; // Maximum number of events, ignored in the present implemented of AliEventPoolManager // centrality bins Double_t centralityBins[] = {0.,100.}; Double_t* centbins = centralityBins; Int_t nCentralityBins = sizeof(centralityBins) / sizeof(Double_t) - 1; // Zvtx bins Double_t vertexBins[] = {-10., 10.}; Double_t* vtxbins = vertexBins; Int_t nVertexBins = sizeof(vertexBins) / sizeof(Double_t) - 1; AliEventPoolManager *fPoolMgr = 0x0; fPoolMgr = new AliEventPoolManager(poolsize, trackDepth, nCentralityBins, centbins, nVertexBins, vtxbins); } //========================================================// //========================================================// //Create the TChain object: events TChain *eventChain = new TChain("events"); StructEvent tStructEvents; eventChain->SetBranchAddress("event",&tStructEvents); //========================================================// //========================================================// //Create the TChain object: particles TChain *particleChain = new TChain("particles"); StructParticle tStructParticles; particleChain->SetBranchAddress("particle",&tStructParticles); //========================================================// //========================================================// //Fill the TChain with the files in the directory for(Int_t iFile = 1; iFile <= aEventFiles; iFile++) { TString filename = aEventDir.Data(); filename += "/event00"; filename += iFile; filename += ".root"; cout<<"Adding file "<<filename.Data()<<" to the chain..."<<endl; eventChain->Add(filename.Data()); particleChain->Add(filename.Data()); } //========================================================// //========================================================// //QA histograms //Event stats. TString gCutName[5] = {"Total","Offline trigger", "Vertex","Analyzed","sel. Centrality"}; TH1F *fHistEventStats = new TH1F("fHistEventStats", "Event statistics;;N_{events}", 5,0.5,5.5); for(Int_t i = 1; i <= 5; i++) fHistEventStats->GetXaxis()->SetBinLabel(i,gCutName[i-1].Data()); fList->Add(fHistEventStats); //Number of accepted particles TH1F *fHistNumberOfAcceptedTracks = new TH1F("fHistNumberOfAcceptedTracks",";N_{acc.};Entries",4001,-0.5,4000.5); fList->Add(fHistNumberOfAcceptedTracks); //Particle level: eta-phi TH2F *fHistEtaPhiPositive = new TH2F("fHistEtaPhiPositive",";#eta;#varphi (rad)",80,gEtaMin,gEtaMax,72,0.0,2.*TMath::Pi()); fList->Add(fHistEtaPhiPositive); TH2F *fHistEtaPhiNegative = new TH2F("fHistEtaPhiNegative",";#eta;#varphi (rad)",80,gEtaMin,gEtaMax,72,0.0,2.*TMath::Pi()); fList->Add(fHistEtaPhiNegative); //Particle level: pt TH1F *fHistPtPositive = new TH1F("fHistPtPositive",";p_{T} (GeV/c)",100,0.01,30.01); fList->Add(fHistPtPositive); TH1F *fHistPtNegative = new TH1F("fHistPtNegative",";p_{T} (GeV/c)",100,0.01,30.01); fList->Add(fHistPtNegative); //========================================================// //========================================================// //loop over the events Int_t nEvents = eventChain->GetEntries(); cout<<"========================================="<<endl; cout<<"Number of events in the chain: "<<nEvents<<endl; cout<<"========================================="<<endl; Int_t iParticleCounter = 0; Int_t nTotalParticles = 0; for(Int_t iEvent = 0; iEvent < nEvents; iEvent++) { //for(Int_t iEvent = 0; iEvent < 1; iEvent++) { eventChain->GetEntry(iEvent); //========================================================// //Create the TObjArray object to store the particles TObjArray* tracksAccepted = new TObjArray; tracksAccepted->SetOwner(kTRUE); //========================================================// Int_t nParticles = tStructEvents.entries; if(((iEvent+1)%100)==0) cout<<"Event: "<<iEvent+1<<" - ID: "<<tStructEvents.eventID<<" - Entries: "<<tStructEvents.entries<<endl; //========================================================// //Filling event level histos fHistEventStats->Fill(1); fHistEventStats->Fill(2); fHistEventStats->Fill(3); fHistEventStats->Fill(4); fHistEventStats->Fill(5); Int_t gNumberOfAcceptedParticles = 0; Double_t gReactionPlane = 0.; Double_t gCharge = 0.; //========================================================// //loop over particles for(Int_t iParticle = 0; iParticle < nParticles; iParticle++) { particleChain->GetEntry(nTotalParticles+iParticle); //========================================================// //consider only primordial particles if(!IsPhysicalPrimary(tStructParticles.pid, tStructParticles.fathereid, gCharge)) continue; //========================================================// //Calculate kinematic variables Double_t gPt = TMath::Sqrt(TMath::Power(tStructParticles.px,2) + TMath::Power(tStructParticles.py,2)); Double_t gP = TMath::Sqrt(TMath::Power(tStructParticles.px,2) + TMath::Power(tStructParticles.py,2) + TMath::Power(tStructParticles.pz,2) ); Double_t gEta = -100.; if(gP != tStructParticles.pz) gEta = 0.5*TMath::Log((gP + tStructParticles.pz)/(gP - tStructParticles.pz)); Double_t gPhi = TMath::Pi()+TMath::ATan2(-tStructParticles.py,-tStructParticles.px); //========================================================// //Fill QA if(gCharge > 0) { fHistEtaPhiPositive->Fill(gEta,gPhi); fHistPtPositive->Fill(gPt); } else if(gCharge < 0) { fHistEtaPhiNegative->Fill(gEta,gPhi); fHistPtNegative->Fill(gPt); } //========================================================// //========================================================// //Apply cuts if((gEta > gEtaMax)||(gEta < gEtaMin)) continue; if((gPt > gPtMax)||(gPt < gPtMin)) continue; tracksAccepted->Add(new AliBFBasicParticle(gEta,gPhi,gPt,gCharge, 1.)); gNumberOfAcceptedParticles += 1; iParticleCounter += 1; //cout<<"\t Particle counter: "<<iParticleCounter<<" - Particle in the event: "<<iParticle+1<<" - eventID: "<<tStructParticles.eventid<<" - pid: "<<tStructParticles.pid<<" - fatherpid: "<<tStructParticles.fatherpid<<" - rootpid: "<<tStructParticles.rootpid<<" - fathereid: "<<tStructParticles.fathereid<<" - eid: "<<tStructParticles.eid<<endl; }//particle loop //========================================================// // Event mixing (borrowed code from the task) if (gRunMixing) { Int_t fMixingTracks = 50000; AliEventPool* pool = fPoolMgr->GetEventPool(1.,0.,0.); if (!pool) { AliFatal(Form("No pool found")); } else { //pool->SetDebug(1); if (pool->IsReady() || pool->NTracksInPool() > fMixingTracks / 10 || pool->GetCurrentNEvents() >= 5){ Int_t nMix = pool->GetCurrentNEvents(); //cout << "nMix = " << nMix << " tracks in pool = " << pool->NTracksInPool() << endl; // Fill mixed-event histos here for (Int_t jMix=0; jMix<nMix; jMix++) { TObjArray* tracksMixed = pool->GetEvent(jMix); bfm->CalculateBalance(gReactionPlane,tracksAccepted,tracksMixed,1.,0.); } } // Update the Event pool pool->UpdatePool(tracksAccepted); //pool->PrintInfo(); }//pool NULL check }//run mixing //========================================================// //========================================================// // calculate balance function bf->CalculateBalance(gReactionPlane,tracksAccepted,NULL,1.,0.); fHistNumberOfAcceptedTracks->Fill(gNumberOfAcceptedParticles); nTotalParticles += nParticles; } //========================================================// //Output file TFile *f = TFile::Open("AnalysisResults.root","recreate"); TDirectoryFile *dir = new TDirectoryFile("PWGCFEbyE.outputBalanceFunctionPsiAnalysis","PWGCFEbyE.outputBalanceFunctionPsiAnalysis"); fList->SetName("listQA"); fList->SetOwner(kTRUE); dir->Add(fList); fListBF->SetName("listBF"); fListBF->SetOwner(kTRUE); dir->Add(fListBF); if(gRunMixing) { fListBFM->SetName("listBFMixed"); fListBFM->SetOwner(kTRUE); dir->Add(fListBFM); } dir->Write(dir->GetName(),TObject::kSingleKey); f->Close(); //========================================================// // Print real and CPU time used for analysis: timer.Stop(); timer.Print(); } //______________________________________________________________// Bool_t IsPhysicalPrimary(Int_t gPDGCode, Int_t gFathereid, Double_t &gCharge) { //Check whether the primordial particle belongs to the list //of known particles Bool_t kStatus = kFALSE; if(gFathereid != -1) return kStatus; //List of stable particles const Int_t kNstable = 3; Int_t pdgStable[kNstable] = { 211, // Pion 321, // Kaon 2212, // Proton }; if(gPDGCode < 0) gCharge = -1; else if(gPDGCode > 0) gCharge = 1; for(Int_t iParticle = 0; iParticle < kNstable; iParticle++) { if((TMath::Abs(gPDGCode) == pdgStable[iParticle])) { kStatus = kTRUE; return kStatus; } } return kFALSE; }