1 /*************************************************************************
2 * Copyright(c) 1998-2009, 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 **************************************************************************/
17 // Generic Histogram container with support for groups and filling of groups by passing
21 // Jens Wiechula <Jens.Wiechula@cern.ch>
28 #include <TCollection.h>
29 #include <THashList.h>
31 #include <TObjString.h>
32 #include <TObjArray.h>
41 #include <TVirtualPS.h>
42 // #include <TVectorD.h>
44 #include "AliDielectronHistos.h"
47 ClassImp(AliDielectronHistos)
50 AliDielectronHistos::AliDielectronHistos() :
52 TNamed("AliDielectronHistos","Dielectron Histogram Container"),
55 fReservedWords(new TString)
58 // Default constructor
60 fHistoList.SetOwner(kTRUE);
61 fHistoList.SetName("Dielectron_Histos");
64 //_____________________________________________________________________________
65 AliDielectronHistos::AliDielectronHistos(const char* name, const char* title) :
70 fReservedWords(new TString)
75 fHistoList.SetOwner(kTRUE);
76 fHistoList.SetName(name);
79 //_____________________________________________________________________________
80 AliDielectronHistos::~AliDielectronHistos()
86 if (fList) fList->Clear();
87 delete fReservedWords;
90 //_____________________________________________________________________________
91 void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
92 Int_t nbinsX, Double_t xmin, Double_t xmax,
93 UInt_t valTypeX, Bool_t logBinX)
96 // Default histogram creation 1D case
98 if (!IsHistogramOk(histClass,name)) return;
100 Double_t *binLimX=0x0;
103 binLimX=MakeLogBinning(nbinsX, xmin, xmax);
105 binLimX=MakeLinBinning(nbinsX, xmin, xmax);
108 TH1* hist=new TH1F(name,title,nbinsX,binLimX);
112 Bool_t isReserved=fReservedWords->Contains(histClass);
114 UserHistogramReservedWords(histClass, hist, valTypeX);
116 UserHistogram(histClass, hist, valTypeX);
119 //_____________________________________________________________________________
120 void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
121 Int_t nbinsX, Double_t xmin, Double_t xmax,
122 Int_t nbinsY, Double_t ymin, Double_t ymax,
123 UInt_t valTypeX, UInt_t valTypeY,
124 Bool_t logBinX, Bool_t logBinY)
127 // Default histogram creation 2D case
129 if (!IsHistogramOk(histClass,name)) return;
131 Double_t *binLimX=0x0;
132 Double_t *binLimY=0x0;
135 binLimX=MakeLogBinning(nbinsX, xmin, xmax);
137 binLimX=MakeLinBinning(nbinsX, xmin, xmax);
140 binLimY=MakeLogBinning(nbinsY, ymin, ymax);
142 binLimY=MakeLinBinning(nbinsY, ymin, ymax);
145 TH1* hist=new TH2F(name,title,nbinsX,binLimX,nbinsY,binLimY);
151 Bool_t isReserved=fReservedWords->Contains(histClass);
153 UserHistogramReservedWords(histClass, hist, valTypeX+100*valTypeY);
155 UserHistogram(histClass, hist, valTypeX+100*valTypeY);
159 //_____________________________________________________________________________
160 void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
161 Int_t nbinsX, Double_t xmin, Double_t xmax,
162 Int_t nbinsY, Double_t ymin, Double_t ymax,
163 Int_t nbinsZ, Double_t zmin, Double_t zmax,
164 UInt_t valTypeX, UInt_t valTypeY, UInt_t valTypeZ,
165 Bool_t logBinX, Bool_t logBinY, Bool_t logBinZ)
168 // Default histogram creation 3D case
170 if (!IsHistogramOk(histClass,name)) return;
172 Double_t *binLimX=0x0;
173 Double_t *binLimY=0x0;
174 Double_t *binLimZ=0x0;
177 binLimX=MakeLogBinning(nbinsX, xmin, xmax);
179 binLimX=MakeLinBinning(nbinsX, xmin, xmax);
183 binLimY=MakeLogBinning(nbinsY, ymin, ymax);
185 binLimY=MakeLinBinning(nbinsY, ymin, ymax);
189 binLimZ=MakeLogBinning(nbinsZ, zmin, zmax);
191 binLimZ=MakeLinBinning(nbinsZ, zmin, zmax);
194 TH1* hist=new TH3F(name,title,nbinsX,binLimX,nbinsY,binLimY,nbinsZ,binLimZ);
200 Bool_t isReserved=fReservedWords->Contains(histClass);
202 UserHistogramReservedWords(histClass, hist, valTypeX+100*valTypeY+10000*valTypeZ);
204 UserHistogram(histClass, hist, valTypeX+100*valTypeY+10000*valTypeZ);
207 //_____________________________________________________________________________
208 void AliDielectronHistos::UserHistogram(const char* histClass, TH1* hist, UInt_t valTypes)
211 // Add any type of user histogram
214 //special case for the calss Pair. where histograms will be created for all pair classes
215 Bool_t isReserved=fReservedWords->Contains(histClass);
217 UserHistogramReservedWords(histClass, hist, valTypes);
221 if (!IsHistogramOk(histClass,hist->GetName())) return;
223 THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
224 hist->SetDirectory(0);
225 hist->SetUniqueID(valTypes);
226 classTable->Add(hist);
229 //_____________________________________________________________________________
230 void AliDielectronHistos::AddClass(const char* histClass)
233 // Add a class of histograms
234 // Several classes can be added by separating them by a ';' e.g. 'class1;class2;class3'
236 TString hists(histClass);
237 TObjArray *arr=hists.Tokenize(";");
240 while ( (o=next()) ){
241 if (fHistoList.FindObject(o->GetName())){
242 Warning("AddClass","Cannot create class '%s' it already exists.",histClass);
245 if (fReservedWords->Contains(o->GetName())){
246 Error("AddClass","Pair is a reserved word, please use another name");
249 THashList *table=new THashList;
250 table->SetOwner(kTRUE);
251 table->SetName(o->GetName());
252 fHistoList.Add(table);
257 //_____________________________________________________________________________
258 void AliDielectronHistos::Fill(const char* histClass, const char* name, Double_t xval)
261 // Fill function 1D case
263 THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
265 if (!classTable || !(hist=(TH1*)classTable->FindObject(name)) ){
266 Warning("Fill","Cannot fill histogram. Either class '%s' or histogram '%s' not existing.",histClass,name);
272 //_____________________________________________________________________________
273 void AliDielectronHistos::Fill(const char* histClass, const char* name, Double_t xval, Double_t yval)
276 // Fill function 2D case
278 THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
280 if (!classTable || !(hist=(TH2*)classTable->FindObject(name)) ){
281 Warning("UserHistogram","Cannot fill histogram. Either class '%s' or histogram '%s' not existing.",histClass,name);
284 hist->Fill(xval,yval);
287 //_____________________________________________________________________________
288 void AliDielectronHistos::Fill(const char* histClass, const char* name, Double_t xval, Double_t yval, Double_t zval)
291 // Fill function 3D case
293 THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
295 if (!classTable || !(hist=(TH3*)classTable->FindObject(name)) ){
296 Warning("UserHistogram","Cannot fill histogram. Either class '%s' or histogram '%s' not existing.",histClass,name);
299 hist->Fill(xval,yval,zval);
302 //_____________________________________________________________________________
303 void AliDielectronHistos::FillClass(const char* histClass, Int_t nValues, const Double_t *values)
306 // Fill class 'histClass' (by name)
309 THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
311 Warning("FillClass","Cannot fill class '%s' its not defined.",histClass);
315 TIter nextHist(classTable);
317 while ( (hist=(TH1*)nextHist()) ){
318 UInt_t valueTypes=hist->GetUniqueID();
319 if (valueTypes==(UInt_t)kNoAutoFill) continue;
320 UInt_t value1=valueTypes%100; //last two digits
321 UInt_t value2=valueTypes/100%100; //second last two digits
322 UInt_t value3=valueTypes/10000%100; //third last two digits
323 if (value1>=(UInt_t)nValues||value2>=(UInt_t)nValues||value3>=(UInt_t)nValues) {
324 Warning("FillClass","One of the values is out of range. Not filling histogram '%s/%s'.", histClass, hist->GetName());
327 switch (hist->GetDimension()){
329 hist->Fill(values[value1]);
332 ((TH2*)hist)->Fill(values[value1],values[value2]);
335 ((TH3*)hist)->Fill(values[value1],values[value2],values[value3]);
341 //_____________________________________________________________________________
342 // void AliDielectronHistos::FillClass(const char* histClass, const TVectorD &vals)
347 // FillClass(histClass, vals.GetNrows(), vals.GetMatrixArray());
350 //_____________________________________________________________________________
351 void AliDielectronHistos::UserHistogramReservedWords(const char* histClass, TH1 *hist, UInt_t valTypes)
354 // Creation of histogram for all pair types
356 TString title(hist->GetTitle());
357 // Same Event Like Sign
358 TIter nextClass(&fHistoList);
360 while ( (l=static_cast<THashList*>(nextClass())) ){
361 TString name(l->GetName());
362 if (name.Contains(histClass)){
363 TH1 *h=static_cast<TH1*>(hist->Clone());
365 h->SetTitle(Form("%s %s",title.Data(),l->GetName()));
366 UserHistogram(l->GetName(),h,valTypes);
372 //_____________________________________________________________________________
373 void AliDielectronHistos::DumpToFile(const char* file)
376 // Dump the histogram list to a newly created root file
378 TFile f(file,"recreate");
379 fHistoList.Write(fHistoList.GetName(),TObject::kSingleKey);
383 //_____________________________________________________________________________
384 TH1* AliDielectronHistos::GetHistogram(const char* histClass, const char* name) const
387 // return histogram 'name' in 'histClass'
389 THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
390 if (!classTable) return 0x0;
391 return (TH1*)classTable->FindObject(name);
394 //_____________________________________________________________________________
395 TH1* AliDielectronHistos::GetHistogram(const char* cutClass, const char* histClass, const char* name) const
398 // return histogram from list of list of histograms
399 // this function is thought for retrieving histograms if a list of AliDielectronHistos is set
402 if (!fList) return 0x0;
403 THashList *h=dynamic_cast<THashList*>(fList->FindObject(cutClass));
405 THashList *classTable=dynamic_cast<THashList*>(h->FindObject(histClass));
406 if (!classTable) return 0x0;
407 return (TH1*)classTable->FindObject(name);
410 //_____________________________________________________________________________
411 void AliDielectronHistos::Draw(const Option_t* option)
417 TString drawStr(option);
418 TObjArray *arr=drawStr.Tokenize(";");
423 TObjString *ostr=0x0;
427 while ( (ostr=(TObjString*)nextOpt()) ){
428 currentOpt=ostr->GetString();
429 currentOpt.Remove(TString::kBoth,'\t');
430 currentOpt.Remove(TString::kBoth,' ');
433 if ( currentOpt.Contains(testOpt.Data()) ){
434 drawClasses=currentOpt(testOpt.Length(),currentOpt.Length());
441 // Bool_t same=drawOpt.Contains("same"); //FIXME not yet implemented
446 Error("Draw","When writing to a file you have to create a canvas before opening the file!!!");
454 TIter nextClass(&fHistoList);
455 THashList *classTable=0;
456 // Bool_t first=kTRUE;
457 while ( (classTable=(THashList*)nextClass()) ){
458 //test classes option
459 if (!drawClasses.IsNull() && !drawClasses.Contains(classTable->GetName())) continue;
461 Int_t nPads = classTable->GetEntries();
462 Int_t nCols = (Int_t)TMath::Ceil( TMath::Sqrt(nPads) );
463 Int_t nRows = (Int_t)TMath::Ceil( (Double_t)nPads/(Double_t)nCols );
468 canvasName.Form("c%s_%s",GetName(),classTable->GetName());
469 c=(TCanvas*)gROOT->FindObject(canvasName.Data());
470 if (!c) c=new TCanvas(canvasName.Data(),Form("%s: %s",GetName(),classTable->GetName()));
475 // if (nPads>1) gVirtualPS->NewPage();
477 if (nPads>1) c->Clear();
480 if (nCols>1||nRows>1) c->Divide(nCols,nRows);
482 //loop over histograms and draw them
483 TIter nextHist(classTable);
486 while ( (h=(TH1*)nextHist()) ){
488 if ( (h->InheritsFrom(TH2::Class())) ) drawOpt="colz";
489 if (nCols>1||nRows>1) c->cd(++iPad);
490 if ( TMath::Abs(h->GetXaxis()->GetBinWidth(1)-h->GetXaxis()->GetBinWidth(2))>1e-10 ) gPad->SetLogx();
491 if ( TMath::Abs(h->GetYaxis()->GetBinWidth(1)-h->GetYaxis()->GetBinWidth(2))>1e-10 ) gPad->SetLogy();
492 if ( TMath::Abs(h->GetZaxis()->GetBinWidth(1)-h->GetZaxis()->GetBinWidth(2))>1e-10 ) gPad->SetLogz();
493 TString histOpt=h->GetOption();
495 if (histOpt.Contains("logx")) gPad->SetLogx();
496 if (histOpt.Contains("logy")) gPad->SetLogy();
497 if (histOpt.Contains("logz")) gPad->SetLogz();
498 histOpt.ReplaceAll("logx","");
499 histOpt.ReplaceAll("logy","");
500 histOpt.ReplaceAll("logz","");
501 h->Draw(drawOpt.Data());
508 // if (gVirtualPS) delete c;
511 //_____________________________________________________________________________
512 void AliDielectronHistos::Print(const Option_t* option) const
515 // Print classes and histograms
517 TString optString(option);
519 if (optString.IsNull()) PrintStructure();
525 //_____________________________________________________________________________
526 void AliDielectronHistos::PrintStructure() const
529 // Print classes and histograms in the class to stdout
532 TIter nextClass(&fHistoList);
533 THashList *classTable=0;
534 while ( (classTable=(THashList*)nextClass()) ){
535 TIter nextHist(classTable);
537 printf("+ %s\n",classTable->GetName());
538 while ( (o=nextHist()) )
539 printf("| ->%s\n",o->GetName());
542 TIter nextCutClass(fList);
543 THashList *cutClass=0x0;
544 while ( (cutClass=(THashList*)nextCutClass()) ) {
545 printf("+ %s\n",cutClass->GetName());
546 TIter nextClass(cutClass);
547 THashList *classTable=0;
548 while ( (classTable=(THashList*)nextClass()) ){
549 TIter nextHist(classTable);
551 printf("| + %s\n",classTable->GetName());
552 while ( (o=nextHist()) )
553 printf("| | ->%s\n",o->GetName());
560 //_____________________________________________________________________________
561 void AliDielectronHistos::SetHistogramList(THashList &list, Bool_t setOwner/*=kTRUE*/)
564 // set histogram classes and histograms to this instance. It will take onwnership!
566 ResetHistogramList();
567 TString name(GetName());
568 if (name == "AliDielectronHistos") SetName(list.GetName());
571 while ( (o=next()) ){
575 list.SetOwner(kFALSE);
576 fHistoList.SetOwner(kTRUE);
580 //_____________________________________________________________________________
581 Bool_t AliDielectronHistos::SetCutClass(const char* cutClass)
584 // Assign histogram list according to cutClass
587 if (!fList) return kFALSE;
588 ResetHistogramList();
589 THashList *h=dynamic_cast<THashList*>(fList->FindObject(cutClass));
591 Warning("SetCutClass","cutClass '%s' not found", cutClass);
594 SetHistogramList(*h,kFALSE);
598 //_____________________________________________________________________________
599 Bool_t AliDielectronHistos::IsHistogramOk(const char* histClass, const char* name)
602 // check whether the histogram class exists and the histogram itself does not exist yet
604 Bool_t isReserved=fReservedWords->Contains(histClass);
605 if (!fHistoList.FindObject(histClass)&&!isReserved){
606 Warning("IsHistogramOk","Cannot create histogram. Class '%s' not defined. Please create it using AddClass before.",histClass);
609 if (GetHistogram(histClass,name)){
610 Warning("IsHistogramOk","Cannot create histogram '%s' in class '%s': It already exists!",name,histClass);
616 // //_____________________________________________________________________________
617 // TIterator* AliDielectronHistos::MakeIterator(Bool_t dir) const
622 // return new TListIter(&fHistoList, dir);
625 //_____________________________________________________________________________
626 void AliDielectronHistos::ReadFromFile(const char* file)
629 // Read histos from file
632 TIter nextKey(f.GetListOfKeys());
634 while ( (key=(TKey*)nextKey()) ){
635 TObject *o=f.Get(key->GetName());
636 THashList *list=dynamic_cast<THashList*>(o);
638 SetHistogramList(*list);
644 //_____________________________________________________________________________
645 void AliDielectronHistos::DrawSame(const char* histName, const Option_t *opt)
648 // Draw all histograms with the same name into one canvas
649 // if option contains 'leg' a legend will be created with the class name as caption
650 // if option contains 'can' a new canvas is created
653 TString optString(opt);
655 Bool_t optLeg=optString.Contains("leg");
656 Bool_t optCan=optString.Contains("can");
661 c=(TCanvas*)gROOT->FindObject(Form("c%s",histName));
662 if (!c) c=new TCanvas(Form("c%s",histName),Form("All '%s' histograms",histName));
667 if (optLeg) leg=new TLegend(.8,.3,.99,.9);
670 TIter next(&fHistoList);
671 THashList *classTable=0;
674 while ( (classTable=(THashList*)next()) ){
675 if ( TH1 *h=(TH1*)classTable->FindObject(histName) ){
677 h->SetLineColor(i+1);
678 h->SetMarkerColor(i+1);
679 h->Draw(i>0?"same":"");
680 if (leg) leg->AddEntry(h,classTable->GetName(),"lp");
682 max=TMath::Max(max,h->GetMaximum());
686 leg->SetFillColor(10);
687 leg->SetY1(.9-i*.05);
690 if (hFirst&&(hFirst->GetYaxis()->GetXmax()<max)){
691 hFirst->SetMaximum(max);
695 //_____________________________________________________________________________
696 void AliDielectronHistos::SetReservedWords(const char* words)
699 // set reserved words
702 (*fReservedWords)=words;
705 //_____________________________________________________________________________
706 Double_t* AliDielectronHistos::MakeLogBinning(Int_t nbinsX, Double_t xmin, Double_t xmax) const
709 // Make logarithmic binning
710 // the user has to delete the array afterwards!!!
714 if (xmin<1e-20 || xmax<1e-20){
715 Error("MakeLogBinning","For Log binning xmin and xmax must be > 1e-20. Using linear binning instead!");
716 return MakeLinBinning(nbinsX, xmin, xmax);
718 Double_t *binLim=new Double_t[nbinsX+1];
721 Double_t expMax=TMath::Log(last/first);
722 for (Int_t i=0; i<nbinsX+1; ++i){
723 binLim[i]=first*TMath::Exp(expMax/nbinsX*(Double_t)i);
728 //_____________________________________________________________________________
729 Double_t* AliDielectronHistos::MakeLinBinning(Int_t nbinsX, Double_t xmin, Double_t xmax) const
732 // Make logarithmic binning
733 // the user has to delete the array afterwards!!!
735 Double_t *binLim=new Double_t[nbinsX+1];
738 Double_t binWidth=(last-first)/nbinsX;
739 for (Int_t i=0; i<nbinsX+1; ++i){
740 binLim[i]=first+binWidth*(Double_t)i;