/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ /* $Log$ */ #include "Riostream.h" #include "AliFlowLeeYangZerosMaker.h" #include "AliFlowEvent.h" #include "AliFlowSelection.h" #include "AliFlowConstants.h" //?? #include "AliFlowLYZHist1.h" #include "AliFlowLYZHist2.h" #include "AliFlowLYZConstants.h" //?? //#include "AliFlowLYZSummary.h" #include "TMath.h" #include "TComplex.h" #include "TProfile.h" #include "TObjArray.h" #include "TFile.h" #include "TVector.h" #include "TVector2.h" #include "TGraphErrors.h" #include "TCanvas.h" class TTree; class TH1F; class TH1D; class TVector3; class TProfile2D; class TObject; //class Riostream; //does not compile //class TMath; //does not compile //class TVector; //does not compile //Description: Maker to analyze Flow using the LeeYangZeros method // Equation numbers are from Big Paper (BP): Nucl. Phys. A 727, 373 (2003) // Practical Guide (PG): J. Phys. G: Nucl. Part. Phys. 30, S1213 (2004) // Adapted from StFlowLeeYangZerosMaker.cxx // by Markus Oldenberg and Art Poskanzer, LBNL // with advice from Jean-Yves Ollitrault and Nicolas Borghini // //Author: Naomi van der Kolk (kolk@nikhef.nl) ClassImp(AliFlowLeeYangZerosMaker) //----------------------------------------------------------------------- AliFlowLeeYangZerosMaker::AliFlowLeeYangZerosMaker(): fFirstRun(kTRUE), fUseSum(kTRUE), fDebug(kFALSE), fHistFileName(0), fHistFile(0), fSummaryFile(0), firstRunFile(0) { //default constructor if (fDebug) cout<<"****AliFlowLeeYangZerosMaker::AliFlowLeeYangZerosMaker default constructor****"<plots) fHistFile = new TFile(fHistFileName.Data(), "RECREATE"); //fHistFile->cd() ; //all histograms will be saved in this file //for each harmonic ??? fQsum.Set(0.,0.); fQ2sum = 0.; // Book histograms Int_t fNtheta = AliFlowLYZConstants::kTheta; //for control histograms fHistOrigMult = new TH1F("Control_FlowLYZ_OrigMult", "Control_FlowLYZ_OrigMult",1000, 0., 10000.); fHistOrigMult->SetXTitle("Original Multiplicity"); fHistOrigMult->SetYTitle("Counts"); fHistMult = new TH1F("Control_FlowLYZ_Mult", "Control_FlowLYZ_Mult",1000, 0., 10000.); fHistMult->SetXTitle("Multiplicity from selection"); fHistMult->SetYTitle("Counts"); fHistQ = new TH1F("Control_FlowLYZ_Q","Control_FlowLYZ_Q",500, 0., 10.); fHistQ->SetXTitle("Qvector"); fHistQ->SetYTitle("Counts"); fHistPt = new TH1F("Control_FlowLYZ_Pt","Control_FlowLYZ_Pt",200, 0., 10.); fHistPt->SetXTitle("Pt (GeV/c)"); fHistPt->SetYTitle("Counts"); fHistPhi = new TH1F("Control_FlowLYZ_Phi","Control_FlowLYZ_Phi",70, 0., 7.); fHistPhi->SetXTitle("Phi"); fHistPhi->SetYTitle("Counts"); fHistEta = new TH1F("Control_FlowLYZ_Eta","Control_FlowLYZ_Eta",40, 0., 2.); fHistEta->SetXTitle("Eta"); fHistEta->SetYTitle("Counts"); fHistQtheta = new TH1F("Control_FlowLYZ_Qtheta","Control_FlowLYZ_Qtheta",50,-1000.,1000.); fHistQtheta->SetXTitle("Qtheta"); fHistQtheta->SetYTitle("Counts"); if (fFirstRun){ //for first loop over events fHistProR0thetaHar1 = new TProfile("First_FlowProLYZ_r0theta_Har1","First_FlowProLYZ_r0theta_Har1",fNtheta,-0.5,fNtheta-0.5); fHistProR0thetaHar1->SetXTitle("#theta"); fHistProR0thetaHar1->SetYTitle("r_{0}^{#theta}"); fHistProR0thetaHar2 = new TProfile("First_FlowProLYZ_r0theta_Har2","First_FlowProLYZ_r0theta_Har2",fNtheta,-0.5,fNtheta-0.5); fHistProR0thetaHar2->SetXTitle("#theta"); fHistProR0thetaHar2->SetYTitle("r_{0}^{#theta}"); fHistProVthetaHar1 = new TProfile("First_FlowProLYZ_Vtheta_Har1","First_FlowProLYZ_Vtheta_Har1",fNtheta,-0.5,fNtheta-0.5); fHistProVthetaHar1->SetXTitle("#theta"); fHistProVthetaHar1->SetYTitle("V_{n}^{#theta}"); fHistProVthetaHar2 = new TProfile("First_FlowProLYZ_Vtheta_Har2","First_FlowProLYZ_Vtheta_Har2",fNtheta,-0.5,fNtheta-0.5); fHistProVthetaHar2->SetXTitle("#theta"); fHistProVthetaHar2->SetYTitle("V_{n}^{#theta}"); fHistProVR0 = new TProfile("First_FlowProLYZ_vR0","First_FlowProLYZ_vR0",2,0.5,2.5,-100.,100.); fHistProVR0->SetXTitle("Harmonic"); fHistProVR0->SetYTitle("v integrated from r0 (%)"); fHistVR0 = new TH1D("First_FlowLYZ_vR0","First_FlowLYZ_vR0",2,0.5,2.5); fHistVR0->SetXTitle("Harmonic"); fHistVR0->SetYTitle("v integrated from r0 (%)"); fHistProV = new TProfile("First_FlowProLYZ_V","First_FlowProLYZ_V",2,0.5,2.5,-1000.,1000.); fHistProV->SetXTitle("Harmonic"); fHistProV->SetYTitle("v integrated"); //class AliFlowLYZHist1 defines the histograms: fHistProGtheta, fHistProReGtheta, fHistProImGtheta, fHistProR0theta for (Int_t j=0;jSetXTitle("#theta"); fHistProReDenomHar1->SetYTitle("Re(Q^{#theta}e^{ir_{0}^{#theta}Q^{#theta}})"); fHistProReDenomHar2 = new TProfile("Second_FlowProLYZ_ReDenom_Har2","Second_FlowProLYZ_ReDenom_Har2" , fNtheta, -0.5, fNtheta-0.5); fHistProReDenomHar2->SetXTitle("#theta"); fHistProReDenomHar2->SetYTitle("Re(Q^{#theta}e^{ir_{0}^{#theta}Q^{#theta}})"); fHistProImDenomHar1 = new TProfile("Second_FlowProLYZ_ImDenom_Har1","Second_FlowProLYZ_ImDenom_Har1" , fNtheta, -0.5, fNtheta-0.5); fHistProImDenomHar1->SetXTitle("#theta"); fHistProImDenomHar1->SetYTitle("Im(Q^{#theta}e^{ir_{0}^{#theta}Q^{#theta}})"); fHistProImDenomHar2 = new TProfile("Second_FlowProLYZ_ImDenom_Har2","Second_FlowProLYZ_ImDenom_Har2" , fNtheta, -0.5, fNtheta-0.5); fHistProImDenomHar2->SetXTitle("#theta"); fHistProImDenomHar2->SetYTitle("Im(Q^{#theta}e^{ir_{0}^{#theta}Q^{#theta}})"); fHistProVetaHar1 = new TProfile("Second_FlowProLYZ_Veta_Har1","Second_FlowProLYZ_Veta_Har1",40,-2.,2.); fHistProVetaHar1->SetXTitle("rapidity"); fHistProVetaHar1->SetYTitle("v (%)"); fHistProVetaHar2 = new TProfile("Second_FlowProLYZ_Veta_Har2","Second_FlowProLYZ_Veta_Har2",40,-2.,2.); fHistProVetaHar2->SetXTitle("rapidity"); fHistProVetaHar2->SetYTitle("v (%)"); fHistProVPtHar1 = new TProfile("Second_FlowProLYZ_VPt_Har1","Second_FlowProLYZ_VPt_Har1",100,0.,10.); fHistProVPtHar1->SetXTitle("Pt"); fHistProVPtHar1->SetYTitle("v (%)"); fHistProVPtHar2 = new TProfile("Second_FlowProLYZ_VPt_Har2","Second_FlowProLYZ_VPt_Har2",100,0.,10.); fHistProVPtHar2->SetXTitle("Pt"); fHistProVPtHar2->SetYTitle("v (%)"); fHistVPtHar2 = new TH1D("Second_FlowLYZ_VPt_Har2","Second_FlowLYZ_VPt_Har2",100,0.,10.); fHistVPtHar2->SetXTitle("Pt"); fHistVPtHar2->SetYTitle("v (%)"); fHistProReDtheta = new TProfile("Second_FlowProLYZ_ReDtheta_Har2","Second_FlowProLYZ_ReDtheta_Har2",fNtheta, -0.5, fNtheta-0.5); fHistProReDtheta->SetXTitle("#theta"); fHistProReDtheta->SetYTitle("Re(D^{#theta})"); fHistProImDtheta = new TProfile("Second_FlowProLYZ_ImDtheta_Har2","Second_FlowProLYZ_ImDtheta_Har2",fNtheta, -0.5, fNtheta-0.5); fHistProImDtheta->SetXTitle("#theta"); fHistProImDtheta->SetYTitle("Im(D^{#theta})"); //class AliFlowLYZHist2 defines the histograms: for (Int_t j=0;jIsZombie()){ //check if file exists cout << "Error opening file, run first with fFirstrun = kTRUE" << endl; exit(-1); } else if (firstRunFile->IsOpen()){ cout<<"----firstRunFile is open----"<Get("First_FlowProLYZ_Vtheta_Har1"); fHistProVthetaHar2 = (TProfile*)firstRunFile->Get("First_FlowProLYZ_Vtheta_Har2"); fHistProR0thetaHar2 = (TProfile*)firstRunFile->Get("First_FlowProLYZ_r0theta_Har2"); fHistProV = (TProfile*)firstRunFile->Get("First_FlowProLYZ_V"); } } if (fDebug) cout<<"****Histograms initialised****"<SetCompressionLevel(1); fFlowTree = new TTree("FlowTree", "Flow Summary Tree"); fFlowTree->SetAutoSave(1000000); // autosave when 1 Mbyte written fFlowTree->Branch("fLYZSummary","AliFlowLYZSummary",&fLYZSummary,25000,99); } */ return kTRUE; } //----------------------------------------------------------------------- Bool_t AliFlowLeeYangZerosMaker::Make(AliFlowEvent* fFlowEvent) { //make method if (fDebug) cout<<"****AliFlowLeeYangZerosMaker::Make()****"<TrackCollection(); if (fDebug) cout<<"****fFlowSelect in Make() "<PrintSelectionList() ; if (fDebug) fFlowSelect->PrintList() ; if (fFlowSelect && fFlowSelect->Select(fFlowEvent)) // check if event is selected { fFlowTracks = fFlowEvent->TrackCollection(); //get tracks from event fFlowEvent->SetSelections(fFlowSelect) ; // does the selection of tracks for r.p. calculation (sets flags in AliFlowTrack) if (fFirstRun){ MakeControlHistograms(fFlowEvent); FillFromFlowEvent(fFlowEvent); } else { MakeControlHistograms(fFlowEvent); SecondFillFromFlowEvent(fFlowEvent); } } } else { cout<<"##### FlowLeeYangZero: FlowEvent pointer null"<first harmonic, j=1 ->second harmonic { Float_t fMeanMult = fHistMult->GetMean(); //cerr<<"fMeanMult = "<FillGtheta(); fR0 = fHist1[j][theta]->GetR0(); //cerr<<"fR0 = "<SetBinError(b+1,fv2Err); } if (fDebug) cout<<"****histograms filled****"<IsOpen()) { fSummaryFile->Write(0,TObject::kOverwrite); fSummaryFile->Close(); } } */ //save histograms in file //temp for testing selector fHistFile->cd(); fHistFile->Write(); return kTRUE; fEventNumber =0; //set to zero for second round over events } //firstrun else { //second run //calculate differential flow //declare variables Float_t fEta, fPt, fReRatio, fVeta, fVPt; Float_t fReDenom = 0; Float_t fImDenom = 0; Double_t fR0 = 0; TComplex fDenom, fNumer, fDtheta; Int_t m = 1; TComplex i = TComplex::I(); Float_t fBesselRatio[3] = {1., 1.202, 2.69}; Double_t fErrdifcomb = 0.; //set error to zero Double_t fErr2difcomb = 0.; //set error to zero /* //v1 integrated for (Int_t j=0;jfirst harmonic, j=1 ->second harmonic { for (Int_t theta=0;thetaFillGtheta()); fReDenom = fHistProReDenomHar2->GetBinContent(theta+1); fImDenom = fHistProImDenomHar2->GetBinContent(theta+1); TComplex fDenom(fReDenom,fImDenom); //complete!! }//end of loop over theta }//end of loop over harmonics */ //differential flow //for (Int_t j=0;jfirst harmonic, j=1 ->second harmonic //{ Int_t j=1; //temp only harm 2 //fFlowSelect->SetHarmonic(j); //not needed here? for (Int_t theta=0;thetaGetBinContent(theta+1); fVtheta = 2.405/fR0; //fVtheta = fHistProVthetaHar1->GetBinContent(theta+1); // BP Eq. 9 -> Vn^theta = j01/r0^theta fReDenom = fHistProReDenomHar1->GetBinContent(theta+1); fImDenom = fHistProImDenomHar1->GetBinContent(theta+1); } if (j==1) { fR0 = fHistProR0thetaHar2->GetBinContent(theta+1); if (fDebug) cerr<<"fR0 = "< Vn^theta = j01/r0^theta fReDenom = fHistProReDenomHar2->GetBinContent(theta+1); fImDenom = fHistProImDenomHar2->GetBinContent(theta+1); } fDenom(fReDenom,fImDenom); //for new method and use by others (only with the sum generating function): if (fUseSum) { fR0 = fHistProR0thetaHar2->GetBinContent(theta+1); fDtheta = fR0*fDenom; fHistProReDtheta->Fill(theta,fDtheta.Re()); fHistProImDtheta->Fill(theta,fDtheta.Im()); } fDenom *= TComplex::Power(i, m-1); //cerr<<"TComplex::Power(i, m-1) = "<GetBinCenter(be); fNumer = fHist2[j][theta]->GetfNumer(be); if (fNumer.Rho()==0) { if (fDebug) cerr<<"WARNING: modulus of fNumer is zero in Finish()"<GetBinError(b)<cd(); fHistFile->Write(); fHistFile->Close(); //Note that when the file is closed, all histograms and Trees in memory associated with this file are deleted if (fDebug) cout<<"****Histograms saved and fHistFile closed, all histograms deleted****"<Close(); } //secondrun delete fFlowSelect; cout<<"----LYZ analysis finished....----"<SetSelection(1); fFlowSelect->SetHarmonic(1); //second harmonic //cerr<<"selection in MakeControlHistograms()"<PrintSelectionList() ; //fFlowSelect->PrintList() ; fFlowTracks = fFlowEvent->TrackCollection(); Int_t fNumberOfTracks = fFlowTracks->GetEntries(); fHistOrigMult->Fill(fNumberOfTracks); //cerr<<"fNumberOfTracks = "<Mult(fFlowSelect); // Multiplicity of tracks in the specified Selection fHistMult->Fill(fMult); //cerr<<"Mult = "<Q(fFlowSelect); fQmult = fQ.Mod()/TMath::Sqrt(fNumberOfTracks); fHistQ->Fill(fQmult); Int_t tempmult = 0; //for testing for (Int_t i=0;iAt(i) ; //get object at array position i //if (fFlowSelect->SelectPart(fFlowTrack)) //if track is selected if (fFlowSelect->Select(fFlowTrack)) { fPt = fFlowTrack->Pt(); fHistPt->Fill(fPt); tempmult++; fPhi = fFlowTrack->Phi(); if (fPhi<0.) fPhi+=2*TMath::Pi(); fHistPhi->Fill(fPhi); fEta = fFlowTrack->Eta(); fHistEta->Fill(fEta); } } if (fMult!=tempmult){cerr<<"ERROR: Mult() is not tempmult! "<SetSelection(1); for (Int_t j=0;jfirst harmonic, j=1 ->second harmonic { Int_t m=1; fFlowSelect->SetHarmonic(j); Float_t fOrder = (double)((j+1)/m); //cerr<<"fOrder = "<Q(fFlowSelect); //for chi calculation: if (j==1) //second harmonic only temporarily { fQsum += fQ; fQ2sum += fQ.Mod2(); //cerr<<"fQ2sum = "<TrackCollection(); for (Int_t theta=0;thetaSetSelection(1); //cerr<<"selection in SecondFillFromFlowEvent()"<PrintSelectionList() ; //fFlowSelect->PrintList() ; for (Int_t j=0;jfirst harmonic, j=1 ->second harmonic { m=1; fFlowSelect->SetHarmonic(j); fOrder = (double)((j+1)/m); //get the Q vector from the FlowEvent TVector2 fQ = fFlowEvent->Q(fFlowSelect); //for chi calculation: if (j==1) //second harmonic only temporarily { fQsum += fQ; fQ2sum += fQ.Mod2(); //cerr<<"fQ2sum = "<TrackCollection(); for (Int_t theta=0;thetaEta(); //rapidity fPt = fFlowTrack->Pt(); fHist2[j][theta]->Fill(fEta,fPt,fNumer); } //if } //loop over tracks } //sum else //product generating function { fDenom = GetDiffFlow(fFlowSelect,fR0,theta); }//product fHistProReDenomHar2->Fill(theta,fDenom.Re()); //fill the real part of fDenom fHistProImDenomHar2->Fill(theta,fDenom.Im()); //fill the imaginary part of fDenom }//j==1 }//end of loop over theta }//loop over harmonics return kTRUE; } //----------------------------------------------------------------------- Double_t AliFlowLeeYangZerosMaker::GetQtheta(AliFlowSelection* fFlowSelect, TObjArray* fFlowTracks, Float_t fTheta) { //calculate Qtheta. Qtheta is the sum over all particles of cos(fOrder*(fPhi-fTheta)) BP eq. 3 if (fDebug) cout<<"****AliFlowLeeYangZerosMaker::GetQtheta()****"<Har(); Double_t fOrder = (double)(fHarmonic+1); Int_t fNumberOfTracks = fFlowTracks->GetEntries(); //cerr<<"GetQtheta::fNumberOfTracks = "<At(i) ; //get object at array position i if(fFlowSelect->Select(fFlowTrack)) //if track is selected //gives the same number of particles as Mult(fFlowSelect) method { Float_t fPhi = fFlowTrack->Phi(); fQtheta += cos(fOrder*(fPhi-fTheta)); } }//loop over tracks return fQtheta; } //----------------------------------------------------------------------- TComplex AliFlowLeeYangZerosMaker::GetGrtheta(AliFlowSelection* fFlowSelect, Float_t fR, Float_t fTheta) { // Product Generating Function for LeeYangZeros method // PG Eq. 3 (J. Phys. G Nucl. Part. Phys 30 S1213 (2004)) if (fDebug) cout<<"****AliFlowLeeYangZerosMaker::GetGrtheta()****"<Har(); Double_t fOrder = (double)(fHarmonic+1); Double_t fWgt = 1.; Int_t fNumberOfTracks = fFlowTracks->GetEntries(); //cerr<<"GetGrtheta::fNumberOfTracks = "<At(i) ; //get object at array position i if (fFlowSelect->SelectPart(fFlowTrack)) //if track is selected { Float_t fPhi = fFlowTrack->Phi(); Double_t fGIm = fR * fWgt*cos(fOrder*(fPhi - fTheta)); TComplex fGi(1., fGIm); fG *= fGi; //product over all tracks }//if }//loop over tracks return fG; } //----------------------------------------------------------------------- TComplex AliFlowLeeYangZerosMaker::GetDiffFlow(AliFlowSelection* fFlowSelect, Float_t fR0, Int_t theta) { // Sum for the denominator for diff. flow for the Product Generating Function for LeeYangZeros method // PG Eq. 9 (J. Phys. G Nucl. Part. Phys 30 S1213 (2004)) // Also for v1 mixed harmonics: DF Eq. 5 // It is the deriverative of Grtheta at r0 divided by Grtheta at r0 if (fDebug) cout<<"****AliFlowLeeYangZerosMaker::GetGrtheta()****"<Har(); Double_t fOrder = (double)(fHarmonic+1); Double_t fWgt = 1.; Int_t fNumberOfTracks = fFlowTracks->GetEntries(); //cerr<<"GetGrtheta::fNumberOfTracks = "<At(i) ; //get object at array position i if (fFlowSelect->SelectPart(fFlowTrack)) //if track is selected { Float_t fPhi = fFlowTrack->Phi(); Double_t fCosTerm = fWgt*cos(fOrder*(fPhi - fTheta)); //GetGr0theta Double_t fGIm = fR0 * fCosTerm; TComplex fGi(1., fGIm); fG *= fGi; //product over all tracks //GetdGr0theta TComplex fCosTermComplex(1., fR0*fCosTerm); fdGr0 +=(fCosTerm / fCosTermComplex); //sum over all tracks }//if }//loop over tracks for (Int_t i=0;iAt(i) ; //get object at array position i if (fFlowSelect->SelectPart(fFlowTrack)) //if track is selected { Float_t fPhi = fFlowTrack->Phi(); Double_t fCosTerm = cos(fOrder*(fPhi-fTheta)); TComplex fCosTermComplex(1.,fR0*fCosTerm); TComplex fNumer = fG*fCosTerm/fCosTermComplex; //PG Eq. 9 Float_t fEta = fFlowTrack->Eta(); //rapidity Float_t fPt = fFlowTrack->Pt(); fHist2[1][theta]->Fill(fEta,fPt,fNumer); }//if }//loop over tracks TComplex fDenom = fG*fdGr0; return fDenom; } //-------------------------------------------------