1 /*************************************************************************
2 * Copyright(c) 1998-2008, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 // -----------------------------------------------------------------------
17 // Tools for drawing/ manipulating histograms. (NEEDS CLEANUP!)
18 // -----------------------------------------------------------------------
19 // Author: Misha Veldhoen (misha.veldhoen@cern.ch)
31 #include "TObjArray.h"
35 #include "AliHistToolsDiHadronPID.h"
39 // -----------------------------------------------------------------------
40 TH1F* AliHistToolsDiHadronPID::RebinVariableBinning(
41 const TH1F* histIn, const Double_t* binsx, const Int_t Nbinsx, const Bool_t density) {
43 // Rebins a histogram (hin) with a variable binning to a histogram
44 // with another variable binning (binsx). If the "density" flag is set,
45 // then it is expected that the bins are per unit x-axis, otherwise an
46 // absolute count is assumed.
48 // TODO: determine over/under-flow bins.
50 // Gather info from the original histogram.
51 const TArrayD* binsxIn = histIn->GetXaxis()->GetXbins();
52 TArrayD* binsxOut = new TArrayD(Nbinsx + 1,binsx);
53 Int_t NbinsxIn = binsxIn->GetSize() - 1;
54 const char* nameIn = histIn->GetName();
55 const char* titleIn = histIn->GetTitle();
56 const char* xAxisTitleIn = histIn->GetXaxis()->GetTitle();
57 const char* yAxisTitleIn = histIn->GetYaxis()->GetTitle();
59 // Gather info from the output histogram and create it.
60 Int_t NbinsxOut = binsxOut->GetSize() - 1;
61 const char* nameOut = Form("%s (rebinned)",nameIn);
62 const char* titleOut = Form("%s_rebinned;%s;%s",titleIn,xAxisTitleIn,yAxisTitleIn);
63 TH1F* histOut = new TH1F(nameOut,titleOut,NbinsxOut,binsxOut->GetArray());
67 for (Int_t iBinOut = 0; iBinOut < NbinsxOut; iBinOut++) {
69 Double_t binOutLowEdge = binsxOut->At(iBinOut);
70 Double_t binOutHighEdge = binsxOut->At(iBinOut+1);
71 Double_t binOutWidth = binOutHighEdge - binOutLowEdge;
72 //Double_t binOutCenter = binOutHighEdge - binOutWidth/2.;
74 // Setting all errors of the outgoing histogram to zero (needed later):
75 histOut->SetBinError(iBinOut+1,0.);
77 for (Int_t iBinIn = 0; iBinIn < NbinsxIn; iBinIn++) {
79 Double_t binInLowEdge = binsxIn->At(iBinIn);
80 Double_t binInHighEdge = binsxIn->At(iBinIn+1);
81 Double_t binInWidth = binInHighEdge - binInLowEdge;
82 //Double_t binInCenter = binInHighEdge - binInWidth/2.;
83 Double_t binInContent = histIn->GetBinContent(iBinIn+1);
84 Double_t binInError2 = histIn->GetBinError(iBinIn+1)*histIn->GetBinError(iBinIn+1);
86 /* -- Determining what percentage of the in-bin is included
87 in the current out-bin -- */
88 Double_t PercentageIncluded = 0.;
90 // Position of the low edge of the in-bin:
93 Int_t binInLowEdgePos = 0;
94 if (binInLowEdge < binOutLowEdge) binInLowEdgePos = 1;
95 else if (binInLowEdge > binOutHighEdge) binInLowEdgePos = 3;
96 else binInLowEdgePos = 2;
98 // Same for the high edge of the in-bin:
99 Int_t binInHighEdgePos = 0;
100 if (binInHighEdge < binOutLowEdge) binInHighEdgePos = 1;
101 else if (binInHighEdge > binOutHighEdge) binInHighEdgePos = 3;
102 else binInHighEdgePos = 2;
104 // In-bin not included.
107 if ( binInLowEdgePos == 3 || binInHighEdgePos == 1 ) {
108 //cout<<"In-bin not included."<<endl;
109 PercentageIncluded = 0.;
112 // In-bin partially included (left side).
115 else if ( binInLowEdgePos == 2 && binInHighEdgePos == 3 ) {
116 //cout<<"In-bin partially included (left side)."<<endl;
117 PercentageIncluded = (binOutHighEdge - binInLowEdge)/(binInHighEdge - binInLowEdge);
120 // In-bin partially included (middle).
123 else if ( binInLowEdgePos == 1 && binInHighEdgePos == 3 ) {
124 //cout<<"In-bin partially included (middle)."<<endl;
125 PercentageIncluded = (binOutHighEdge - binOutLowEdge)/(binInHighEdge - binInLowEdge);
128 // In-bin partially included (right side).
131 else if ( binInLowEdgePos == 1 && binInHighEdgePos == 2 ) {
132 //cout<<"In-bin partially included (right side)."<<endl;
133 PercentageIncluded = (binInHighEdge - binOutLowEdge)/(binInHighEdge - binInLowEdge);
136 // In-bin completely included.
139 else if ( binInLowEdgePos == 2 && binInHighEdgePos == 2 ) {
140 //cout<<"In-bin completely included."<<endl;
141 PercentageIncluded = 1.;
145 //cout<<"Bin Out: "<<iBinOut+1<<" ("<<binOutLowEdge<<","<<binOutHighEdge<<") Bin In: "<<iBinIn+1<<" ("<<binInLowEdge<<","<<binInHighEdge<<"), content: "<<binInContent<<" +/- "<<TMath::Sqrt(binInError2)<<". Bin in Pos: "<<binInLowEdgePos<<" "<<binInHighEdgePos<<" pct: "<<PercentageIncluded<<endl;
147 //else cout<<"Something weird just happened."<<endl;
149 Double_t binOutAddedError2 = 0.;
150 binOutAddedError2 = binInError2 * PercentageIncluded * PercentageIncluded;
151 Double_t binOutAddedContent = 0.;
152 binOutAddedContent = binInContent * PercentageIncluded;
155 binOutAddedContent*=binInWidth;
158 //histOut->Fill(binOutCenter,binOutAddedContent);
159 histOut->SetBinContent(iBinOut+1,histOut->GetBinContent(iBinOut+1)+binOutAddedContent);
161 //cout<<histOut->GetBinError(iBinOut+1)<<endl;
162 //cout<<binOutAddedError2<<endl;
163 histOut->SetBinError(iBinOut+1,histOut->GetBinError(iBinOut+1)+binOutAddedError2);
164 //cout<<histOut->GetBinError(iBinOut+1)<<endl;
167 // Once a certain binOut has been filled all the way we have to scale
168 // it if the "density" flag is set.
170 histOut->SetBinContent(iBinOut + 1,histOut->GetBinContent(iBinOut+1)/binOutWidth);
171 histOut->SetBinError(iBinOut + 1,TMath::Sqrt(histOut->GetBinError(iBinOut+1)));
172 //cout<<histOut->GetBinError(iBinOut+1)<<endl;
179 // -----------------------------------------------------------------------
180 TH1F* AliHistToolsDiHadronPID::RebinVariableBinning(const TH1F* histIn, const TH1F* histAxis, const Bool_t density) {
182 // Rebins histogram histIn to the x-axis of histAxis
183 TAxis* xaxis = histAxis->GetXaxis();
184 Int_t nbinsx = xaxis->GetNbins();
185 const Double_t* binsx = (xaxis->GetXbins())->GetArray();
186 return RebinVariableBinning(histIn, const_cast<Double_t*>(binsx), nbinsx, density);
190 // -----------------------------------------------------------------------
191 TH1F* AliHistToolsDiHadronPID::TrimHisto(const TH1F* histo, const Int_t firstbin, const Int_t lastbin) {
193 const char* name = histo->GetName();
194 const char* title = histo->GetTitle();
195 if (firstbin < 0) return 0x0;
196 if (lastbin > histo->GetNbinsX()) return 0x0;
197 if (firstbin > lastbin) return 0x0;
199 Int_t Nbins = lastbin - firstbin + 1;
200 cout<<firstbin<<" "<<lastbin<<" "<<Nbins<<endl;
201 //const Int_t NbinsC = Nbins;
202 Double_t newaxis[41];
204 for (Int_t ii = firstbin; ii < lastbin+1; ii++) {
205 newaxis[ii - firstbin] = histo->GetBinLowEdge(ii);
206 //cout<<ii-firstbin<<" "<<newaxis[ii - firstbin]<<endl;
208 newaxis[Nbins] = histo->GetBinLowEdge(lastbin+1);
210 TH1F* hout = new TH1F("hout","hout",Nbins,newaxis);
211 hout->SetDirectory(0);
212 hout->SetTitle(title);
215 for (Int_t ii = 0; ii < Nbins+1; ii++) {
216 hout->SetBinContent(ii,histo->GetBinContent(firstbin+ii));
217 hout->SetBinError(ii,histo->GetBinError(firstbin+ii));
224 // -----------------------------------------------------------------------
225 void AliHistToolsDiHadronPID::ConstMinusHist(TH1F* histo, const Float_t cc) {
228 Int_t nbins = histo->GetNbinsX();
229 for (Int_t iBin = 0; iBin < (nbins + 1); iBin++) {
230 Float_t bincontent = histo->GetBinContent(iBin);
231 histo->SetBinContent(iBin,(cc - bincontent));
236 // -----------------------------------------------------------------------
237 TH3F* AliHistToolsDiHadronPID::MakeHist3D(const char* name, const char* title,
238 const Int_t nbinsX, const Double_t minX, const Double_t maxX,
239 const Int_t nbinsY, const Double_t minY, const Double_t maxY,
240 const Int_t nbinsZ, const Double_t* zaxis) {
242 const Double_t* xaxis = const_cast<Double_t*>(CreateAxis(nbinsX,minX,maxX));
243 const Double_t* yaxis = const_cast<Double_t*>(CreateAxis(nbinsY,minY,maxY));
245 TH3F* hout = new TH3F(name,title,nbinsX,xaxis,nbinsY,yaxis,nbinsZ,zaxis);
251 // -----------------------------------------------------------------------
252 TH2F* AliHistToolsDiHadronPID::Function2DToHist2D(const TF2* function, const TH2* grid) {
254 // Creates a 2D histogram of "function" using the binning of
255 // the histogram "grid".
256 // - We assume "grid" to have fixed binwidth.
257 // - Bins are only filled if they are within the domain of the function.
258 // - Histogram takes over the color of the function.
260 // Gathering info about the axes.
261 TAxis* Xaxis = grid->GetXaxis();
262 Int_t NbinsX = Xaxis->GetNbins();
263 TAxis* Yaxis = grid->GetYaxis();
264 Int_t NbinsY = Yaxis->GetNbins();
266 // Determining function range.
271 function->GetRange(Xmin, Ymin, Xmax, Ymax);
273 // Creating the histogram.
274 TH2F* hout = new TH2F(Form("%s_hist", function->GetName()),
275 Form("%s (Hist);%s;%s", function->GetTitle(), Xaxis->GetTitle(), Yaxis->GetTitle()),
276 NbinsX, Xaxis->GetBinLowEdge(1), Xaxis->GetBinUpEdge(NbinsX),
277 NbinsY, Yaxis->GetBinLowEdge(1), Yaxis->GetBinUpEdge(NbinsY));
278 hout->SetLineColor(function->GetLineColor());
279 hout->SetMarkerColor(function->GetLineColor());
280 hout->SetDirectory(0);
282 // Filling the histogram.
283 for (Int_t iBinX = 1; iBinX < (NbinsX + 1); iBinX++) {
284 for (Int_t iBinY = 1; iBinY < (NbinsY + 1); iBinY++) {
285 Double_t CoordX = Xaxis->GetBinCenter(iBinX);
286 Double_t CoordY = Yaxis->GetBinCenter(iBinY);
288 if ( (CoordX < Xmin) || (CoordX > Xmax) || (CoordY < Ymin) || (CoordY > Ymax) ) {continue;}
290 hout->SetBinContent(iBinX, iBinY, function->Eval(CoordX, CoordY));
298 // -----------------------------------------------------------------------
299 TObjArray* AliHistToolsDiHadronPID::CreateSpectraComparison(const char* name,
300 const char* title, const TH1F* h1, const TH1F* h2, const Int_t markerstyle, const Bool_t logy) {
302 // - Creates a window comparing two histograms h1, and h2.
303 // - Returns an array of pointers to the objects created
306 //Int_t optstat = gStyle->GetOptStat();
307 gStyle->SetOptStat(0);
308 //c->UseCurrentStyle();
309 //gStyle->SetOptStat(optstat);
313 Int_t spectracolor[2] = {1,2};
314 Int_t divisioncolor = 4;
316 // Cloning and configuring spectra.
317 spectra[0] = (TH1F*)h1->Clone();
318 //spectra[0]->SetDirectory(0);
319 spectra[1] = (TH1F*)h2->Clone();
320 //spactra[1]->SetDirectory(0);
321 for (Int_t iSpectra = 0; iSpectra < 2; iSpectra++) {
322 spectra[iSpectra]->Sumw2();
323 spectra[iSpectra]->SetMarkerStyle(markerstyle);
324 spectra[iSpectra]->SetLineColor(spectracolor[iSpectra]);
325 spectra[iSpectra]->SetMarkerColor(spectracolor[iSpectra]);
328 // Creating the division.
329 division = (TH1F*)spectra[0]->Clone("hDivision");
330 division->Divide(spectra[1]);
331 division->SetLineColor(divisioncolor);
332 division->SetMarkerColor(divisioncolor);
333 division->GetYaxis()->SetTitle("Ratio");
336 //TCanvas* c = new TCanvas(name,title,0,0,400,400);
337 TCanvas* c = TCanvas::MakeDefCanvas();
340 TPad* p1 = new TPad("p1","pad1",0,0.25,1,1);
341 p1->SetRightMargin(0.05);
342 p1->SetBottomMargin(0.);
343 TPad* p2 = new TPad("p2","pad2",0,0,1,0.25);
344 p2->SetTopMargin(0.);
345 p2->SetRightMargin(0.05);
346 p2->SetBottomMargin(0.3);
347 p2->SetFillStyle(4000);
351 // Determining plotting range.
352 Double_t max = TMath::Max(spectra[0]->GetMaximum(),spectra[1]->GetMaximum());
353 Double_t min = TMath::Min(spectra[0]->GetMinimum(),spectra[1]->GetMinimum());
354 Double_t range = max-min;
355 spectra[0]->SetMinimum(min-0.05*range);
356 spectra[0]->SetMaximum(max+0.05*range);
360 if (logy) {p1->SetLogy();}
361 spectra[0]->Draw("e");
362 spectra[0]->GetXaxis()->SetLabelSize(0);
363 spectra[0]->GetYaxis()->SetLabelSize(0.05);
364 spectra[0]->GetYaxis()->SetTitleSize(0.05);
365 spectra[0]->GetYaxis()->SetTitleOffset(1.1);
366 //Double_t labelsize = spectra[0]->GetYaxis()->GetLabelSize();
367 spectra[1]->Draw("same e");
369 division->SetTitle("");
370 division->GetXaxis()->SetLabelSize(0.1);
371 division->GetXaxis()->SetTitleSize(0.15);
372 division->GetXaxis()->SetTitleOffset(0.6);
373 division->GetYaxis()->SetLabelSize(0.1);
374 division->GetYaxis()->SetTitleSize(0.12);
375 division->GetYaxis()->SetTitleOffset(0.3);
378 //c->UseCurrentStyle();
380 //gStyle->SetOptStat(optstat);
382 TLegend* legend = new TLegend(0.75,0.8,0.95,0.95);
383 legend->AddEntry(spectra[0],h1->GetTitle(),"lpe");
384 legend->AddEntry(spectra[1],h2->GetTitle(),"lpe");
386 legend->Draw("same");
388 // returning the created objects.
389 TObjArray* returnobjects = new TObjArray(6);
390 returnobjects->AddLast(c);
391 returnobjects->AddLast(p1);
392 returnobjects->AddLast(p2);
393 returnobjects->AddLast(spectra[0]);
394 returnobjects->AddLast(spectra[1]);
395 returnobjects->AddLast(division);
397 return returnobjects;
401 // -----------------------------------------------------------------------
402 Double_t* AliHistToolsDiHadronPID::CreateAxis(const Int_t nbins, const Double_t min, const Double_t max) {
404 if (nbins <= 0) return 0x0;
405 if (max < min) return 0x0;
407 Double_t* axis = new Double_t[nbins + 1];
408 Double_t binsize = (max - min)/((Double_t)nbins);
409 for (Int_t iBin = 0; iBin < nbins + 1; iBin++) {
410 axis[iBin] = min + ((Double_t)iBin) * binsize;