]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/UNICOR/AliUnicorHN.cxx
Second attempt to add UNICOR. In its present version it is
[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//=============================================================================
37AliUnicorHN::AliUnicorHN(Char_t *nam, Int_t ndim, TAxis **ax)
38 : TH1D(nam, nam, Albins(ndim,ax), 0.5, Albins(ndim,ax)+0.5),
39 fNdim(ndim)
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
47 for (int i=0; i<fNdim; i++) ax[i]->Copy(fAxis[i]);
48
49 // for speed reasons, number of bins of each axis is stored on fNbins
50 // and the running product of the latter on fMbins
51 // so fMbins = {...,fNbins[fNdim-2]*fNbins[fNdim-1],fNbins[fNdim-1],1}
52
53 fMbins[fNdim-1] = 1;
54 for (int i=0; i<fNdim; i++) fNbins[i] = fAxis[i].GetNbins();
55 for (int i=fNdim-1; i>0; i--) fMbins[i-1] = fMbins[i]*fNbins[i];
56 printf("%d-dimensional histogram %s with %d bins created\n",fNdim,nam,GetNbinsX());
57}
58//=============================================================================
59AliUnicorHN::AliUnicorHN(Char_t *filnam, Char_t *nam)
60 : TH1D(*((TH1D*) TFile::Open(filnam,"read")->GetDirectory(nam)->Get("histo"))),
61 fNdim(0)
62{
63 // Constructor for reading from file.
64
65 TFile *f = TFile::Open(filnam,"read");
66 f->cd(nam);
67 TAxis *ax[fgkMaxNdim];
68 char axnam[1000];
69 for (fNdim=0; fNdim<fgkMaxNdim; fNdim++) {
70 sprintf(axnam,"axis%d",fNdim);
71 ax[fNdim] = (TAxis *) gDirectory->Get(axnam);
72 if (ax[fNdim]) ax[fNdim]->Copy(fAxis[fNdim]);
73 else break;
74 }
75 f->Close();
76
77 fMbins[fNdim-1] = 1;
78 for (int i=0; i<fNdim; i++) fNbins[i] = fAxis[i].GetNbins();
79 for (int i=fNdim-1; i>0; i--) fMbins[i-1] = fMbins[i]*fNbins[i];
80
81 if (GetNbinsX()!=Albins(fNdim,ax)) {
82 printf("number of bins of histo %d differs from product of nbins of axes %d\n",
83 GetNbinsX(),Albins(fNdim,ax));
84 printf("bombing\n");
85 exit(-1);
86 }
87 printf("%d-dimensional histogram %s with %d bins read from file %s\n",
88 fNdim,nam,GetNbinsX(),filnam);
89}
90//=============================================================================
91Int_t AliUnicorHN::Albins(Int_t n, TAxis **ax)
92{
93 // Calculate product of nbins of ax[0]...ax[n-1]
94 // (= total number of bins of the multidimensional histogram to be made).
95
96 Int_t nbins = 1;
97 // while (n--) nbins *= ax[n]->GetNbins();
98 for (int i=0; i<n; i++) nbins *= ax[i]->GetNbins();
99 return nbins;
100}
101//=============================================================================
102Int_t AliUnicorHN::MulToOne(Int_t *k) const
103{
104 // Calculate the 1-dim index n from n-dim indices k[fNdim].
105 // Valid k[i] should be between 0 and fNbins[i]-1.
106 // Valid result will be between 0 and GetNbinsX()-1.
107 // Return -1 if under- or overflow in any dimension.
108
109 Int_t n = 0;
110 for (int i=0; i<fNdim; i++) {
111 if (k[i]<0) return -1;
112 if (k[i]>=fNbins[i]) return -1;
113 n += fMbins[i]*k[i];
114 }
115 return n;
116}
117//=============================================================================
118Int_t AliUnicorHN::MulToOne(Double_t *x)
119{
120 // Calculate the 1-dim index n from n-dim vector x, representing the
121 // abscissa of the n-dim histogram. The result will be between 0 and
122 // GetNbinsX()-1.
123
124 Int_t k[fgkMaxNdim];
125 for (int i=0; i<fNdim; i++) k[i] = fAxis[i].FindBin(x[i])-1;
126 return MulToOne(k);
127}
128//=============================================================================
129void AliUnicorHN::OneToMul(Int_t n, Int_t *k) const
130{
131 // Calculate the n-dim indices k[fNdim] from 1-dim index n.
132 // Valid n should be between 0 and GetNbinsX()-1.
133 // Valid results will be between 0 and fNbins[i]-1.
134
135 div_t idi; // integer division structure
136 for (int i=0; i<fNdim; i++) {
137 idi = div(n,fMbins[i]);
138 k[i] = idi.quot; // quotient
139 n = idi.rem; // remainder
140 }
141}
142//=============================================================================
143Int_t AliUnicorHN::Fill(Double_t *xx, Double_t w)
144{
145 // Fill the histogram. The array xx holds the abscissa information, w is the
146 // weigth. The 1-dim histogram is filled using the standard Fill method
147 // (direct access to the arrays was tried and was not faster).
148
149 int nbin = MulToOne(xx);
150 if (nbin == -1) return 0;
151 return TH1D::Fill(nbin+1,w);
152}
153//=============================================================================
154Int_t AliUnicorHN::Fill(Double_t x0, Double_t x1, ...)
155{
156 // Fill the histogram. Arguments are passed as doubles rather than array.
157 va_list ap;
158 Double_t xx[fgkMaxNdim] = {x0, x1};
159 va_start(ap,x1);
160 for (int i=2; i<fNdim; i++) xx[i] = va_arg(ap,Double_t);
161 Double_t weigth = va_arg(ap,Double_t);
162 va_end(ap);
163 return Fill(xx,weigth);
164}
165//=============================================================================
166Int_t AliUnicorHN::Write() const
167{
168 // Save the 1-dim histo and the axes in a subdirectory on file. This might
169 // not be the most elegant way but it is very simple and backward and forward
170 // compatible.
171
172 Int_t nbytes = 0;
173 TH1D histo(*this);
174 histo.SetName("histo"); // hadd bug fix; actually, does not cost memory, strange
175
176 TDirectory *dest = gDirectory->mkdir(GetName());
177 if (dest) {
178 dest->cd();
179 nbytes += histo.Write("histo");
180 char axnam[1000];
181 for (int i=0; i<fNdim; i++) {
182 sprintf(axnam,"axis%d",i);
183 nbytes += fAxis[i].Write(axnam);
184 }
185 printf(" %s stored in %s\n",GetName(),dest->GetPath());
186 dest->cd("..");
187 }
188 return nbytes;
189}
190//=============================================================================
191AliUnicorHN *AliUnicorHN::ProjectAlong(char *nam, Int_t dim, Int_t first, Int_t last)
192{
193 // Reduce dimension dim by summing up its bins between first and last.
194 // Use root convention: bin=1 is the first bin, bin=nbins is the last.
195 // Return the resulting fNdim-1 dimensional histogram.
196
197 if (dim<0 || dim>fNdim-1) return 0;
198 if (first<0) first = 1;
199 if (last<0) last = fNbins[dim];
200
201 // create new (reduced) histogram
202
203 TAxis *ax[fgkMaxNdim-1];
204 int n=0;
205 for (int i=0; i<fNdim; i++) if (i!=dim) ax[n++] = GetAxis(i);
206 char *name = strlen(nam)? nam : Form("%s_wo%d",GetName(),dim);
207 char *eame = Form("%s_error",name);
208 AliUnicorHN *his = new AliUnicorHN(name,fNdim-1,ax); // result histogram
209 AliUnicorHN *eis = new AliUnicorHN(eame,fNdim-1,ax); // temporary storage for errors
210
211 // sum up the content and errors squared
212
213 Int_t *k = new Int_t[fNdim]; // old hist multiindex
214 Int_t *m = new Int_t[fNdim-1]; // new hist multiindex
215 for (int i=0; i<GetNbinsX(); i++) {
216 OneToMul(i,k);
217 if (k[dim]+1<first) continue;
218 if (k[dim]+1>last) continue;
219 n = 0;
220 for (int j=0; j<fNdim; j++) if (j!=dim) m[n++] = k[j];
221 n = his->MulToOne(m);
222 his->AddBinContent(n+1,GetBinContent(i+1));
223 eis->AddBinContent(n+1,GetBinError(i+1)*GetBinError(i+1));
224 }
225
226 // combine content and errors in one histogram
227
228 for (int i=0; i<his->GetNbinsX(); i++) {
229 his->SetBinError(i+1,sqrt(eis->GetBinContent(i+1)));
230 }
231
232 his->SetLineColor(this->GetLineColor());
233 his->SetFillColor(this->GetFillColor());
234 his->SetMarkerColor(this->GetMarkerColor());
235 his->SetMarkerStyle(this->GetMarkerStyle());
236
237 // some cleanup
238
239 delete eis;
240 return his;
241}
242//=============================================================================
243TH1D *AliUnicorHN::ProjectOn(char *nam, Int_t dim, Int_t *first, Int_t *last) const
244{
245 // Project on dimension dim. Use only bins between first[i] and last[i].
246 // Use root convention: bin=1 is the first bin, bin=nbins is the last.
247 // first[i]=0 means from the first bin
248 // last[i]=0 means till the last bin
249
250 if (dim<0 || dim>fNdim-1) return 0;
251
252 // calculate the projection; lowest index 0
253
254 double *yy = new double[fNbins[dim]]; // value
255 double *ey = new double[fNbins[dim]]; // error
256 for (int i=0; i<fNbins[dim]; i++) yy[i]=0;
257 for (int i=0; i<fNbins[dim]; i++) ey[i]=0;
258 Int_t *k = new Int_t[fNdim];
259 for (int i=0; i<GetNbinsX(); i++) {
260 OneToMul(i,k);
261 int isgood = 1; // bin within the range?
262 for (int j=0; j<fNdim; j++) {
263 if (first) if (first[j]) if (k[j]+1<first[j]) {isgood = 0; break;}
264 if (last) if (last[j]) if (k[j]+1>last[j]) {isgood = 0; break;}
265 }
266 if (isgood) {
267 yy[k[dim]]+=GetBinContent(i+1);
268 ey[k[dim]]+=GetBinError(i+1)*GetBinError(i+1);
269 }
270 }
271
272 // make the projection histogram
273 // use name nam if specified; otherwise generate one
274
275 TH1D *his;
276 char *name = strlen(nam)? nam : Form("%s_proj%d",GetName(),dim);
277 if (fAxis[dim].IsVariableBinSize())
278 his = new TH1D(name,name,fNbins[dim],fAxis[dim].GetXbins()->GetArray());
279 else
280 his = new TH1D(name,name,fNbins[dim],fAxis[dim].GetXmin(),fAxis[dim].GetXmax());
281 his->SetXTitle(fAxis[dim].GetTitle());
282 // or his->GetXaxis()->ImportAttributes(ax);
283 his->Sumw2();
284 his->SetLineColor(this->GetLineColor());
285 his->SetFillColor(this->GetFillColor());
286 his->SetMarkerColor(this->GetMarkerColor());
287 his->SetMarkerStyle(this->GetMarkerStyle());
288 for (int i=0; i<his->GetNbinsX(); i++) {
289 his->SetBinContent(i+1,yy[i]);
290 his->SetBinError(i+1,sqrt(ey[i]));
291 }
292
293 // some cleanup
294
295 delete [] yy;
296 delete [] ey;
297 delete [] k;
298 // if (name!=nam) delete [] name;
299
300 return his;
301}
302//=============================================================================
303TH1D *AliUnicorHN::ProjectOn(char *nam, Int_t dim, Double_t *first, Double_t *last)
304{
305 // Project on dimension dim. Use only bins between first[i] and last[i].
306
307 if (dim<0 || dim>fNdim-1) return 0;
308 Int_t kfirst[fgkMaxNdim];
309 Int_t klast[fgkMaxNdim];
310 for (int i=0; i<fNdim; i++) {
311 kfirst[i] = fAxis[i].FindBin(first[i]);
312 klast[i] = fAxis[i].FindBin(last[i]);
313 }
314 return ProjectOn(nam,dim,kfirst,klast);
315}
316//=============================================================================
317TH2D *AliUnicorHN::ProjectOn(char *nam, Int_t dim0, Int_t dim1, Int_t *first, Int_t *last) const
318{
319 // Project on dim1 vs dim0. Use only bins between first[i] and last[i].
320 // Use root convention: bin=1 is the first bin, bin=nbins is the last.
321 // first[i]=0 means from the first bin
322 // last[i]=0 means till the last bin
323
324 if (dim0<0 || dim0>fNdim-1) return 0;
325 if (dim1<0 || dim1>fNdim-1) return 0;
326
327 // calculate the projection
328
329 double **yy = new double*[fNbins[dim0]]; // value
330 double **ey = new double*[fNbins[dim0]]; // error
331 for (int i=0; i<fNbins[dim0]; i++) yy[i] = new double[fNbins[dim1]];
332 for (int i=0; i<fNbins[dim0]; i++) ey[i] = new double[fNbins[dim1]];
333 for (int i=0; i<fNbins[dim0]; i++) for (int j=0; j<fNbins[dim1]; j++) yy[i][j]=0;
334 for (int i=0; i<fNbins[dim0]; i++) for (int j=0; j<fNbins[dim1]; j++) ey[i][j]=0;
335 Int_t *k = new Int_t[fNdim];
336 for (int i=0; i<GetNbinsX(); i++) {
337 OneToMul(i,k);
338 int isgood = 1; // bin within the range?
339 for (int j=0; j<fNdim; j++) {
340 if (first) if (first[j]) if (k[j]+1<first[j]) {isgood = 0; break;}
341 if (last) if (last[j]) if (k[j]+1>last[j]) {isgood = 0; break;}
342 }
343 if (isgood) {
344 yy[k[dim0]][k[dim1]]+=GetBinContent(i+1);
345 ey[k[dim0]][k[dim1]]+=GetBinError(i+1)*GetBinError(i+1);
346 }
347 }
348
349 // make the projection histogram
350 // use name nam if specified; otherwise generate one
351
352 TH2D *his=0;
353 char *name = strlen(nam)? nam : Form("%s_proj%dvs%d",GetName(),dim1,dim0);
354 if (fAxis[dim0].IsVariableBinSize() && fAxis[dim1].IsVariableBinSize())
355 his = new TH2D(name,name,
356 fNbins[dim0],fAxis[dim0].GetXbins()->GetArray(),
357 fNbins[dim1],fAxis[dim1].GetXbins()->GetArray());
358 else if (!fAxis[dim0].IsVariableBinSize() && fAxis[dim1].IsVariableBinSize())
359 his = new TH2D(name,name,
360 fNbins[dim0],fAxis[dim0].GetXmin(),fAxis[dim0].GetXmax(),
361 fNbins[dim1],fAxis[dim1].GetXbins()->GetArray());
362 else if (fAxis[dim0].IsVariableBinSize() && !fAxis[dim1].IsVariableBinSize())
363 his = new TH2D(name,name,
364 fNbins[dim0],fAxis[dim0].GetXbins()->GetArray(),
365 fNbins[dim1],fAxis[dim1].GetXmin(),fAxis[dim1].GetXmax());
366 else if (!fAxis[dim0].IsVariableBinSize() && !fAxis[dim1].IsVariableBinSize())
367 his = new TH2D(name,name,
368 fNbins[dim0],fAxis[dim0].GetXmin(),fAxis[dim0].GetXmax(),
369 fNbins[dim1],fAxis[dim1].GetXmin(),fAxis[dim1].GetXmax());
370 his->SetXTitle(fAxis[dim0].GetTitle());
371 his->SetYTitle(fAxis[dim1].GetTitle());
372 // or his->GetXaxis()->ImportAttributes(ax0);
373 // or his->GetYaxis()->ImportAttributes(ax1);
374 his->Sumw2();
375 his->SetLineColor(this->GetLineColor());
376 his->SetFillColor(this->GetFillColor());
377 his->SetMarkerColor(this->GetMarkerColor());
378 his->SetMarkerStyle(this->GetMarkerStyle());
379 for (int i=0; i<his->GetNbinsX(); i++)
380 for (int j=0; j<his->GetNbinsY(); j++) {
381 his->SetBinContent(i+1,j+1,yy[i][j]);
382 his->SetBinError(i+1,j+1,sqrt(ey[i][j]));
383 }
384
385 // some cleanup
386
387 for (int i=0; i<fNbins[dim0]; i++) delete [] yy[i];
388 for (int i=0; i<fNbins[dim0]; i++) delete [] ey[i];
389 delete [] yy;
390 delete [] ey;
391 delete [] k;
392 // if (name!=nam) delete [] name;
393
394 return his;
395}
396//=============================================================================