Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:45:08

0001 // Author: Gero Flucke <mailto:flucke@mail.desy.de>
0002 //____________________________________
0003 // GFHistManager
0004 //   Author:      Gero Flucke
0005 //   Date:        Feb. 10th, 2002
0006 //   last update: $Date: 2012/03/29 07:57:38 $  
0007 //   by:          $Author: flucke $
0008 //
0009 
0010 #include <string.h>
0011 
0012 // #include <iostream>
0013 // #include <vector>
0014 // RooT header:
0015 #include <TROOT.h>
0016 #include <TError.h>
0017 #include <TH1.h>
0018 #include <TH2.h>
0019 #include <TF1.h>
0020 #include <TCanvas.h>
0021 #include <TFile.h>
0022 #include <TString.h>
0023 #include <TObjArray.h>
0024 #include <TList.h>
0025 #include <TLegend.h>
0026 #include <TLegendEntry.h>
0027 #include <TPaveStats.h>
0028 #include <TStyle.h>
0029 
0030 // my header:
0031 #include "GFHistManager.h"
0032 #include "GFUtils/GFHistArray.h"
0033 
0034 ClassImp(GFHistManager);
0035 
0036 const Int_t GFHistManager::kDefaultPadsPerCanX = 1;
0037 const Int_t GFHistManager::kDefaultPadsPerCanY = 1;
0038 const Int_t GFHistManager::kDefaultDepth = 0;
0039 TString GFHistManager::fgLegendEntryOption = "l";
0040 
0041 
0042 GFHistManager::GFHistManager()
0043 {
0044   this->Initialise();
0045   fBatch = kFALSE;
0046   fDrawDiffStyle = kTRUE;
0047   fSameWithStats = kFALSE;
0048   fLegendY1 = 0.75;
0049   fLegendX1 = 0.7;
0050   fLegendY2 = 0.99;
0051   fLegendX2 = 0.99;
0052   fStatsX1 = 0.72, fStatsX2 = 0.995, fStatsY1 = .8, fStatsY2 = .995;
0053   fCanvasName = "canvas";
0054   fCanvasWidth = 600;
0055   fCanvasHeight = 600;
0056 }
0057 
0058 GFHistManager::GFHistManager(TH1* hist)
0059 {
0060   // constructing with hist as first histogram 
0061   this->Initialise();
0062   
0063   this->AddHist(hist);
0064   fBatch = kFALSE;
0065   fDrawDiffStyle = kTRUE;
0066   fSameWithStats = kFALSE;
0067   fLegendY1 = 0.75;
0068   fLegendX1 = 0.7;
0069   fLegendY2 = 0.99;
0070   fLegendX2 = 0.99;
0071   fStatsX1 = 0.72, fStatsX2 = 0.995, fStatsY1 = .8, fStatsY2 = .995;
0072   fCanvasName = "canvas";
0073   fCanvasWidth = 600;
0074   fCanvasHeight = 600;
0075 }
0076 
0077 GFHistManager::GFHistManager(TCollection* hists)
0078 {
0079   // constructing with histos in 'hists' as first histogram 
0080   this->Initialise();
0081 
0082   this->AddHists(hists);
0083   fBatch = kFALSE;
0084   fDrawDiffStyle = kTRUE;
0085   fSameWithStats = kFALSE;
0086   fLegendY1 = 0.75;
0087   fLegendX1 = 0.7;
0088   fLegendY2 = 0.99;
0089   fLegendX2 = 0.99;
0090   fStatsX1 = 0.72, fStatsX2 = 0.995, fStatsY1 = .8, fStatsY2 = .995;
0091   fCanvasName = "canvas";
0092   fCanvasWidth = 600;
0093   fCanvasHeight = 600;
0094 }
0095 
0096 //________________________________________________________
0097 void GFHistManager::Initialise()
0098 {
0099   fDepth = kDefaultDepth;
0100   fNoX.Set(fDepth);
0101   fNoY.Set(fDepth);
0102 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,10,2) && ROOT_VERSION_CODE <= ROOT_VERSION(4,0,3)
0103   // TArrayI::Reset(Int_t) buggy in 3.10_02:
0104   for(Int_t i = 0; i < fNoX.GetSize(); ++i) fNoX[i] = kDefaultPadsPerCanX;
0105   for(Int_t i = 0; i < fNoY.GetSize(); ++i) fNoY[i] = kDefaultPadsPerCanY;
0106 #else
0107   fNoX.Reset(kDefaultPadsPerCanX);
0108   fNoY.Reset(kDefaultPadsPerCanY);
0109 #endif  
0110   fLogY.Set(fDepth);
0111   fLogY.Reset(); // set to 0
0112 
0113 //   fCanvasWidth = 700;
0114 //   fCanvasHeight = 500;
0115 //   fCanvasWidth = 600;
0116 //   fCanvasHeight = 600;
0117 
0118   fHistArrays = new TObjArray;
0119   for(Int_t i = 0; i < fDepth; ++i){
0120     fHistArrays->Add(new TObjArray);
0121   }
0122   fCanArrays = new TObjArray;
0123   fLegendArrays = NULL;
0124   fObjLists = NULL;
0125 }
0126 
0127 //________________________________________________________
0128 GFHistManager::~GFHistManager()
0129 {
0130   // destructor: delete stored arrays, legends and canvases, but not the hists and objects!
0131   if(fHistArrays) {
0132     TIter iter(fHistArrays);
0133     while(TObjArray* array = static_cast<TObjArray*>(iter.Next())){
0134       array->Delete();
0135     }
0136     fHistArrays->Delete();
0137     delete fHistArrays;
0138   }
0139   if(fLegendArrays) {
0140     TIter legIter(fLegendArrays);
0141     while(TObjArray* array = static_cast<TObjArray*>(legIter.Next())){
0142       array->Delete();
0143     }
0144     fLegendArrays->Delete();
0145     delete fLegendArrays;
0146   }
0147 
0148   if(fObjLists) { 
0149     TIter listArrayIter(fObjLists);
0150     while(TObjArray* listArray = static_cast<TObjArray*>(listArrayIter.Next())){
0151       listArray->Delete();; // delete lists, but not its objects
0152     }
0153     fObjLists->Delete(); // delete arrays of lists
0154     delete fObjLists;// delete array of arrays of lists
0155   }
0156 
0157   if(fCanArrays) {
0158     TIter canIter(fCanArrays);
0159     while(TObjArray* array = static_cast<TObjArray*>(canIter.Next())){
0160       array->Delete();
0161     }
0162     fCanArrays->Delete();
0163     delete fCanArrays;
0164   }
0165 }
0166 
0167 //________________________________________________________
0168 void GFHistManager::Clear(Bool_t deleteHists)
0169 {
0170   // delete all canvases and clear the lists of hists stored in the manager 
0171   // (hists and objects are deleted if deleteHists is true [by default it is false])
0172 
0173   TIter iterCanArrays(fCanArrays);
0174   while(TObjArray* arr = static_cast<TObjArray*>(iterCanArrays.Next())){
0175     // A simple 'arr->Delete();' causes a crash if the user has closed a canvas
0176     // via the GUI - so delete only those that are known to gROOT:
0177     TIter cans(arr);
0178     while (TObject *c = cans.Next()) delete gROOT->GetListOfCanvases()->FindObject(c);
0179   }
0180   fCanArrays->Delete(); // delete arrays of canvases
0181   delete fCanArrays;
0182 
0183   if(fLegendArrays){ // by default there are no legends...
0184     TIter iterLegArrays(fLegendArrays);
0185     while(TObjArray* arr = static_cast<TObjArray*>(iterLegArrays.Next())){
0186       arr->Delete(); // delete legends
0187     }
0188     fLegendArrays->Delete(); // delete arrays of legends
0189     delete fLegendArrays;
0190   }
0191 
0192   if(fObjLists) { 
0193     TIter listArrayIter(fObjLists);
0194     while(TObjArray* listArray = static_cast<TObjArray*>(listArrayIter.Next())){
0195       if(deleteHists) {
0196     TIter listIter(listArray);
0197     while(TList* list = static_cast<TList*>(listIter.Next())){
0198       list->Delete(); // delete objects if requested
0199     }
0200       }
0201       listArray->Delete(); // delete lists
0202     }
0203     fObjLists->Delete(); // delete arrays of lists
0204     delete fObjLists; // delete array of arrays of lists
0205   }
0206 
0207   TIter iterHistArrays(fHistArrays);
0208   while(TObjArray* arr = static_cast<TObjArray*>(iterHistArrays.Next())){
0209     TIter iterHistArrays2(arr);
0210     while(TObjArray* arr2 = static_cast<TObjArray*>(iterHistArrays2.Next())){
0211       if(deleteHists) arr2->Delete(); // delete histograms
0212       else            arr2->Clear();
0213     }
0214     arr->Delete();
0215   }
0216   fHistArrays->Delete(); // delete arrays of arrays of histograms
0217   delete fHistArrays;
0218 
0219   this->Initialise(); // here the arrays are rebuild and fDepth etc. adjusted
0220 }
0221 
0222 //________________________________________________________
0223 void GFHistManager::Draw(Option_t *)
0224 {
0225   // draw all layers of histograms (ignore if in batch mode)
0226   if(fBatch) return; // for speed up...
0227   for(Int_t i = 0; i < fDepth; ++i){
0228     this->Draw(i);
0229   }
0230 }
0231 
0232 //________________________________________________________
0233 void GFHistManager::Draw(Int_t layer)
0234 {
0235   if(fBatch) return;
0236   this->DrawReally(layer);
0237 }
0238 
0239 
0240 //________________________________________________________
0241 void GFHistManager::DrawReally(Int_t layer)
0242 {
0243   if(layer < 0 || layer > fDepth-1) {
0244     this->Warning("DrawReally","Layer %d does not exist, possible are 0 to %d.", 
0245           layer, fDepth-1);
0246     return;
0247   }
0248 
0249   this->MakeCanvases(layer);
0250 
0251   TIter canIter(static_cast<TObjArray*>(fCanArrays->At(layer)));
0252   TIter histIter(static_cast<TObjArray*>(fHistArrays->At(layer)));
0253 
0254   Int_t histNo = 0; // becomes number of histograms in layer
0255   while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
0256     Int_t nPads = this->NumberOfSubPadsOf(can);
0257     if (fNoX[layer] * fNoY[layer] != nPads && 
0258     !(nPads == 0 && fNoX[layer] * fNoY[layer] == 1)) {
0259       this->Warning("DrawReally", "inconsistent number of pads %d, expect %d*%d",
0260             nPads, fNoX[layer], fNoY[layer]);
0261     }
0262     for(Int_t i = 0; i <= nPads; ++i){
0263       if (i == 0 && nPads != 0) i = 1;
0264       can->cd(i);
0265       if(GFHistArray* histsOfPad = static_cast<GFHistArray*>(histIter.Next())){
0266     TIter hists(histsOfPad);
0267     TH1* firstHist = static_cast<TH1*>(hists.Next());
0268     firstHist->Draw();
0269     this->DrawFuncs(firstHist);
0270     while(TH1* h = static_cast<TH1*>(hists.Next())){
0271       h->Draw(Form("SAME%s%s", (fSameWithStats ? "S" : ""), h->GetOption()));
0272       this->DrawFuncs(h);
0273     }
0274     if(histsOfPad->GetEntriesFast() > 1){
0275       const Double_t max = this->MaxOfHists(histsOfPad);
0276       if(//firstHist->GetMaximumStored() != -1111. &&  ????
0277          //max > firstHist->GetMaximumStored()){
0278          max > firstHist->GetMaximum()){
0279         firstHist->SetMaximum((fLogY[layer] ? 1.1 : 1.05) * max);
0280       }
0281       const Double_t min = this->MinOfHists(histsOfPad);
0282       if (min < 0.) {
0283         firstHist->SetMinimum(min * 1.05);
0284       } else if (gStyle->GetHistMinimumZero()) {
0285         // nothing to do
0286       } else if (min != 0. || !fLogY[layer]) {
0287         // Do not set to zero: log scale issue!
0288         firstHist->SetMinimum(min * 0.95);
0289       }
0290     }
0291     if(fLogY[layer] 
0292        && (firstHist->GetMinimum() > 0. 
0293           || (firstHist->GetMinimum() == 0. 
0294           && firstHist->GetMinimumStored() == -1111.)))gPad->SetLogy();
0295     // draw other objects:
0296     this->DrawObjects(layer, histNo);
0297     // make hist style differ
0298     if(fDrawDiffStyle) GFHistManager::MakeDifferentStyle(histsOfPad);
0299     // draw legends on top of all
0300     if(fLegendArrays && layer <= fLegendArrays->GetLast() && fLegendArrays->At(layer)){
0301       this->DrawLegend(layer, histNo);
0302     }
0303     gPad->Modified();
0304     this->ColourFuncs(histsOfPad);
0305     if (fSameWithStats) {
0306       gPad->Update(); // not nice to need this here, makes use over network impossible...
0307       this->ColourStatsBoxes(histsOfPad);
0308     }
0309     histNo++;
0310       }
0311     } // loop over pads
0312     const TString name = can->GetTitle();
0313     can->SaveAs(name+".pdf");
0314   } // loop over canvases
0315 }
0316 
0317 //________________________________________________________
0318 void GFHistManager::DrawLegend(Int_t layer, Int_t histNo)
0319 {
0320   // histNo starting at '0'
0321   // We must already be in the correct pad, layer and histNo must exist
0322 
0323   if(fLegendArrays && layer <= fLegendArrays->GetLast() && fLegendArrays->At(layer)){
0324     TObjArray* legends = static_cast<TObjArray*>(fLegendArrays->At(layer));
0325     TObject* legend = (histNo <= legends->GetLast() ? legends->At(histNo) : NULL);
0326     if(legend) legend->Draw();
0327   }
0328 }
0329 
0330 //________________________________________________________
0331 void GFHistManager::DrawObjects(Int_t layer, Int_t histNo)
0332 {
0333   // histNo starting at '0'
0334   // We must already be in the correct pad, layer and histNo must exist
0335   if(fObjLists && layer <= fObjLists->GetLast() && fObjLists->At(layer)){
0336     TObjArray* layerLists = static_cast<TObjArray*>(fObjLists->At(layer));
0337     if(histNo <= layerLists->GetLast() && layerLists->At(histNo)){
0338       TObjLink *lnk = static_cast<TList*>(layerLists->At(histNo))->FirstLink();
0339       while (lnk) {
0340     lnk->GetObject()->Draw(lnk->GetOption());
0341     lnk = lnk->Next();
0342       }
0343     }
0344   }
0345 }
0346 
0347 //________________________________________________________
0348 void GFHistManager::Print(const char* filename, Bool_t add)
0349 {
0350   // print all layers of histograms to ps-file 'filename'
0351   // if 'add == true' puts '(' or ')' only if 'filename' ends with it, 
0352   // e.g. if i is loop variable 
0353   //   GFHistManager *man = ...;
0354   //   TString name("XXX.ps");
0355   //   if(i == 0) man->Print(name + '(');
0356   //   else if(i == last) man->Print(name + ')');
0357   //   else man->Print(name, kTRUE);
0358 
0359 
0360   const Bool_t rootIsBatch = gROOT->IsBatch();
0361   if(fBatch){
0362     gROOT->SetBatch();
0363     for(Int_t i = 0; i < fDepth; ++i){
0364       this->DrawReally(i);
0365     }
0366   }
0367   gROOT->SetBatch(rootIsBatch);
0368 
0369   TObjArray cans;
0370   TIter canArrayIter(fCanArrays);
0371   while(TObjArray* canArray = static_cast<TObjArray*>(canArrayIter.Next())){
0372     cans.AddAll(canArray);
0373   }
0374 
0375   const Int_t nCans = cans.GetEntriesFast();
0376   if(nCans == 1) {
0377     cans.At(0)->Print(filename);
0378     return;
0379   }
0380 
0381   TString plainName(filename);
0382   const Bool_t starting = plainName.EndsWith("(");
0383   if(starting) {
0384     const Ssiz_t ind = plainName.Last('(');
0385     plainName.Remove(ind);
0386     //    plainName.ReplaceAll("(", "");
0387   }
0388   const Bool_t ending = plainName.EndsWith(")");
0389   if(ending) {
0390     const Ssiz_t ind = plainName.Last(')');
0391     plainName.Remove(ind);
0392 //     plainName.ReplaceAll(")", "");
0393   }
0394 
0395   for(Int_t i = 0; i < nCans; ++i){
0396     if(i == 0 && !ending && (!add || starting)) {
0397       cans.At(i)->Print(plainName + "(");
0398     } else if(i == nCans - 1 && !starting && (!add || ending)) {
0399       cans.At(i)->Print(plainName + ")");
0400     } else {
0401       cans.At(i)->Print(plainName);
0402     }
0403   }
0404 }
0405 
0406 // //________________________________________________________
0407 // void GFHistManager::Print(const char* filename, Int_t layer)
0408 // {
0409 //   // print all canvases of layer into .ps-files with name of their first histogram
0410 //   Bool_t rootIsBatch = gROOT->IsBatch();
0411 //   gROOT->SetBatch();
0412 //   this->DrawReally(layer);
0413 
0414 //   TIter canIter(static_cast<TObjArray*>(fCanArrays->At(layer)));
0415 //   Int_t nCan = 0;
0416 //   while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
0417 //     TObjArray* histLayer = static_cast<TObjArray*>(fHistArrays->At(layer));
0418 //     TObjArray* firstHistInCan =
0419 //       static_cast<TObjArray*>(histLayer->At(nCan*fNoX[layer]*fNoY[layer]));
0420 //     ++nCan;
0421 //     if(firstHistInCan){
0422 //       TString psFile("/tmp/");
0423 //       psFile+=firstHistInCan->First()->GetName();
0424 //       can->Print(psFile+=".ps");
0425 //     }
0426 //   } // loop over canvases
0427 //   gROOT->SetBatch(rootIsBatch);
0428 // }
0429 
0430 
0431 //________________________________________________________
0432 void GFHistManager::Update()
0433 {
0434   // call Update() to all canvases
0435   for(Int_t i = 0; i < fDepth; ++i){
0436     this->Update(i);
0437   }
0438 }
0439 
0440 //________________________________________________________
0441 void GFHistManager::Update(Int_t layer)
0442 {
0443   if(!this->CheckDepth("Update", layer, kFALSE)) {
0444     return;
0445   }
0446 
0447   // First loop on canvases:
0448   // If meanwhile the setting of fNoX/fNoY has changed, we are better with
0449   // drawing from scratch:
0450   Bool_t drawFromScratch = kFALSE;
0451   TIter canIter(static_cast<TObjArray*>(fCanArrays->At(layer)));
0452   while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
0453     const Int_t nPads = this->NumberOfSubPadsOf(can);
0454     if (fNoX[layer] * fNoY[layer] != nPads && // does not fit...
0455     !(nPads == 0 && fNoX[layer] * fNoY[layer] == 1)) {// ...nor single hist canvas
0456       drawFromScratch = kTRUE;
0457       break;
0458     }
0459   }
0460   if (drawFromScratch) {
0461     this->Draw(layer);
0462     return; // nothing else to be done...
0463   }
0464 
0465   // Now second loop doing the real Update work:
0466   canIter = static_cast<TObjArray*>(fCanArrays->At(layer));
0467   Int_t numPreviousCansHists = 0;
0468   const Int_t numHistsLayer = this->GetNumHistsOf(layer);
0469   while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
0470     const Int_t nPads = this->NumberOfSubPadsOf(can); // get numbers of first loop?
0471     for(Int_t i = 0; i <= nPads; ++i){
0472       if (i == 0 && nPads != 0) i = 1;// i==0: single hist canvas, else step into pad
0473       can->cd(i);
0474 
0475       const Int_t histNo = TMath::Max(0, numPreviousCansHists + i - 1);// for nPad == 0
0476       if (histNo >= numHistsLayer) continue;
0477       // draw other objects
0478       this->DrawObjects(layer, histNo);
0479       // draw legends on top of all
0480       if(fLegendArrays && fLegendArrays->GetSize() > layer && fLegendArrays->At(layer)){
0481     this->DrawLegend(layer, histNo);
0482       }
0483 
0484       if(fLogY[layer]) {
0485     GFHistArray *histsOfPad = this->GetHistsOf(layer, histNo);
0486     TH1 *h1 = histsOfPad->First();
0487     if (h1->GetMinimumStored() == 0. && histsOfPad->GetEntriesFast() > 1
0488         && this->MinOfHists(histsOfPad) == 0.) {
0489       // trouble with log scale, but assume that 0. set in DrawReally(..)!
0490       h1->SetMinimum(-1111.);
0491     }
0492     if ((h1->GetMinimum() > 0. 
0493          || (h1->GetMinimum() == 0. && h1->GetMinimumStored() == -1111.))) {
0494       gPad->SetLogy();
0495     } else {
0496       gPad->SetLogy(kFALSE);
0497     }
0498       } else {
0499     gPad->SetLogy(kFALSE);
0500       }
0501       gPad->Modified();
0502 //       gPad->Update();
0503 //       gPad->Modified();
0504 //       gPad->Update();
0505     }
0506 //     can->Update();
0507     can->Modified();
0508     can->Update();
0509 //     can->Modified();
0510     numPreviousCansHists += nPads;
0511   } // loop over canvases
0512 }
0513 
0514 
0515 //_____________________________________________________
0516 TLegendEntry* GFHistManager::AddHist(TH1* hist, Int_t layer, const char* legendTitle,
0517                      const char* legOpt)
0518 {
0519   // add hist to 'layer'th list  of histos (expands, if layer does not already exist!)
0520   if(!hist){
0521     this->Warning("AddHist", "adding NULL pointer will be ignored!");
0522     return NULL;
0523   }
0524 
0525   if(!this->CheckDepth("AddHist", layer)) return NULL;
0526   GFHistArray* newHist = new GFHistArray;
0527   newHist->Add(hist);
0528   TObjArray* layerHistArrays = static_cast<TObjArray*>(fHistArrays->At(layer));
0529   layerHistArrays->Add(newHist);
0530   if(legendTitle){
0531     TObjArray* legends = this->MakeLegends(layer);
0532     TLegend* legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
0533 #if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
0534     if (TString(gStyle->GetName()) == "Plain") legend->SetBorderSize(1);
0535 #endif
0536     legend->SetTextFont(42);
0537     legend->SetFillColor(kWhite);
0538     legends->AddAtAndExpand(legend, layerHistArrays->IndexOf(newHist));
0539     return legend->AddEntry(hist, legendTitle, legOpt ? legOpt : fgLegendEntryOption.Data());
0540   }
0541   return NULL;
0542 }
0543 
0544 //_____________________________________________________
0545 void GFHistManager::AddHists(TCollection* hists, Int_t layer, const char* legendTitle,
0546                  const char* legOpt)
0547 {
0548   // add contents of 'hists' to 'layer'th list of histos (should be histograms!!!)
0549   TIter iter(hists);
0550   while(TObject* hist = iter.Next()){
0551     if(!hist->InheritsFrom(TH1::Class())){
0552       this->Warning("AddHists", "Trying to add a non-histogram object, ignore!");
0553     } else this->AddHist(static_cast<TH1*>(hist), layer, legendTitle, legOpt);
0554   }
0555 }
0556 
0557 //_____________________________________________________
0558 TLegendEntry* GFHistManager::AddHistSame(TH1* hist, Int_t layer, Int_t histNum,
0559                      const char* legendTitle, const char* legOpt)
0560 {
0561   // adds hist to layer to draw it in the same pad as histNum's histo of that layer 
0562   if(!hist){
0563     this->Warning("AddHistSame", "adding NULL pointer will be ignored!");
0564     return NULL;
0565   }
0566   if (histNum > 0 && this->CheckDepth("AddHistSame", layer, kTRUE) //maybe added layer?
0567       && !this->GetHistsOf(layer, histNum-1)) {
0568     this->Error("AddHistSame", "usage as AddHist only for next free histNum, not %d", histNum);
0569     return NULL;
0570   }
0571   GFHistArray *histsArray = this->GetHistsOf(layer, histNum, kTRUE);// expand!
0572   TLegendEntry* result = NULL;
0573   if(histsArray) {
0574     histsArray->Add(hist); 
0575     if(legendTitle && strlen(legendTitle)){
0576       TObjArray* legends = this->MakeLegends(layer);
0577       TLegend* legend = NULL;
0578       if(legends->GetLast() >= histNum
0579      && legends->At(histNum)){
0580     legend = static_cast<TLegend*>(legends->At(histNum));
0581       } else {
0582     legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
0583 #if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
0584     if (TString(gStyle->GetName()) == "Plain") legend->SetBorderSize(1);
0585 #endif
0586     legends->AddAtAndExpand(legend, histNum);
0587     legend->SetFillColor(kWhite);
0588       }
0589       result = legend->AddEntry(hist,legendTitle, legOpt ? legOpt : fgLegendEntryOption.Data());
0590     }
0591   }
0592   return result;
0593 }
0594 
0595 //_____________________________________________________
0596 void GFHistManager::AddHistsSame(GFHistArray* hists, Int_t layer,
0597                  const char* legendTitle, const char* legOpt)
0598 {
0599   // adds hists to layer
0600   // each hist is AddHistSame(hist, layer, pad = 0...n)
0601   if(!hists){
0602     this->Warning("AddHistsSame", "adding NULL pointer will be ignored!");
0603     return;
0604   }
0605   for(Int_t i = 0; i < hists->GetEntriesFast(); ++i){
0606     this->AddHistSame(hists->At(i), layer, i, legendTitle, legOpt);
0607   }
0608 }
0609 
0610 //_____________________________________________________
0611 void GFHistManager::AddHistsSame(GFHistArray* hists, Int_t layer, Int_t histNum)
0612 {
0613   // adds hists to layer to draw it in the same pad as histNum's histo of that layer
0614   if(!hists){
0615     this->Warning("AddHistsSame", "adding NULL pointer will be ignored!");
0616     return;
0617   }
0618   GFHistArray* histsArray = this->GetHistsOf(layer, histNum, kTRUE);
0619   if(histsArray) histsArray->AddAll(hists);
0620 }
0621 
0622 //_____________________________________________________
0623 void GFHistManager::AddLayers(GFHistManager* other)
0624 {
0625   // append the layers from other to this, hists are not cloned, but legends?
0626   if(!other) return;
0627   const Int_t oldDepth = fDepth;
0628   for(Int_t iLayer = 0; iLayer < other->GetNumLayers(); ++iLayer){
0629     for(Int_t iPad = 0; iPad < other->GetNumHistsOf(iLayer); ++iPad){
0630       GFHistArray* hists = other->GetHistsOf(iLayer, iPad);
0631       this->AddHistsSame(hists, oldDepth + iLayer, iPad);
0632       TLegend* leg = other->GetLegendOf(iLayer, iPad);
0633       if(leg) this->AddLegend(static_cast<TLegend*>(leg->Clone()), iLayer, iPad);
0634     }
0635   }
0636 }
0637 
0638 //_____________________________________________________
0639 void GFHistManager::AddLayer(GFHistManager* other, Int_t layer)
0640 {
0641   // append the layer 'layer' from other to this, hists are not cloned, but legends?
0642   if(!other || layer >= other->GetNumLayers()) return;
0643 
0644   const Int_t newLayer = fDepth;
0645   for(Int_t iPad = 0; iPad < other->GetNumHistsOf(layer); ++iPad){
0646     GFHistArray* hists = other->GetHistsOf(layer, iPad);
0647     this->AddHist(hists->At(0), newLayer);
0648     for(Int_t iHist = 1; iHist < hists->GetEntriesFast(); ++iHist){
0649       this->AddHistSame(hists->At(iHist), newLayer, iPad);
0650     }
0651     TLegend* leg = other->GetLegendOf(layer, iPad);
0652     if(leg) this->AddLegend(static_cast<TLegend*>(leg->Clone()), newLayer, iPad);
0653   }
0654 }
0655 
0656 //_____________________________________________________
0657 void GFHistManager::Overlay(GFHistManager* other, Int_t otherLayer, Int_t myLayer,
0658                 const char* legendTitle)
0659 {
0660   if (!other || otherLayer >= other->GetNumLayers()
0661       || myLayer >= other->GetNumLayers()
0662       || other->GetNumHistsOf(otherLayer) != this->GetNumHistsOf(myLayer)) return;
0663 
0664   const Int_t histNo = 0;
0665   for (Int_t iPad = 0; iPad < other->GetNumHistsOf(otherLayer); ++iPad) {
0666     GFHistArray* hists = other->GetHistsOf(otherLayer, iPad);
0667     this->AddHistSame(hists->At(histNo), myLayer, iPad, legendTitle);//, legOpt)
0668   }
0669 }
0670 
0671 //_____________________________________________________
0672 TLegend* GFHistManager::AddLegend(Int_t layer, Int_t histoNum, 
0673                   const char* header, Bool_t referAll)
0674 {
0675   // adds a legend referencing all hists in same pad 'histoNum' of layer
0676   // 
0677 
0678   // FIXME: use help of other AddLegend method?
0679   if(!this->CheckHistNum("AddLegend", layer, histoNum)) return NULL;
0680 
0681   TObjArray* legendsOfLayer = this->MakeLegends(layer);
0682   TLegend* legend = (legendsOfLayer->GetSize() <= histoNum ? 
0683              NULL : static_cast<TLegend*>(legendsOfLayer->At(histoNum)));
0684   if(!legend) {
0685     legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
0686 #if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
0687     if (TString(gStyle->GetName()) == "Plain") legend->SetBorderSize(1);
0688 #endif
0689     legend->SetFillColor(kWhite);
0690     legendsOfLayer->AddAtAndExpand(legend, histoNum);
0691   }
0692 
0693   if(header) legend->SetHeader(header);
0694   GFHistArray* hists = this->GetHistsOf(layer, histoNum);
0695   TList* legendEntries = legend->GetListOfPrimitives();
0696 
0697   if(referAll){
0698     TIter histsIter(hists);
0699     while(TObject* hist = histsIter.Next()){
0700       Bool_t addNew = kTRUE;
0701       TIter legEntrIter(legendEntries);
0702       while(TLegendEntry* entry = static_cast<TLegendEntry*>(legEntrIter())){
0703     if(hist == entry->GetObject()) {addNew = kFALSE; break;}
0704       }  
0705       if(addNew) legend->AddEntry(hist, hist->GetName(), fgLegendEntryOption);
0706     }
0707   }
0708 
0709   if(layer < fCanArrays->GetEntriesFast()) {
0710     this->Update(layer); // if canvas already drawn
0711   }
0712   return legend;
0713 }
0714 
0715 //_____________________________________________________
0716 Bool_t GFHistManager::RemoveLegend(Int_t layer, Int_t nPad)
0717 {
0718   // true if there was a legend
0719   if(!this->CheckHistNum("RemoveLegend", layer, nPad)) return kFALSE;
0720 
0721   TLegend* leg = this->GetLegendOf(layer, nPad);
0722   if(!leg) return kFALSE;
0723 
0724   TObjArray* legendsOfLayer = this->MakeLegends(layer);
0725   if(!legendsOfLayer->Remove(leg)) {
0726     this->Error("RemoveLegend", "inconsistent state for layer %d, nPad %d", layer, nPad);
0727     return kFALSE;
0728   }
0729   delete leg;
0730 
0731   if(layer < fCanArrays->GetEntriesFast()) {
0732     this->Update(layer); // if canvas already drawn
0733   }
0734 
0735   return kTRUE;
0736 }
0737 
0738 //_____________________________________________________
0739 void GFHistManager::AddLegend(TLegend* leg, Int_t layer, Int_t histoNum)
0740 {
0741   // hist and layer must already exist
0742   if(!this->CheckHistNum("AddLegend", layer, histoNum)) return;
0743 
0744   TObjArray* legendsOfLayer = this->MakeLegends(layer);
0745   TLegend* legend = (legendsOfLayer->GetSize() < histoNum ? 
0746              NULL : static_cast<TLegend*>(legendsOfLayer->At(histoNum)));
0747   if(legend) {
0748     this->Error("AddLegend", "legend exists, replacing it");
0749     delete legend;
0750   }
0751   legend = leg;
0752   legendsOfLayer->AddAtAndExpand(legend, histoNum);
0753 
0754   if(layer < fCanArrays->GetEntriesFast()) {
0755     this->Update(layer); // if canvas already drawn
0756   }
0757 }
0758 
0759 
0760 //_____________________________________________________
0761 void GFHistManager::AddObject(TObject* obj, Int_t layer, Int_t histoNum, Option_t* opt)
0762 {
0763   // Hist and layer must already exist.
0764   // If the given pad is already drawn, it will get updated to display the object.
0765   // If you add many objects, this can become pretty slow, so it is recommended
0766   // to first work in batch mode (SetBatch()), add all hists and objects and then
0767   // go back and draw: SetBatch(false); Draw();// or Draw(layer)
0768   if(!this->CheckHistNum("AddObject", layer, histoNum)) return;
0769 
0770   TList* objList = this->MakeObjList(layer, histoNum);
0771   objList->Add(obj, opt);
0772 
0773   if(layer < fCanArrays->GetEntriesFast()) {
0774     // Would be nice to update only for histoNum to speed up...
0775     this->Update(layer); // if canvas already drawn
0776   }
0777 }
0778 
0779 
0780 //_____________________________________________________
0781 void GFHistManager::WriteCanvases(TFile* file)
0782 {
0783   // write canvases with their content to file  (overwrite)
0784   if(!file) {
0785     this->Warning("WriteCanvases", "no file given, ignore!");
0786     return;
0787   }
0788 
0789   TDirectory* saveDir = gDirectory;
0790   file->cd();
0791   for(Int_t i = 0; i < fDepth; ++i){
0792     TIter canvases(static_cast<TObjArray*>(fCanArrays->At(i)));
0793     while(TCanvas* can = static_cast<TCanvas*>(canvases.Next())){
0794       can->Write(0, kOverwrite);
0795     }
0796   }
0797   saveDir->cd();
0798 }
0799 
0800 //_____________________________________________________
0801 void GFHistManager::WriteHistos(TFile* file)
0802 {
0803   // write histos to file (overwrite)
0804 
0805   if(!file) {
0806     this->Warning("WriteHistos", "no file given, ignore!");
0807     return;
0808   }
0809 
0810   TDirectory* saveDir = gDirectory;
0811   file->cd();
0812   for(Int_t i = 0; i < fDepth; ++i){
0813     TIter iterHistsArr(static_cast<TObjArray*>(fHistArrays->At(i)));
0814     while(TObjArray* arr2 = static_cast<TObjArray*>(iterHistsArr.Next())){
0815       TIter iterHistArr2(arr2);
0816       while(TObject* hist = iterHistArr2.Next()){
0817     hist->Write(0, kOverwrite);
0818       }
0819     }
0820   }
0821   saveDir->cd();
0822 }
0823 
0824 //_____________________________________________________
0825 void GFHistManager::MakeCanvases(Int_t layer)
0826 {
0827   // no check done whether layer is consistent with depth...
0828 
0829   Int_t nHists = static_cast<TObjArray*>(fHistArrays->At(layer))->GetEntriesFast();
0830   Int_t nCanvases = nHists / (fNoX[layer] * fNoY[layer]);
0831   if(nHists > nCanvases * fNoX[layer] * fNoY[layer]){
0832     ++nCanvases;
0833   }
0834 
0835   Bool_t oneCanvas = kFALSE;
0836   while(nHists < fNoX[layer] * fNoY[layer]){
0837     oneCanvas = kTRUE;
0838 //     fNoX[layer] > 1 ? --(fNoX[layer]) : --(fNoY[layer]);
0839     (fNoX[layer] > 1 && fNoX[layer] >= fNoY[layer]) ? --(fNoX[layer]) : --(fNoY[layer]);
0840 //  if(nHists < fNoX[layer] * fNoY[layer]) fNoY[layer] > 1 ? --(fNoY[layer]) : --(fNoX[layer]);
0841     if(nHists < fNoX[layer] * fNoY[layer])
0842       (fNoY[layer] > 1 && fNoY[layer] >= fNoX[layer]) ? --(fNoY[layer]) : --(fNoX[layer]);
0843   }
0844 //   if(oneCanvas && nHists > fNoX[layer] * fNoY[layer]) ++(fNoX[layer]);
0845 //   if(oneCanvas && nHists > fNoX[layer] * fNoY[layer]) 
0846 //     (fNoX[layer] > fNoY[layer]) ? ++(fNoY[layer]) : ++(fNoX[layer]);
0847   while(oneCanvas && nHists > fNoX[layer] * fNoY[layer]){
0848     (fNoX[layer] > fNoY[layer]) ? ++(fNoY[layer]) : ++(fNoX[layer]);
0849   }
0850 
0851   if(fCanArrays->GetSize() > layer && fCanArrays->At(layer)){
0852     static_cast<TObjArray*>(fCanArrays->At(layer))->Delete();
0853   } else {
0854     fCanArrays->AddAtAndExpand(new TObjArray, layer);
0855   }
0856 
0857   TString canName(fCanvasName);
0858   (canName += layer) += "_";
0859 
0860   for(Long_t i = 0; i < nCanvases; i++){
0861     Int_t width = fCanvasWidth, height = fCanvasHeight;
0862 //  on screen this is nice, but Print for different canvas sizes in one .ps fails...
0863 //     if(fNoX[layer] < fNoY[layer]){
0864 //       width = (width * 11) / 14;
0865 //       height *= 73; height /= 50;
0866 //     } else if(fNoX[layer] > fNoY[layer]){ // new!
0867 //       width = (width * 73) / 50;
0868 //       //      height *= 11; height /= 14;
0869 //     }
0870 
0871     while(gROOT->FindObject(canName+i)){
0872       canName += 'n';
0873     }
0874 
0875     TCanvas* can = new TCanvas(canName+i, canName+i, 10, 10, width, height);
0876     if (fNoX[layer] != 1 || fNoY[layer] != 1) can->Divide(fNoX[layer], fNoY[layer]);
0877     static_cast<TObjArray*>(fCanArrays->At(layer))->Add(can);
0878   }
0879 }
0880 
0881 
0882 //________________________________________________________
0883 Int_t GFHistManager::NumberOfSubPadsOf(TCanvas* can)
0884 {
0885   Int_t n = 0;
0886 
0887   TIter next(can ? can->GetListOfPrimitives() : NULL);
0888   while (TObject* obj = next()) {
0889     if (obj->InheritsFrom(TVirtualPad::Class())){
0890       ++n;
0891     }
0892   }
0893 
0894   return n;
0895 }
0896 
0897 //________________________________________________________
0898 void GFHistManager::SetLegendX1Y1X2Y2(Double_t x1, Double_t y1, Double_t x2,Double_t y2)
0899 {
0900   fLegendX1 = x1;
0901   fLegendY1 = y1;
0902   fLegendX2 = x2;
0903   fLegendY2 = y2;
0904 }
0905 
0906 //________________________________________________________
0907 void GFHistManager::SetLegendX1(Double_t x1) {fLegendX1 = x1;}
0908 //________________________________________________________
0909 void GFHistManager::SetLegendY1(Double_t y1) {fLegendY1 = y1;}
0910 //________________________________________________________
0911 void GFHistManager::SetLegendX2(Double_t x2) {fLegendX2 = x2;}
0912 //________________________________________________________
0913 void GFHistManager::SetLegendY2(Double_t y2) {fLegendY2 = y2;}
0914 
0915 //________________________________________________________
0916 void GFHistManager::SetStatsX1Y1X2Y2(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
0917 {
0918   fStatsX1 = x1;
0919   fStatsX2 = x2;
0920   fStatsY1 = y1;
0921   fStatsY2 = y2;
0922 }
0923 
0924 //________________________________________________________
0925 void GFHistManager::SetNumHistsX(UInt_t numX)
0926 {
0927   for(Int_t i = 0; i < fDepth; ++i){
0928     fNoX[i] = numX;
0929   }
0930 }
0931 
0932 //________________________________________________________
0933 void GFHistManager::SetNumHistsX(UInt_t numX, Int_t layer)
0934 {
0935   if(this->CheckDepth("SetNumHistsX", layer, kFALSE)) {
0936     fNoX[layer] = numX;
0937   }
0938 }
0939 
0940 //________________________________________________________
0941 void GFHistManager::SetNumHistsY(UInt_t numY)
0942 {
0943   for(Int_t i = 0; i < fDepth; ++i){
0944     fNoY[i] = numY;
0945   }
0946 }
0947 
0948 //________________________________________________________
0949 void GFHistManager::SetNumHistsY(UInt_t numY, Int_t layer)
0950 {
0951   if(this->CheckDepth("SetNumHistsY", layer, kFALSE)) {
0952     fNoY[layer] = numY;
0953   }
0954 }
0955 
0956 //________________________________________________________
0957 void GFHistManager::SetNumHistsXY(UInt_t numX, UInt_t numY)
0958 {
0959   this->SetNumHistsX(numX);
0960   this->SetNumHistsY(numY);
0961 }
0962 
0963 //________________________________________________________
0964 void GFHistManager::SetNumHistsXY(UInt_t numX, UInt_t numY, Int_t layer)
0965 {
0966   this->SetNumHistsX(numX, layer);
0967   this->SetNumHistsY(numY, layer);
0968 }
0969 
0970 //________________________________________________________
0971 void GFHistManager::SetLogY(Bool_t yesNo)
0972 {
0973   for(Int_t i = 0; i < fDepth; ++i){
0974     this->SetLogY(i, yesNo);
0975   }
0976 }
0977 
0978 //________________________________________________________
0979 void GFHistManager::SetLogY(Int_t layer, Bool_t yesNo)
0980 {
0981   if(this->CheckDepth("SetLogY", layer, kFALSE)) {
0982     fLogY[layer] = yesNo ? 1 : 0;
0983     if(layer < fCanArrays->GetEntriesFast()) {
0984       this->Update(layer); // if canvas already drawn
0985     }
0986   }
0987 }
0988 
0989 //________________________________________________________
0990 void GFHistManager::SetHistsOption(Option_t* option)
0991 {
0992   for(Int_t i = 0; i < fDepth; ++i){
0993     this->SetHistsOption(option, i);
0994   }
0995 }
0996 
0997 //________________________________________________________
0998 void GFHistManager::SetHistsOption(Option_t* option, Int_t layer)
0999 {
1000   if(!this->CheckDepth("SetHistsOption", layer, kFALSE)) return;
1001 
1002   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1003   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1004     TIter iter(arr); // arr is GFHistArray* !
1005     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1006       TString opt(option); opt.ToLower();
1007       if(!hist->InheritsFrom(TH2::Class()) && opt.Contains("box")){
1008     opt.ReplaceAll("box",0);
1009       }
1010       hist->SetOption(opt);
1011     }
1012   }
1013 }
1014 
1015 //________________________________________________________
1016 void GFHistManager::SetHistsMinMax(Double_t minMax, Bool_t min)
1017 {
1018   for(Int_t i = 0; i < fDepth; ++i){
1019     this->SetHistsMinMax(minMax, min, i);
1020   }
1021 }
1022 
1023 //________________________________________________________
1024 void GFHistManager::SetHistsMinMax(Double_t minMax, Bool_t min, Int_t layer)
1025 {
1026   if(!this->CheckDepth("SetHistsMinMax", layer, kFALSE)) return;
1027 
1028   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1029   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1030     TIter iter(arr); // arr is GFHistArray* !
1031     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1032       if(min) hist->SetMinimum(minMax);
1033       else hist->SetMaximum(minMax);
1034     }
1035   }
1036   if(layer < fCanArrays->GetEntriesFast()) {
1037     this->Update(layer); // if canvas already drawn
1038   }
1039 }
1040 
1041 
1042 //________________________________________________________
1043 void GFHistManager::AddHistsOption(Option_t* option)
1044 {
1045   for(Int_t i = 0; i < fDepth; ++i){
1046     this->AddHistsOption(option, i);
1047   }
1048 }
1049 
1050 //________________________________________________________
1051 void GFHistManager::AddHistsOption(Option_t* option, Int_t layer)
1052 {
1053   // if 'layer' exists, add 'option' to all hists so far existing in this layer
1054   // (ignore option 'box' for 1-D histograms)
1055   if(!this->CheckDepth("AddHistsOption", layer, kFALSE)) return;
1056 
1057   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1058   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1059     TIter iter(arr); // arr is GFHistArray* !
1060     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1061       TString opt(option); opt.ToLower();
1062       if(!hist->InheritsFrom(TH2::Class()) && opt.Contains("box",TString::kIgnoreCase)){
1063     opt.ReplaceAll("box",0);
1064       }
1065       hist->SetOption(opt += hist->GetOption());
1066     }
1067   }
1068 }
1069 
1070 
1071 //________________________________________________________
1072 void GFHistManager::SetHistsXTitle(const char* title)
1073 {
1074   for(Int_t i = 0; i < fDepth; ++i){
1075     this->SetHistsXTitle(title, i);
1076   }
1077 }
1078 
1079 //________________________________________________________
1080 void GFHistManager::SetHistsXTitle(const char* title, Int_t layer)
1081 {
1082   if(!this->CheckDepth("SetHistsXTitle", layer, kFALSE)) return;
1083 
1084   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1085   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1086     TIter iter(arr); // arr is GFHistArray* !
1087     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1088       hist->SetXTitle(title);
1089     }
1090   }
1091 }
1092 
1093 //________________________________________________________
1094 void GFHistManager::SetHistsYTitle(const char* title)
1095 {
1096   for(Int_t i = 0; i < fDepth; ++i){
1097     this->SetHistsYTitle(title, i);
1098   }
1099 }
1100 
1101 //________________________________________________________
1102 void GFHistManager::SetHistsYTitle(const char* title, Int_t layer)
1103 {
1104   if(!this->CheckDepth("SetHistsYTitle", layer, kFALSE)) return;
1105 
1106   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1107   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1108     TIter iter(arr);// arr is GFHistArray* !
1109     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1110       hist->SetYTitle(title);
1111     }
1112   }
1113 }
1114 
1115 
1116 //________________________________________________________
1117 void GFHistManager::SetHistsFillColor(Color_t color)
1118 {
1119   for(Int_t i = 0; i < fDepth; ++i){
1120     this->SetHistsFillColor(color, i);
1121   }
1122 }
1123 
1124 //________________________________________________________
1125 void GFHistManager::SetHistsFillColor(Color_t color, Int_t layer)
1126 {
1127   if(!this->CheckDepth("SetHistsFillColor", layer, kFALSE)) return;
1128 
1129   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1130   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1131     TIter iter(arr); // arr is GFHistArray* !
1132     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1133       hist->SetFillColor(color);
1134     }
1135   }
1136 }
1137 
1138 //________________________________________________________
1139 void GFHistManager::SetHistsLineWidth(Width_t width)
1140 {
1141   for(Int_t i = 0; i < fDepth; ++i){
1142     this->SetHistsLineWidth(width, i);
1143   }
1144 }
1145 
1146 //________________________________________________________
1147 void GFHistManager::SetHistsLineWidth(Width_t width, Int_t layer)
1148 {
1149   if(!this->CheckDepth("SetHistsLineWidth", layer, kFALSE)) return;
1150 
1151   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1152   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1153     TIter iter(arr); // arr is GFHistArray* !
1154     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1155       hist->SetLineWidth(width);
1156     }
1157   }
1158 }
1159 
1160 //________________________________________________________
1161 void GFHistManager::SetHistsLineStyle(Int_t s)
1162 {
1163   for(Int_t i = 0; i < fDepth; ++i){
1164     this->SetHistsLineStyle(s, i);
1165   }
1166 }
1167 
1168 //________________________________________________________
1169 void GFHistManager::SetHistsLineStyle(Int_t s, Int_t layer, Int_t numHistInPad)
1170 {
1171   // sets style 's' toall hists in 'layer'.
1172   // if numHistInPad >= 0: only the given histNum in each pad is changed in style
1173   // (default is numHistInPad = -1)
1174   if(!this->CheckDepth("SetHistsLineStyle", layer, kFALSE)) return;
1175 
1176   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1177   while(const GFHistArray* arr = static_cast<GFHistArray*>(iter2.Next())){
1178     if(numHistInPad < 0 || numHistInPad >= arr->GetEntriesFast()){ // all hist in pad
1179       TIter iter(arr); // arr is GFHistArray* !
1180       while(TH1* hist = static_cast<TH1*>(iter.Next())){
1181     hist->SetLineStyle(s);
1182       }
1183     } else {
1184       (*arr)[numHistInPad]->SetLineStyle(s);
1185     }
1186   }
1187 }
1188 
1189 
1190 //________________________________________________________
1191 void GFHistManager::SetHistsLineColor(Color_t color)
1192 {
1193   for(Int_t i = 0; i < fDepth; ++i){
1194     this->SetHistsLineColor(color, i);
1195   }
1196 }
1197 
1198 //________________________________________________________
1199 void GFHistManager::SetHistsLineColor(Color_t color, Int_t layer)
1200 {
1201   if(!this->CheckDepth("SetHistsLineColor", layer, kFALSE)) return;
1202 
1203   TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
1204   while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
1205     TIter iter(arr); // arr is GFHistArray* !
1206     while(TH1* hist = static_cast<TH1*>(iter.Next())){
1207       hist->SetLineColor(color);
1208     }
1209   }
1210 }
1211 
1212 //________________________________________________________
1213 Bool_t GFHistManager::CheckDepth(const char* method, Int_t layer, 
1214                  Bool_t mayExpand)
1215 {
1216   // true, if layer is possible, if (mayExpand) expands to layer >= 0
1217   if(layer < 0){
1218     this->Warning("CheckDepth", "Layer below 0 (%d) called in '%s'!",
1219           layer, method);
1220     return kFALSE;
1221   }
1222 
1223   if(layer > fDepth-1){
1224     if(mayExpand) {
1225       this->ExpandTo(layer);
1226       return kTRUE;
1227     } else {
1228       this->Warning("CheckDepth", "Layer %d called in '%s', max. is %d",
1229           layer, method, fDepth-1);
1230       return kFALSE;
1231     }
1232   }
1233   return kTRUE;
1234 }
1235 
1236 //________________________________________________________
1237 void GFHistManager::ExpandTo(Int_t layer)
1238 {
1239   if(layer+1 <= fDepth){
1240     this->Error("ExpandTo",
1241         "Shrinking forbidden, fDepth = %d, should expand to = %d",
1242         fDepth, layer+1);
1243     return;
1244   }
1245 
1246   fNoX.Set(layer+1);
1247   fNoY.Set(layer+1);
1248   fLogY.Set(layer+1);
1249 
1250   for(Int_t i = fDepth; i <= layer; ++i){
1251     fNoX[i] = kDefaultPadsPerCanX;
1252     fNoY[i] = kDefaultPadsPerCanY;
1253     fLogY[i]= 0;
1254     fHistArrays->AddAtAndExpand(new TObjArray, i);
1255     fCanArrays->AddAtAndExpand(new TObjArray, i);
1256   }
1257 
1258   fDepth = layer+1;
1259 }
1260 
1261 //________________________________________________________
1262 Bool_t GFHistManager::CheckHistNum(const char* method, Int_t layer, 
1263                  Int_t histNum, Bool_t mayExpand)
1264 {
1265   // true if hist 'histNum' exists in 'layer' 
1266   // if(mayExpand == kTRUE) expands to this size if necessary! (default: kFALSE)
1267   if(!this->CheckDepth(method, layer, mayExpand)) return kFALSE; 
1268   
1269 
1270   TObjArray * layerArr = static_cast<TObjArray*>(fHistArrays->At(layer));
1271   if(histNum < 0) {
1272     this->Warning("CheckHistNum", "histogram number %d requested!", histNum);
1273     return kFALSE;
1274   }
1275   while(histNum >= layerArr->GetEntriesFast()){
1276     if(mayExpand){
1277       layerArr->AddAtAndExpand(new GFHistArray, layerArr->GetEntriesFast());
1278     } else {
1279       this->Warning("CheckHistNum", "layer %d has only %d histograms, number %d requested!",
1280             layer, layerArr->GetEntriesFast(), histNum);
1281       return kFALSE;
1282     }
1283   }
1284   return kTRUE;
1285 }
1286 
1287 //________________________________________________________
1288 TObjArray* GFHistManager::MakeLegends(Int_t layer)
1289 {
1290   //  returns array of legends of 'layer' (to be called if 'layer' really exist!)
1291   // creates if necessary
1292   if(!fLegendArrays) fLegendArrays = new TObjArray(fDepth);
1293   if(layer > fLegendArrays->GetLast() || !fLegendArrays->At(layer)) {
1294     fLegendArrays->AddAtAndExpand(new TObjArray, layer);
1295   }
1296 
1297   return static_cast<TObjArray*>(fLegendArrays->At(layer));
1298 }
1299 
1300 //________________________________________________________
1301 TList* GFHistManager::MakeObjList(Int_t layer, Int_t histoNum)
1302 {
1303   // return list of objects to be drawn upon hists in pad histoNum of 'layer' 
1304   // (to be called if 'layer' really exist!)
1305   if(!fObjLists) fObjLists = new TObjArray(fDepth);
1306   if(layer > fObjLists->GetLast() || !fObjLists->At(layer)){
1307     fObjLists->AddAtAndExpand(new TObjArray(this->GetNumHistsOf(layer)),layer);
1308   }
1309   TObjArray* layerLists = static_cast<TObjArray*>(fObjLists->At(layer));
1310   if(histoNum > layerLists->GetLast() || !layerLists->At(histoNum)){
1311     layerLists->AddAtAndExpand(new TList, histoNum); 
1312   }
1313 
1314   return static_cast<TList*>(layerLists->At(histoNum));
1315 }
1316 
1317 //________________________________________________________
1318 GFHistArray* GFHistManager::GetHistsOf(Int_t layer, Int_t histNum, Bool_t mayExpand)
1319 {
1320   //  returns array of histograms for pad 'histNum' of 'layer'
1321   // if(mayExpand) creates if necessary!
1322   if(!this->CheckHistNum("GetHistsOf", layer, histNum, mayExpand)) return NULL;
1323   TObjArray* layerHists = static_cast<TObjArray*>(fHistArrays->At(layer));
1324   return static_cast<GFHistArray*>(layerHists->At(histNum));
1325 }
1326 
1327 //________________________________________________________
1328 TList* GFHistManager::GetObjectsOf(Int_t layer, Int_t histNo)
1329 {
1330   if(!this->CheckHistNum("GetObjectsOf", layer, histNo, kFALSE)) return NULL;
1331 
1332   if(fObjLists && layer <= fObjLists->GetLast() && fObjLists->At(layer)){
1333     TObjArray* layerLists = static_cast<TObjArray*>(fObjLists->At(layer));
1334     if(histNo <= layerLists->GetLast() && layerLists->At(histNo)){
1335       return static_cast<TList*>(layerLists->At(histNo));
1336     }
1337   }
1338 
1339   return NULL;
1340 }
1341 
1342 //________________________________________________________
1343 Int_t GFHistManager::GetNumHistsOf(Int_t layer)
1344 {
1345   if(!this->CheckDepth("GetNumHistsOf", layer, kFALSE)) return 0;
1346   TObjArray* layerHists = static_cast<TObjArray*>(fHistArrays->At(layer));
1347   if(layerHists) return layerHists->GetEntriesFast();
1348   return 0;
1349 }
1350 
1351 //________________________________________________________
1352 TLegend* GFHistManager::GetLegendOf(Int_t layer, Int_t histoNum)
1353 {
1354   // if it already exists!
1355   if(!this->CheckHistNum("AddLegend", layer, histoNum)) return NULL;
1356 
1357   TObjArray* legendsOfLayer = this->MakeLegends(layer);
1358   TLegend* legend = (legendsOfLayer->GetSize() < histoNum ? 
1359              NULL : static_cast<TLegend*>(legendsOfLayer->At(histoNum)));
1360   return legend;
1361 }
1362 
1363 
1364 //________________________________________________________
1365 void GFHistManager::MakeDifferentStyle(GFHistArray* hists)
1366 {
1367   // easy version: adjust the histogram lines to colors
1368   // kBlack, kRed, kGreen, kBlue, kYellow, kMagenta, kCyan (c.f. $ROOTSYS/include/Gtypes.h)
1369   // 1       2     3       4      5        6         7 (skip 3 and 5: kGreen hardly visible...)
1370   //                                                           (... kYellow dito)
1371   // also set line style, set marker color to line color
1372 
1373   if (!hists || hists->GetEntriesFast() < 2) return; // nothing to do
1374 
1375   Color_t color = 0;
1376   for(Int_t i = 0; i < hists->GetEntriesFast(); ++i){
1377 //     Color_t color = i+1;
1378     ++color;
1379     Style_t style = i+1;
1380     while(style > 4) style -= 4;
1381     if(color == 3) ++color; //omit kGreen
1382     if(color == 5) ++color; // and kYellow 
1383     if(color > 7 ) {
1384       ::Error("GFHistManager::MakeDifferentStyle", "Out of colors");
1385       color = 0;//      break;
1386     }
1387     hists->At(i)->SetLineColor(color);
1388     hists->At(i)->SetMarkerColor(color);
1389     hists->At(i)->SetMarkerSize(0.02);
1390     hists->At(i)->SetLineStyle(style);
1391   }
1392 }
1393 
1394 //________________________________________________________
1395 Double_t GFHistManager::MaxOfHist(const TH1* h) const
1396 {
1397   // Take bin with max content, adds error and returns (no *1.05 applied!),
1398   // but cares that - together with an error bar - another bin might be higher...
1399   // If the hists option contains nothing about errors: error is NOT added!
1400 
1401   TString option = h->GetOption();
1402   option.ToLower();
1403   option.ReplaceAll("same", 0);
1404   
1405   Int_t maxBin = h->GetMaximumBin();
1406   Double_t result = h->GetBinContent(maxBin);
1407   if(option.Contains('e') || (h->GetSumw2N() && !option.Contains("hist"))){
1408     for(Int_t bin = 1; bin <= h->GetNbinsX(); ++bin){ //FIXME: for 2/3D: loop over y/z!
1409       result = TMath::Max(result, (h->GetBinContent(bin) + h->GetBinError(bin))); 
1410     }
1411   }
1412   return result;
1413 }
1414 
1415 //________________________________________________________
1416 Double_t GFHistManager::MaxOfHists(const TObjArray* hists) const
1417 {
1418   Double_t result = 0.;
1419   TIter nextHist(hists);
1420   while(TObject* hist = nextHist()){
1421     if(hist->InheritsFrom(TH1::Class())){
1422       result = TMath::Max(result, this->MaxOfHist(static_cast<TH1*>(hist)));
1423     } else {
1424       this->Warning("MaxOfHists", "Entry in input array is not a histogram!");
1425     }
1426   }
1427   return result;
1428 }
1429 
1430 //________________________________________________________
1431 Double_t GFHistManager::MinOfHist(const TH1* h) const
1432 {
1433   // Take bin with min content, subtract error and returns (no *1.05 applied!),
1434   // but cares that - together with an error bar - another bin might be lower...
1435   // If the hists option contains nothing about errors: error is NOT subtracted!
1436 
1437   TString option = h->GetOption();
1438   option.ToLower();
1439   option.ReplaceAll("same", 0);
1440   
1441   const Int_t minBin = h->GetMinimumBin();
1442   Double_t result = h->GetBinContent(minBin);
1443   if(option.Contains('e') || (h->GetSumw2N() && !option.Contains("hist"))){
1444     for(Int_t bin = 1; bin <= h->GetNbinsX(); ++bin){ //FIXME: for 2/3D: loop over y/z!
1445       result = TMath::Min(result, (h->GetBinContent(bin) - h->GetBinError(bin))); 
1446     }
1447   }
1448   return result;
1449 }
1450 
1451 //________________________________________________________
1452 Double_t GFHistManager::MinOfHists(const TObjArray* hists) const
1453 {
1454   Double_t result = DBL_MAX;
1455   TIter nextHist(hists);
1456   while(TObject* hist = nextHist()){
1457     if(hist->InheritsFrom(TH1::Class())){
1458       result = TMath::Min(result, this->MinOfHist(static_cast<TH1*>(hist)));
1459     } else {
1460       this->Warning("MinOfHists", "Entry in input array is not a histogram!");
1461     }
1462   }
1463 
1464   return result;
1465 }
1466 //________________________________________________________
1467 TCanvas*  GFHistManager::GetCanvas(Int_t layer, Int_t number)
1468 {
1469   // after draw!!
1470   if(!fCanArrays || fCanArrays->GetEntriesFast() <= layer) return NULL;
1471   TObjArray* cans = static_cast<TObjArray*>(fCanArrays->At(layer));
1472   if(cans && cans->GetEntriesFast() > number){
1473     return static_cast<TCanvas*>(cans->At(number));
1474   }
1475   return NULL;
1476 }
1477 
1478 //________________________________________________________
1479 TVirtualPad* GFHistManager::GetPad(Int_t layer, Int_t histNum)
1480 {
1481   // pointer to pad where hists from layer/histNum are painted in
1482   // callable after draw!
1483     
1484   Int_t totHistsYet = 0;
1485   Int_t numHists = 0;
1486   TCanvas *can = NULL;
1487 
1488   for (Int_t numCan = 0; ; ++numCan) {
1489     can = this->GetCanvas(layer, numCan);
1490     if (!can) break;
1491     numHists = TMath::Max(1, this->NumberOfSubPadsOf(can));
1492     totHistsYet += numHists;
1493     if (totHistsYet > histNum) {
1494       totHistsYet -= numHists;
1495       break;
1496     }
1497   }
1498 
1499   TVirtualPad *result = NULL;
1500   if (can) {
1501     TVirtualPad *oldPad = gPad;
1502     if (numHists <= 1) can->cd(0); // one hist per canvas: no pads!
1503     else can->cd(histNum - totHistsYet + 1);
1504     result = gPad;
1505     oldPad->cd();
1506   }
1507 
1508   return result;
1509 }
1510 
1511 //________________________________________________________
1512 Int_t GFHistManager::GetNumHistsX(Int_t layer) const
1513 {
1514   if(layer >= 0 && layer < fDepth) return fNoX[layer];
1515   else return 0;
1516 }
1517 
1518 //________________________________________________________
1519 Int_t GFHistManager::GetNumHistsY(Int_t layer) const
1520 {
1521   if(layer >= 0 && layer < fDepth) return fNoY[layer];
1522   else return 0;
1523 }
1524 
1525 //________________________________________________________
1526 void GFHistManager::GetLegendX1Y1X2Y2(Double_t& x1, Double_t& y1, 
1527                       Double_t& x2, Double_t& y2) const
1528 {
1529    x1 = fLegendX1;
1530    y1 = fLegendY1;
1531    x2 = fLegendX2;
1532    y2 = fLegendY2;
1533 }
1534 
1535 //________________________________________________________
1536 void GFHistManager::DrawFuncs(const TH1* hist) const
1537 {
1538   // calls Draw("SAME") for all TF1 in hist's GetListOfFunctions if necessary
1539   if(!hist || !TString(hist->GetOption()).Contains("HIST", TString::kIgnoreCase)) return;
1540   TIter nextprim(hist->GetListOfFunctions());
1541   while(TObject* next = nextprim()){
1542     if(next->InheritsFrom(TF1::Class())){
1543       next->Draw("SAME");
1544     }
1545   }
1546 }
1547 
1548 //________________________________________________________
1549 void GFHistManager::ColourStatsBoxes(GFHistArray *hists) const
1550 {
1551   // colours stats boxes like hists' line colors and moves the next to each other
1552   if (!hists) return;
1553   Double_t x1 = fStatsX1, x2 = fStatsX2, y1 = fStatsY1, y2 = fStatsY2;
1554   for (Int_t iH = 0; iH < hists->GetEntriesFast(); ++iH) {
1555     TH1 *h = hists->At(iH);
1556     if (!h) continue;
1557     TObject *statObj = h->GetListOfFunctions()->FindObject("stats");
1558     if (statObj && statObj->InheritsFrom(TPaveStats::Class())) {
1559       TPaveStats *stats = static_cast<TPaveStats*>(statObj);
1560       stats->SetLineColor(hists->At(iH)->GetLineColor());
1561       stats->SetTextColor(hists->At(iH)->GetLineColor());
1562       stats->SetX1NDC(x1);
1563       stats->SetX2NDC(x2);
1564       stats->SetY1NDC(y1);
1565       stats->SetY2NDC(y2);
1566       y2 = y1 - 0.005; // shift down 2
1567       y1 = y2 - (fStatsY2 - fStatsY1); // shift down 1
1568       if (y1 < 0.) {
1569     y1 = fStatsY1; y2 = fStatsY2; // restart y-positions
1570     x2 = x1 - 0.005; // shift left 2
1571     x1 = x2 - (fStatsX2 - fStatsX1); // shift left 1
1572     if (x1 < 0.) { // give up, start again:
1573       x1 = fStatsX1, x2 = fStatsX2, y1 = fStatsY1, y2 = fStatsY2;
1574     }
1575       }
1576     } else if (gStyle->GetOptStat() != 0) { // failure in case changed in list via TExec....
1577       this->Warning("ColourStatsBoxes", "No stats found for %s", hists->At(iH)->GetName());
1578     }
1579   }
1580 }
1581 
1582 //________________________________________________________
1583 void GFHistManager::ColourFuncs(GFHistArray *hists) const
1584 {
1585   // adjust colour of funcs to match hist, but only if exactly one function per hist
1586   if (!hists) return;
1587   for (Int_t iH = 0; iH < hists->GetEntriesFast(); ++iH) {
1588     TH1 *h = hists->At(iH);
1589     if (!h) continue;
1590 
1591     // look for _the_ TF1 (not > 1!)
1592     TF1 *func = NULL;
1593     TIter nextprim(h->GetListOfFunctions());
1594     while (TObject* next = nextprim()) {
1595       if (next->InheritsFrom(TF1::Class())) {
1596     if (func) { // there is already a TF1, so...
1597       func = NULL; // remove it again...
1598       break;       // ...and stop searching for  more!
1599     } else {
1600       func = static_cast<TF1*>(next);
1601     }
1602       }
1603     }
1604 // if exactly 1 found, adjust line style/colour
1605     if (func) {
1606       func->SetLineColor(h->GetLineColor());
1607       func->SetLineStyle(h->GetLineStyle());
1608     }
1609   } 
1610 }
1611 
1612 //________________________________________________________
1613 void GFHistManager::SetCanvasName(const TString& name) {
1614   fCanvasName = name;
1615 }