1 //Author: Dariusz Miskowiec 2007
3 //=============================================================================
4 // simple event loop manager
5 // First, events are classified according to centrality, reaction plane angle,
6 // and z-vertex. Then, single particles and true pairs are processed. Finally,
7 // event mixing is done within event classes. For this, the tree and the event
8 // passed as arguments are cloned.
9 // The class is, at present, deliberately left in a macro-like design, with all
10 // the essential things happening inside the function AliDLoop::Run. This is
11 // subject to future polishing if the class proves useful.
12 //=============================================================================
17 #include <TStopwatch.h>
19 #include "AliDAnalGlobal.h"
20 #include "AliDAnalSingle.h"
21 #include "AliDAnalCorrel.h"
22 #include "AliDAnalPtfluc.h"
23 #include "AliDEvent.h"
27 //=============================================================================
28 AliDLoop::AliDLoop(TTree *tr, AliDEvent *ev0, char *outfil):
30 fTree0(tr), fTree1(0x0),
32 fOutputFilename(outfil)
35 // Clone the tree such that during the event mixing the two events get
36 // populated from two different trees. This costs some memory (37 MB for
37 // ceres) but allows to avoid switching one tree between two different
38 // events, especially difficult for alice because alice trees do not like
39 // to be attached more than once.
41 fTree1 = (TTree*) tr->Clone();
42 fEv1 = (AliDEvent*) ev0->Clone();
43 fEv0->AttachTree(fTree0);
44 fEv1->AttachTree(fTree1);
46 //=============================================================================
47 AliDLoop::AliDLoop(const AliDLoop &loop) :
48 TObject(loop), fTree0(loop.fTree0), fTree1(loop.fTree1), fEv0(loop.fEv0),
49 fEv1(loop.fEv1), fOutputFilename(loop.fOutputFilename)
51 //copy constructor, shallow copy, just to make the compiler happy
53 //=============================================================================
54 AliDLoop &AliDLoop::operator=(const AliDLoop &source)
56 // substitution operator, shallow copy, just to make the compiler happy
58 TObject::operator=(source);
59 fTree0 = source.fTree0;
60 fTree1 = source.fTree1;
63 fOutputFilename = source.fOutputFilename;
66 //=============================================================================
67 Int_t AliDLoop::Mem() const
69 // return memory in MB occupied by this process
72 gSystem->GetProcInfo(&info);
73 Int_t memmb = info.fMemVirtual/1024;
76 //=============================================================================
77 void AliDLoop::Run(int nwish)
79 // process nwish events from fTree0; nwish=-1 (default) means process all
84 // const int kcen = 10; // number of centrality bins for mixing
85 // const int kphi = 8; // number of phi bins for mixing
86 // const int kzve = 13; // number of z-vertex bins for mixing
87 const int kcen = 1; // number of centrality bins for mixing
88 const int kphi = 1; // number of phi bins for mixing
89 const int kzve = 1; // number of z-vertex bins for mixing
90 int mixingFactor = 1; // number of wished event pairs/number of events
91 int mixingStep[10] = {2,3,5,7,11,13,17,19,23,29};
92 if (mixingFactor>=10) {printf("mixing factor too high\n"); exit(-1);}
93 int minn = 20*mixingFactor; // minimum number of events per bin
94 int pr = !gROOT->IsBatch(); // more printing in interactive mode
96 // initialize analysis
98 Double_t etami = fEv0->Etamin();
99 Double_t etama = fEv0->Etamax();
100 AliDAnalGlobal *dag = new AliDAnalGlobal("dag");
101 AliDAnalSingle *all = new AliDAnalSingle("all",etami,etama,0);
102 AliDAnalSingle *pim = new AliDAnalSingle("pim",etami,etama,-211);
103 AliDAnalSingle *pip = new AliDAnalSingle("pip",etami,etama, 211);
104 AliDAnalCorrel *cnn = new AliDAnalCorrel("cnn",etami,etama,-211,-211);
105 AliDAnalCorrel *cpp = new AliDAnalCorrel("cpp",etami,etama, 211, 211);
106 AliDAnalPtfluc *ptf = new AliDAnalPtfluc("ptf",-211,-211);
108 // initialize number of events etc
110 printf("\ndetermining number of events in chain...");
111 int nmax = fTree0->GetEntries();
113 if (nwish>-1 && nwish<nmax) nact = nwish;
114 printf("analyzing %d events of %d\n\n",nact,nmax);
120 // find groups of of similar events
121 // first allocate nact entries to each array; later reduce
123 printf("%4d MB; booking event index arrays\n",Mem());
124 TArrayI *ar[kcen][kphi][kzve];
125 int nar[kcen][kphi][kzve];
126 for (int i=0; i<kcen; i++)
127 for (int j=0; j<kphi; j++)
128 for (int k=0; k<kzve; k++) {
129 ar[i][j][k] = new TArrayI(nact);
132 printf("%4d MB; filling event index arrays\n",Mem());
133 for (int i=0; i<nact; i++) {
135 if (!fEv0->Good()) continue;
136 int icen = (int) (kcen*fEv0->Centrality());
137 int iphi = (int) (kphi*(fEv0->RPphi()/TMath::Pi()+1)/2);
138 int izve = (int) (kzve*(fEv0->Zver()+1.0)/2.0);
139 if (pr) printf("\revent %5d %2d%2d%2d",i,icen,iphi,izve);
140 if (icen<0 || icen>=kcen) continue;
141 if (iphi<0 || iphi>=kphi) continue;
142 if (izve<0 || izve>=kzve) continue;
143 ar[icen][iphi][izve]->AddAt(i,nar[icen][iphi][izve]);
144 nar[icen][iphi][izve]++;
146 if (pr) printf("\n");
148 printf("%4d MB; shrinking event index arrays\n",Mem());
151 for (int i=0; i<kcen; i++)
152 for (int j=0; j<kphi; j++)
153 for (int k=0; k<kzve; k++) {
154 nall += nar[i][j][k];
155 // suppress scarse bins
156 if (nar[i][j][k]<minn) {
157 nsup += nar[i][j][k];
160 ar[i][j][k]->Set(nar[i][j][k]);
162 printf("%4d MB; %d events sorted into bins\n",Mem(),nall);
163 printf("%d events suppressed because bin occupancy was below %d\n",nsup,minn);
164 printf("sorting events took %.1f s CPU %.1f s real %.1f ms real per event\n\n",
165 sto.CpuTime(),sto.RealTime(),1000*sto.RealTime()/nall);
166 if ((nall-=nsup) < 1) return;
170 printf("%4d MB; starting the main loop\n",Mem());
173 for (int i=0; i<kcen; i++)
174 for (int j=0; j<kphi; j++)
175 for (int k=0; k<kzve; k++) {
179 int nevents = ar[i][j][k]->GetSize(); // number of events in this bin
180 for (int l=0; l<nevents; l++) {
181 if (pr) printf("\revent %6d of %6d %3d%3d%3d",l,nevents,i,j,k);
182 int m = ar[i][j][k]->At(l);
188 cnn->Process(0,fEv0,fEv0,0);
189 cnn->Process(2,fEv0,fEv0,TMath::DegToRad()*180);
190 cpp->Process(0,fEv0,fEv0,0);
191 cpp->Process(2,fEv0,fEv0,TMath::DegToRad()*180);
192 ptf->Process(0,fEv0,fEv0);
194 if (pr && nevents) printf("\n");
197 // loop somewhat optimized to reduce jumping back and forth
199 for (int imix=0; imix<mixingFactor; imix++) {
200 int step = mixingStep[imix];
201 for (int phase=0; phase<step; phase++) for (int l=phase; l<nevents; l+=step) {
202 int m0 = ar[i][j][k]->At(l);
203 int next = (l+step)%nevents;
204 int m1 = ar[i][j][k]->At(next);
205 if (pr) printf("\rmixing %5d and %5d",m0,m1);
206 fTree0->GetEvent(m0);
207 fTree1->GetEvent(m1);
208 //printf(" event0 %f event1 %f\n",fEv0->ParticleP(0),fEv1->ParticleP(0));
209 cnn->Process(1,fEv0,fEv1,0);
210 cpp->Process(1,fEv0,fEv1,0);
211 ptf->Process(1,fEv0,fEv1);
213 if (pr && nevents) printf("\r");
218 printf("event loop took %.1f s CPU %.1f s real %.1f ms real per event\n\n",
219 sto.CpuTime(),sto.RealTime(),1000*sto.RealTime()/nall);
221 // save analysis results
223 dag->Save(fOutputFilename.Data(),"recreate");
224 all->Save(fOutputFilename.Data());
225 pim->Save(fOutputFilename.Data());
226 pip->Save(fOutputFilename.Data());
227 cnn->Save(fOutputFilename.Data());
228 cpp->Save(fOutputFilename.Data());
229 ptf->Save(fOutputFilename.Data());
231 //=============================================================================