]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/UNICOR/AliUnicorHN.cxx
extra macro to illustrate behavior centrality variables
[u/mrichter/AliRoot.git] / PWG2 / UNICOR / AliUnicorHN.cxx
CommitLineData
621688e4 1/*************************************************************************
2* Copyright(c) 1998-2048, ALICE Experiment at CERN, All rights reserved. *
3* *
4* Author: The ALICE Off-line Project. *
5* Contributors are mentioned in the code where appropriate. *
6* *
7* Permission to use, copy, modify and distribute this software and its *
8* documentation strictly for non-commercial purposes is hereby granted *
9* without fee, provided that the above copyright notice appears in all *
10* copies and that both the copyright notice and this permission notice *
11* appear in the supporting documentation. The authors make no claims *
12* about the suitability of this software for any purpose. It is *
13* provided "as is" without express or implied warranty. *
14**************************************************************************/
15
16// Author: Dariusz Miskowiec <mailto:d.miskowiec@gsi.de> 2007
17
18//=============================================================================
19// multidimensional histogram
20// Physically, the data are kept in one single one-dimensional histogram.
21// Projecting on 1, 2, and n-1 dimensions is implemented.
22// The histogram can be saved on root file as the one-dimensional data
23// histogram and the axes, thus eternal forward compatibility is ensured.
24//=============================================================================
25
26#include <cmath>
27#include <stdlib.h>
28#include <TFile.h>
29#include <TDirectory.h>
30#include <TAxis.h>
31#include <TH2.h>
32#include "AliUnicorHN.h"
33
34ClassImp(AliUnicorHN)
35
36//=============================================================================
61e4657c 37AliUnicorHN::AliUnicorHN(const char *nam, Int_t ndim, TAxis **ax)
621688e4 38 : TH1D(nam, nam, Albins(ndim,ax), 0.5, Albins(ndim,ax)+0.5),
61e4657c 39 fNdim(ndim)
621688e4 40{
41 // Constructor for building from scratch.
42
43 // Above, we just have managed to create a single one-dimensional histogram
44 // with number of bins equal to the product of the numbers of bins in all
45 // dimensions. For easy inspection the histogram range was set to -0.5,n-0.5.
46
c6fc7f72 47 for (int i=0; i<fNdim; i++) ax[i]->SetName(Form("axis%d",i));
621688e4 48 for (int i=0; i<fNdim; i++) ax[i]->Copy(fAxis[i]);
49
50 // for speed reasons, number of bins of each axis is stored on fNbins
51 // and the running product of the latter on fMbins
52 // so fMbins = {...,fNbins[fNdim-2]*fNbins[fNdim-1],fNbins[fNdim-1],1}
53
61e4657c 54 for (int i=0; i<fgkMaxNdim; i++) fNbins[i] = fAxis[i].GetNbins();
55 for (int i=0; i<fgkMaxNdim; i++) fMbins[i] = 1;
621688e4 56 for (int i=fNdim-1; i>0; i--) fMbins[i-1] = fMbins[i]*fNbins[i];
c6fc7f72 57 printf(" %d-dimensional histogram %s with %d bins created\n",fNdim,nam,GetNbinsX());
621688e4 58}
59//=============================================================================
61e4657c 60AliUnicorHN::AliUnicorHN(const char *filnam, const char *nam) :
76d78859 61 TH1D(*(TFile::Open(filnam,"read")?
62 TFile::Open(filnam,"read")->GetDirectory(nam)?
63 (TH1D*) TFile::Open(filnam,"read")->GetDirectory(nam)->Get("histo"):new TH1D():new TH1D()
64 )),
65 fNdim(0)
621688e4 66{
67 // Constructor for reading from file.
68
69 TFile *f = TFile::Open(filnam,"read");
76d78859 70 if (f) if (f->cd(nam)) {
71 TAxis *ax[fgkMaxNdim];
72 for (fNdim=0; fNdim<fgkMaxNdim; fNdim++) {
73 ax[fNdim] = (TAxis *) gDirectory->Get(Form("axis%d",fNdim));
74 if (ax[fNdim]) ax[fNdim]->Copy(fAxis[fNdim]);
75 else break;
76 }
77 f->Close();
78
61e4657c 79 for (int i=0; i<fgkMaxNdim; i++) fNbins[i] = fAxis[i].GetNbins();
80 for (int i=0; i<fgkMaxNdim; i++) fMbins[i] = 1;
76d78859 81 for (int i=fNdim-1; i>0; i--) fMbins[i-1] = fMbins[i]*fNbins[i];
82
83 if (GetNbinsX()!=Albins(fNdim,ax)) {
84 printf("number of bins of histo %d differs from product of nbins of axes %d\n",
85 GetNbinsX(),Albins(fNdim,ax));
86 printf("bombing\n");
87 exit(-1);
88 }
621688e4 89
76d78859 90 printf("%d-dimensional histogram %s with %d bins read from file %s\n",
91 fNdim,nam,GetNbinsX(),filnam);
621688e4 92 }
621688e4 93}
94//=============================================================================
95Int_t AliUnicorHN::Albins(Int_t n, TAxis **ax)
96{
97 // Calculate product of nbins of ax[0]...ax[n-1]
98 // (= total number of bins of the multidimensional histogram to be made).
99
100 Int_t nbins = 1;
101 // while (n--) nbins *= ax[n]->GetNbins();
102 for (int i=0; i<n; i++) nbins *= ax[i]->GetNbins();
103 return nbins;
104}
105//=============================================================================
c6fc7f72 106Int_t AliUnicorHN::MulToOne(const Int_t * const k) const
621688e4 107{
108 // Calculate the 1-dim index n from n-dim indices k[fNdim].
109 // Valid k[i] should be between 0 and fNbins[i]-1.
110 // Valid result will be between 0 and GetNbinsX()-1.
111 // Return -1 if under- or overflow in any dimension.
112
113 Int_t n = 0;
114 for (int i=0; i<fNdim; i++) {
115 if (k[i]<0) return -1;
116 if (k[i]>=fNbins[i]) return -1;
117 n += fMbins[i]*k[i];
118 }
119 return n;
120}
121//=============================================================================
122Int_t AliUnicorHN::MulToOne(Double_t *x)
123{
124 // Calculate the 1-dim index n from n-dim vector x, representing the
125 // abscissa of the n-dim histogram. The result will be between 0 and
126 // GetNbinsX()-1.
127
61e4657c 128 Int_t k[fgkMaxNdim] = {0};
621688e4 129 for (int i=0; i<fNdim; i++) k[i] = fAxis[i].FindBin(x[i])-1;
130 return MulToOne(k);
131}
132//=============================================================================
133void AliUnicorHN::OneToMul(Int_t n, Int_t *k) const
134{
135 // Calculate the n-dim indices k[fNdim] from 1-dim index n.
136 // Valid n should be between 0 and GetNbinsX()-1.
137 // Valid results will be between 0 and fNbins[i]-1.
138
139 div_t idi; // integer division structure
140 for (int i=0; i<fNdim; i++) {
141 idi = div(n,fMbins[i]);
142 k[i] = idi.quot; // quotient
143 n = idi.rem; // remainder
144 }
145}
146//=============================================================================
c6fc7f72 147Int_t AliUnicorHN::Fill(Double_t *xx, Double_t w)
621688e4 148{
149 // Fill the histogram. The array xx holds the abscissa information, w is the
150 // weigth. The 1-dim histogram is filled using the standard Fill method
151 // (direct access to the arrays was tried and was not faster).
152
153 int nbin = MulToOne(xx);
154 if (nbin == -1) return 0;
155 return TH1D::Fill(nbin+1,w);
156}
157//=============================================================================
158Int_t AliUnicorHN::Fill(Double_t x0, Double_t x1, ...)
159{
160 // Fill the histogram. Arguments are passed as doubles rather than array.
161 va_list ap;
162 Double_t xx[fgkMaxNdim] = {x0, x1};
163 va_start(ap,x1);
164 for (int i=2; i<fNdim; i++) xx[i] = va_arg(ap,Double_t);
165 Double_t weigth = va_arg(ap,Double_t);
166 va_end(ap);
c6fc7f72 167 //for (int i=0; i<fgkMaxNdim; i++) printf("%8.2f ",xx[i]); printf("%6.2f \n",weigth);
621688e4 168 return Fill(xx,weigth);
169}
170//=============================================================================
171Int_t AliUnicorHN::Write() const
172{
173 // Save the 1-dim histo and the axes in a subdirectory on file. This might
174 // not be the most elegant way but it is very simple and backward and forward
175 // compatible.
176
177 Int_t nbytes = 0;
178 TH1D histo(*this);
179 histo.SetName("histo"); // hadd bug fix; actually, does not cost memory, strange
180
181 TDirectory *dest = gDirectory->mkdir(GetName());
182 if (dest) {
183 dest->cd();
184 nbytes += histo.Write("histo");
c6fc7f72 185 for (int i=0; i<fNdim; i++) nbytes += fAxis[i].Write();
621688e4 186 printf(" %s stored in %s\n",GetName(),dest->GetPath());
187 dest->cd("..");
188 }
189 return nbytes;
190}
191//=============================================================================
61e4657c 192AliUnicorHN *AliUnicorHN::ProjectAlong(const char *nam, Int_t dim, Int_t first, Int_t last)
621688e4 193{
194 // Reduce dimension dim by summing up its bins between first and last.
195 // Use root convention: bin=1 is the first bin, bin=nbins is the last.
76d78859 196 // last=0 means till the last bin
621688e4 197 // Return the resulting fNdim-1 dimensional histogram.
198
199 if (dim<0 || dim>fNdim-1) return 0;
76d78859 200 if (last<=0) last = fNbins[dim];
621688e4 201
202 // create new (reduced) histogram
203
61e4657c 204 TAxis *ax[fgkMaxNdim-1] = {0};
621688e4 205 int n=0;
206 for (int i=0; i<fNdim; i++) if (i!=dim) ax[n++] = GetAxis(i);
61e4657c 207 const char *name = strlen(nam)? nam : Form("%s_wo%d",GetName(),dim);
208 const char *eame = Form("%s_error",name);
621688e4 209 AliUnicorHN *his = new AliUnicorHN(name,fNdim-1,ax); // result histogram
210 AliUnicorHN *eis = new AliUnicorHN(eame,fNdim-1,ax); // temporary storage for errors
211
212 // sum up the content and errors squared
213
61e4657c 214 int k[fgkMaxNdim] = {0}; // old hist multiindex
215 int m[fgkMaxNdim] = {0}; // new hist multiindex
621688e4 216 for (int i=0; i<GetNbinsX(); i++) {
217 OneToMul(i,k);
218 if (k[dim]+1<first) continue;
219 if (k[dim]+1>last) continue;
220 n = 0;
221 for (int j=0; j<fNdim; j++) if (j!=dim) m[n++] = k[j];
222 n = his->MulToOne(m);
223 his->AddBinContent(n+1,GetBinContent(i+1));
224 eis->AddBinContent(n+1,GetBinError(i+1)*GetBinError(i+1));
225 }
226
227 // combine content and errors in one histogram
228
229 for (int i=0; i<his->GetNbinsX(); i++) {
230 his->SetBinError(i+1,sqrt(eis->GetBinContent(i+1)));
231 }
232
233 his->SetLineColor(this->GetLineColor());
234 his->SetFillColor(this->GetFillColor());
235 his->SetMarkerColor(this->GetMarkerColor());
236 his->SetMarkerStyle(this->GetMarkerStyle());
237
238 // some cleanup
239
240 delete eis;
241 return his;
242}
243//=============================================================================
61e4657c 244TH1D *AliUnicorHN::ProjectOn(const char *nam, Int_t dim, const Int_t * const first, const Int_t * const last) const
621688e4 245{
246 // Project on dimension dim. Use only bins between first[i] and last[i].
247 // Use root convention: bin=1 is the first bin, bin=nbins is the last.
248 // first[i]=0 means from the first bin
249 // last[i]=0 means till the last bin
250
251 if (dim<0 || dim>fNdim-1) return 0;
252
253 // calculate the projection; lowest index 0
254
255 double *yy = new double[fNbins[dim]]; // value
256 double *ey = new double[fNbins[dim]]; // error
257 for (int i=0; i<fNbins[dim]; i++) yy[i]=0;
258 for (int i=0; i<fNbins[dim]; i++) ey[i]=0;
259 Int_t *k = new Int_t[fNdim];
260 for (int i=0; i<GetNbinsX(); i++) {
261 OneToMul(i,k);
262 int isgood = 1; // bin within the range?
263 for (int j=0; j<fNdim; j++) {
264 if (first) if (first[j]) if (k[j]+1<first[j]) {isgood = 0; break;}
265 if (last) if (last[j]) if (k[j]+1>last[j]) {isgood = 0; break;}
266 }
267 if (isgood) {
268 yy[k[dim]]+=GetBinContent(i+1);
269 ey[k[dim]]+=GetBinError(i+1)*GetBinError(i+1);
270 }
271 }
272
273 // make the projection histogram
274 // use name nam if specified; otherwise generate one
275
276 TH1D *his;
61e4657c 277 const char *name = strlen(nam)? nam : Form("%s_proj%d",GetName(),dim);
76d78859 278 // if (gDirectory->Get(name)) gDirectory->Get(name)->Delete(); // for some reason leads to troubles
621688e4 279 if (fAxis[dim].IsVariableBinSize())
280 his = new TH1D(name,name,fNbins[dim],fAxis[dim].GetXbins()->GetArray());
281 else
282 his = new TH1D(name,name,fNbins[dim],fAxis[dim].GetXmin(),fAxis[dim].GetXmax());
283 his->SetXTitle(fAxis[dim].GetTitle());
284 // or his->GetXaxis()->ImportAttributes(ax);
285 his->Sumw2();
286 his->SetLineColor(this->GetLineColor());
287 his->SetFillColor(this->GetFillColor());
288 his->SetMarkerColor(this->GetMarkerColor());
289 his->SetMarkerStyle(this->GetMarkerStyle());
290 for (int i=0; i<his->GetNbinsX(); i++) {
291 his->SetBinContent(i+1,yy[i]);
292 his->SetBinError(i+1,sqrt(ey[i]));
293 }
294
295 // some cleanup
296
297 delete [] yy;
298 delete [] ey;
299 delete [] k;
300 // if (name!=nam) delete [] name;
301
302 return his;
303}
304//=============================================================================
61e4657c 305TH1D *AliUnicorHN::ProjectOn(const char *nam, Int_t dim, const Double_t * const first, const Double_t * const last)
621688e4 306{
307 // Project on dimension dim. Use only bins between first[i] and last[i].
308
309 if (dim<0 || dim>fNdim-1) return 0;
61e4657c 310 Int_t kfirst[fgkMaxNdim] = {0};
311 Int_t klast[fgkMaxNdim] = {0};
621688e4 312 for (int i=0; i<fNdim; i++) {
313 kfirst[i] = fAxis[i].FindBin(first[i]);
314 klast[i] = fAxis[i].FindBin(last[i]);
315 }
316 return ProjectOn(nam,dim,kfirst,klast);
317}
318//=============================================================================
61e4657c 319TH2D *AliUnicorHN::ProjectOn(const char *nam, Int_t dim0, Int_t dim1, const Int_t * const first, const Int_t * const last) const
621688e4 320{
321 // Project on dim1 vs dim0. Use only bins between first[i] and last[i].
322 // Use root convention: bin=1 is the first bin, bin=nbins is the last.
323 // first[i]=0 means from the first bin
324 // last[i]=0 means till the last bin
325
326 if (dim0<0 || dim0>fNdim-1) return 0;
327 if (dim1<0 || dim1>fNdim-1) return 0;
328
329 // calculate the projection
330
331 double **yy = new double*[fNbins[dim0]]; // value
332 double **ey = new double*[fNbins[dim0]]; // error
333 for (int i=0; i<fNbins[dim0]; i++) yy[i] = new double[fNbins[dim1]];
334 for (int i=0; i<fNbins[dim0]; i++) ey[i] = new double[fNbins[dim1]];
335 for (int i=0; i<fNbins[dim0]; i++) for (int j=0; j<fNbins[dim1]; j++) yy[i][j]=0;
336 for (int i=0; i<fNbins[dim0]; i++) for (int j=0; j<fNbins[dim1]; j++) ey[i][j]=0;
337 Int_t *k = new Int_t[fNdim];
338 for (int i=0; i<GetNbinsX(); i++) {
339 OneToMul(i,k);
340 int isgood = 1; // bin within the range?
341 for (int j=0; j<fNdim; j++) {
342 if (first) if (first[j]) if (k[j]+1<first[j]) {isgood = 0; break;}
343 if (last) if (last[j]) if (k[j]+1>last[j]) {isgood = 0; break;}
344 }
345 if (isgood) {
346 yy[k[dim0]][k[dim1]]+=GetBinContent(i+1);
347 ey[k[dim0]][k[dim1]]+=GetBinError(i+1)*GetBinError(i+1);
348 }
349 }
350
351 // make the projection histogram
352 // use name nam if specified; otherwise generate one
353
354 TH2D *his=0;
61e4657c 355 const char *name = strlen(nam)? nam : Form("%s_proj%dvs%d",GetName(),dim1,dim0);
621688e4 356 if (fAxis[dim0].IsVariableBinSize() && fAxis[dim1].IsVariableBinSize())
357 his = new TH2D(name,name,
358 fNbins[dim0],fAxis[dim0].GetXbins()->GetArray(),
359 fNbins[dim1],fAxis[dim1].GetXbins()->GetArray());
360 else if (!fAxis[dim0].IsVariableBinSize() && fAxis[dim1].IsVariableBinSize())
361 his = new TH2D(name,name,
362 fNbins[dim0],fAxis[dim0].GetXmin(),fAxis[dim0].GetXmax(),
363 fNbins[dim1],fAxis[dim1].GetXbins()->GetArray());
364 else if (fAxis[dim0].IsVariableBinSize() && !fAxis[dim1].IsVariableBinSize())
365 his = new TH2D(name,name,
366 fNbins[dim0],fAxis[dim0].GetXbins()->GetArray(),
367 fNbins[dim1],fAxis[dim1].GetXmin(),fAxis[dim1].GetXmax());
368 else if (!fAxis[dim0].IsVariableBinSize() && !fAxis[dim1].IsVariableBinSize())
369 his = new TH2D(name,name,
370 fNbins[dim0],fAxis[dim0].GetXmin(),fAxis[dim0].GetXmax(),
371 fNbins[dim1],fAxis[dim1].GetXmin(),fAxis[dim1].GetXmax());
372 his->SetXTitle(fAxis[dim0].GetTitle());
373 his->SetYTitle(fAxis[dim1].GetTitle());
374 // or his->GetXaxis()->ImportAttributes(ax0);
375 // or his->GetYaxis()->ImportAttributes(ax1);
376 his->Sumw2();
377 his->SetLineColor(this->GetLineColor());
378 his->SetFillColor(this->GetFillColor());
379 his->SetMarkerColor(this->GetMarkerColor());
380 his->SetMarkerStyle(this->GetMarkerStyle());
381 for (int i=0; i<his->GetNbinsX(); i++)
382 for (int j=0; j<his->GetNbinsY(); j++) {
383 his->SetBinContent(i+1,j+1,yy[i][j]);
384 his->SetBinError(i+1,j+1,sqrt(ey[i][j]));
385 }
386
387 // some cleanup
388
389 for (int i=0; i<fNbins[dim0]; i++) delete [] yy[i];
390 for (int i=0; i<fNbins[dim0]; i++) delete [] ey[i];
391 delete [] yy;
392 delete [] ey;
393 delete [] k;
394 // if (name!=nam) delete [] name;
395
396 return his;
397}
398//=============================================================================