// Author: Gero Flucke <mailto:flucke@mail.desy.de>
//____________________________________
// GFHistManager
// Author: Gero Flucke
// Date: Feb. 10th, 2002
// last update: $Date: 2005/12/15 11:20:59 $
// by: $Author: flucke $
//
#include <iostream>
using namespace std;
// #include <vector>
// RooT header:
#include <TROOT.h>
#include <TError.h>
#include <TH1.h>
#include <TH2.h>
#include <TF1.h>
#include <TCanvas.h>
#include <TFile.h>
#include <TString.h>
#include <TObjArray.h>
#include <TList.h>
#include <TLegend.h>
#include <TLegendEntry.h>
#if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
#include <TStyle.h>
#endif
// my header:
#include "GFHistManager.h"
#include "GFUtils/GFHistArray.h"
ClassImp(GFHistManager)
const Int_t GFHistManager::kDefaultPadsPerCanX = 4;
const Int_t GFHistManager::kDefaultPadsPerCanY = 3;
const Int_t GFHistManager::kDefaultDepth = 0;
TString GFHistManager::fgLegendEntryOption = "l";
GFHistManager::GFHistManager()
{
this->Initialise();
fBatch = kFALSE;
fDrawDiffStyle = kTRUE;
fLegendY1 = 0.75;
fLegendX1 = 0.7;
fLegendY2 = 0.99;
fLegendX2 = 0.99;
fCanvasWidth = 600;
fCanvasHeight = 600;
}
GFHistManager::GFHistManager(TH1* hist)
{
// constructing with hist as first histogram
this->Initialise();
this->AddHist(hist);
fBatch = kFALSE;
fDrawDiffStyle = kTRUE;
fLegendY1 = 0.75;
fLegendX1 = 0.7;
fLegendY2 = 0.99;
fLegendX2 = 0.99;
fCanvasWidth = 600;
fCanvasHeight = 600;
}
GFHistManager::GFHistManager(TCollection* hists)
{
// constructing with histos in 'hists' as first histogram
this->Initialise();
this->AddHists(hists);
fBatch = kFALSE;
fDrawDiffStyle = kTRUE;
fLegendY1 = 0.75;
fLegendX1 = 0.7;
fLegendY2 = 0.99;
fLegendX2 = 0.99;
fCanvasWidth = 600;
fCanvasHeight = 600;
}
//________________________________________________________
void GFHistManager::Initialise()
{
fDepth = kDefaultDepth;
fNoX.Set(fDepth);
fNoY.Set(fDepth);
#if ROOT_VERSION_CODE >= ROOT_VERSION(3,10,2) && ROOT_VERSION_CODE <= ROOT_VERSION(4,0,3)
// TArrayI::Reset(Int_t) buggy in 3.10_02:
for(Int_t i = 0; i < fNoX.GetSize(); ++i) fNoX[i] = kDefaultPadsPerCanX;
for(Int_t i = 0; i < fNoY.GetSize(); ++i) fNoY[i] = kDefaultPadsPerCanY;
#else
fNoX.Reset(kDefaultPadsPerCanX);
fNoY.Reset(kDefaultPadsPerCanY);
#endif
fLogY.Set(fDepth);
fLogY.Reset(); // set to 0
// fCanvasWidth = 700;
// fCanvasHeight = 500;
// fCanvasWidth = 600;
// fCanvasHeight = 600;
fHistArrays = new TObjArray;
for(Int_t i = 0; i < fDepth; ++i){
fHistArrays->Add(new TObjArray);
}
fCanArrays = new TObjArray;
fLegendArrays = NULL;
fObjLists = NULL;
}
//________________________________________________________
GFHistManager::~GFHistManager()
{
// destructor: delete stored arrays, legends and canvases, but not the hists and objects!
if(fHistArrays) {
TIter iter(fHistArrays);
while(TObjArray* array = static_cast<TObjArray*>(iter.Next())){
array->Delete();
}
fHistArrays->Delete();
delete fHistArrays;
}
if(fLegendArrays) {
TIter legIter(fLegendArrays);
while(TObjArray* array = static_cast<TObjArray*>(legIter.Next())){
array->Delete();
}
fLegendArrays->Delete();
delete fLegendArrays;
}
if(fObjLists) {
TIter listArrayIter(fObjLists);
while(TObjArray* listArray = static_cast<TObjArray*>(listArrayIter.Next())){
listArray->Delete();; // delete lists, but not its objects
}
fObjLists->Delete(); // delete arrays of lists
delete fObjLists;// delete array of arrays of lists
}
if(fCanArrays) {
TIter canIter(fCanArrays);
while(TObjArray* array = static_cast<TObjArray*>(canIter.Next())){
array->Delete();
}
fCanArrays->Delete();
delete fCanArrays;
}
}
//________________________________________________________
void GFHistManager::Clear(Bool_t deleteHists)
{
// delete all canvases and clear the lists of hists stored in the manager
// (hists and objects are deleted if deleteHists is true [by default it is false])
TIter iterCanArrays(fCanArrays);
while(TObjArray* arr = static_cast<TObjArray*>(iterCanArrays.Next())){
arr->Delete(); // delete canvases
}
fCanArrays->Delete(); // delete arrays of canvases
delete fCanArrays;
if(fLegendArrays){ // by default there are no legends...
TIter iterLegArrays(fLegendArrays);
while(TObjArray* arr = static_cast<TObjArray*>(iterLegArrays.Next())){
arr->Delete(); // delete legends
}
fLegendArrays->Delete(); // delete arrays of legends
delete fLegendArrays;
}
if(fObjLists) {
TIter listArrayIter(fObjLists);
while(TObjArray* listArray = static_cast<TObjArray*>(listArrayIter.Next())){
if(deleteHists) {
TIter listIter(listArray);
while(TList* list = static_cast<TList*>(listIter.Next())){
list->Delete(); // delete objects if requested
}
}
listArray->Delete(); // delete lists
}
fObjLists->Delete(); // delete arrays of lists
delete fObjLists; // delete array of arrays of lists
}
TIter iterHistArrays(fHistArrays);
while(TObjArray* arr = static_cast<TObjArray*>(iterHistArrays.Next())){
TIter iterHistArrays2(arr);
while(TObjArray* arr2 = static_cast<TObjArray*>(iterHistArrays2.Next())){
if(deleteHists) arr2->Delete(); // delete histograms
else arr2->Clear();
}
arr->Delete();
}
fHistArrays->Delete(); // delete arrays of arrays of histograms
delete fHistArrays;
this->Initialise(); // here the arrays are rebuild and fDepth etc. adjusted
}
//________________________________________________________
void GFHistManager::Draw()
{
// draw all layers of histograms (ignore if in batch mode)
if(fBatch) return; // for speed up...
for(Int_t i = 0; i < fDepth; ++i){
this->Draw(i);
}
}
//________________________________________________________
void GFHistManager::Draw(Int_t layer)
{
if(fBatch) return;
this->DrawReally(layer);
}
//________________________________________________________
void GFHistManager::DrawReally(Int_t layer)
{
if(layer < 0 || layer > fDepth-1) {
this->Warning("DrawReally","Layer %d does not exist, possible are 0 to %d.",
layer, fDepth-1);
return;
}
this->MakeCanvases(layer);
TIter canIter(static_cast<TObjArray*>(fCanArrays->At(layer)));
TIter histIter(static_cast<TObjArray*>(fHistArrays->At(layer)));
Int_t histNo = 0; // becomes number of histograms in layer
while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
Int_t nPads = this->NumberOfSubPadsOf(can);
for(Int_t i = 0; i <= nPads; ++i){
if (i == 0 && nPads != 0) i = 1;
can->cd(i);
if(GFHistArray* histsOfPad = static_cast<GFHistArray*>(histIter.Next())){
TIter hists(histsOfPad);
TH1* firstHist = static_cast<TH1*>(hists.Next());
firstHist->Draw();
this->DrawFuncs(firstHist);
while(TH1* h = static_cast<TH1*>(hists.Next())){
h->Draw(Form("SAME%s", h->GetOption()));
this->DrawFuncs(h);
}
if(histsOfPad->GetEntriesFast() > 1){
const Double_t max = this->MaxOfHists(histsOfPad);
if(//firstHist->GetMaximumStored() != -1111. && ????
max > firstHist->GetMaximumStored()){
firstHist->SetMaximum((fLogY[layer] ? 1.1 : 1.05) * max);
}
const Double_t min = this->MinOfHists(histsOfPad);
if(min < 0.) firstHist->SetMinimum(min * 1.05);
}
if(fLogY[layer]
&& (firstHist->GetMinimum() > 0.
|| (firstHist->GetMinimum() == 0.
&& firstHist->GetMinimumStored() == -1111.)))gPad->SetLogy();
// draw other objects:
this->DrawObjects(layer, histNo);
// draw legends on top of all
if(fLegendArrays && layer <= fLegendArrays->GetLast() && fLegendArrays->At(layer)){
if(fDrawDiffStyle) GFHistManager::MakeDifferentStyle(histsOfPad);
this->DrawLegend(layer, histNo);
}
gPad->Modified();
histNo++;
}
} // loop over pads
} // loop over canvases
}
//________________________________________________________
void GFHistManager::DrawLegend(Int_t layer, Int_t histNo)
{
// histNo starting at '0'
// We must already be in the correct pad, layer and histNo must exist
if(fLegendArrays && layer <= fLegendArrays->GetLast() && fLegendArrays->At(layer)){
TObjArray* legends = static_cast<TObjArray*>(fLegendArrays->At(layer));
TObject* legend = (histNo <= legends->GetLast() ? legends->At(histNo) : NULL);
if(legend) legend->Draw();
}
}
//________________________________________________________
void GFHistManager::DrawObjects(Int_t layer, Int_t histNo)
{
// histNo starting at '0'
// We must already be in the correct pad, layer and histNo must exist
if(fObjLists && layer <= fObjLists->GetLast() && fObjLists->At(layer)){
TObjArray* layerLists = static_cast<TObjArray*>(fObjLists->At(layer));
if(histNo <= layerLists->GetLast() && layerLists->At(histNo)){
TObjLink *lnk = static_cast<TList*>(layerLists->At(histNo))->FirstLink();
while (lnk) {
lnk->GetObject()->Draw(lnk->GetOption());
lnk = lnk->Next();
}
}
}
}
//________________________________________________________
void GFHistManager::Print(const char* filename, Bool_t add)
{
// print all layers of histograms to ps-file 'filename'
// if 'add == true' puts '(' or ')' only if 'filename' ends with it,
// e.g. if i is loop variable
// GFHistManager *man = ...;
// TString name("XXX.ps");
// if(i == 0) man->Print(name + '(');
// else if(i == last) man->Print(name + ')');
// else man->Print(name, kTRUE);
const Bool_t rootIsBatch = gROOT->IsBatch();
if(fBatch){
gROOT->SetBatch();
for(Int_t i = 0; i < fDepth; ++i){
this->DrawReally(i);
}
}
gROOT->SetBatch(rootIsBatch);
TObjArray cans;
TIter canArrayIter(fCanArrays);
while(TObjArray* canArray = static_cast<TObjArray*>(canArrayIter.Next())){
cans.AddAll(canArray);
}
const Int_t nCans = cans.GetEntriesFast();
if(nCans == 1) {
cans.At(0)->Print(filename);
return;
}
TString plainName(filename);
const Bool_t starting = plainName.EndsWith("(");
if(starting) {
const Ssiz_t ind = plainName.Last('(');
plainName.Remove(ind);
// plainName.ReplaceAll("(", "");
}
const Bool_t ending = plainName.EndsWith(")");
if(ending) {
const Ssiz_t ind = plainName.Last(')');
plainName.Remove(ind);
// plainName.ReplaceAll(")", "");
}
for(Int_t i = 0; i < nCans; ++i){
if(i == 0 && !ending && (!add || starting)) {
cans.At(i)->Print(plainName + "(");
} else if(i == nCans - 1 && !starting && (!add || ending)) {
cans.At(i)->Print(plainName + ")");
} else {
cans.At(i)->Print(plainName);
}
}
}
// //________________________________________________________
// void GFHistManager::Print(const char* filename, Int_t layer)
// {
// // print all canvases of layer into .ps-files with name of their first histogram
// Bool_t rootIsBatch = gROOT->IsBatch();
// gROOT->SetBatch();
// this->DrawReally(layer);
// TIter canIter(static_cast<TObjArray*>(fCanArrays->At(layer)));
// Int_t nCan = 0;
// while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
// TObjArray* histLayer = static_cast<TObjArray*>(fHistArrays->At(layer));
// TObjArray* firstHistInCan =
// static_cast<TObjArray*>(histLayer->At(nCan*fNoX[layer]*fNoY[layer]));
// ++nCan;
// if(firstHistInCan){
// TString psFile("/tmp/");
// psFile+=firstHistInCan->First()->GetName();
// can->Print(psFile+=".ps");
// }
// } // loop over canvases
// gROOT->SetBatch(rootIsBatch);
// }
//________________________________________________________
void GFHistManager::Update()
{
// call Update() to all canvases
for(Int_t i = 0; i < fDepth; ++i){
this->Update(i);
}
}
//________________________________________________________
void GFHistManager::Update(Int_t layer)
{
if(!this->CheckDepth("Update", layer, kFALSE)) {
return;
}
TIter canIter(static_cast<TObjArray*>(fCanArrays->At(layer)));
Int_t numPreviousCansHists = 0;
const Int_t numHistsLayer = this->GetNumHistsOf(layer);
while(TCanvas* can = static_cast<TCanvas*>(canIter.Next())){
Int_t nPads = this->NumberOfSubPadsOf(can);
for(Int_t i = 0; i <= nPads; ++i){
if (i == 0) {
if (nPads != 0) can->cd(++i);// subpads: step into first (prefix-increment!)
else can->cd(i); // no subpads: step into canvas
}
const Int_t histNo = numPreviousCansHists + i - 1;
if (histNo >= numHistsLayer) continue;
// draw other objects
this->DrawObjects(layer, histNo);
// draw legends on top of all
if(fLegendArrays && fLegendArrays->GetSize() > layer && fLegendArrays->At(layer)){
this->DrawLegend(layer, histNo);
}
const TH1 *h1 = this->GetHistsOf(layer, histNo)->First();
if(fLogY[layer]
&& (h1->GetMinimum() > 0.
|| (h1->GetMinimum() == 0. && h1->GetMinimumStored() == -1111.))) {
gPad->SetLogy();
} else {
gPad->SetLogy(kFALSE);
}
gPad->Modified();
// gPad->Update();
// gPad->Modified();
// gPad->Update();
}
// can->Update();
can->Modified();
can->Update();
// can->Modified();
numPreviousCansHists += nPads;
} // loop over canvases
}
//_____________________________________________________
TLegendEntry* GFHistManager::AddHist(TH1* hist, Int_t layer, const char* legendTitle,
const char* legOpt)
{
// add hist to 'layer'th list of histos (expands, if layer does not already exist!)
if(!hist){
this->Warning("AddHist", "adding NULL pointer will be ignored!");
return NULL;
}
if(!this->CheckDepth("AddHist", layer)) return NULL;
GFHistArray* newHist = new GFHistArray;
newHist->Add(hist);
TObjArray* layerHistArrays = static_cast<TObjArray*>(fHistArrays->At(layer));
layerHistArrays->Add(newHist);
if(legendTitle){
TObjArray* legends = this->MakeLegends(layer);
TLegend* legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
#if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
if (TString(gStyle->GetName()) == "Plain") legend->SetBorderSize(1);
#endif
legends->AddAtAndExpand(legend, layerHistArrays->IndexOf(newHist));
return legend->AddEntry(hist, legendTitle, legOpt ? legOpt : fgLegendEntryOption.Data());
}
return NULL;
}
//_____________________________________________________
void GFHistManager::AddHists(TCollection* hists, Int_t layer, const char* legendTitle,
const char* legOpt)
{
// add contents of 'hists' to 'layer'th list of histos (should be histograms!!!)
TIter iter(hists);
while(TObject* hist = iter.Next()){
if(!hist->InheritsFrom(TH1::Class())){
this->Warning("AddHists", "Trying to add a non-histogram object, ignore!");
} else this->AddHist(static_cast<TH1*>(hist), layer, legendTitle, legOpt);
}
}
//_____________________________________________________
TLegendEntry* GFHistManager::AddHistSame(TH1* hist, Int_t layer, Int_t histNum,
const char* legendTitle, const char* legOpt)
{
// adds hist to layer to draw it in the same pad as histNum's histo of that layer
if(!hist){
this->Warning("AddHistSame", "adding NULL pointer will be ignored!");
return NULL;
}
if (histNum > 0 && this->CheckDepth("AddHistSame", layer, kTRUE) //maybe added layer?
&& !this->GetHistsOf(layer, histNum-1)) {
this->Error("AddHistSame", "usage as AddHist only for next free histNum, not %d", histNum);
return NULL;
}
GFHistArray *histsArray = this->GetHistsOf(layer, histNum, kTRUE);// expand!
TLegendEntry* result = NULL;
if(histsArray) {
histsArray->Add(hist);
if(legendTitle){
TObjArray* legends = this->MakeLegends(layer);
TLegend* legend = NULL;
if(legends->GetLast() >= histNum
&& legends->At(histNum)){
legend = static_cast<TLegend*>(legends->At(histNum));
} else {
legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
#if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
if (TString(gStyle->GetName()) == "Plain") legend->SetBorderSize(1);
#endif
legends->AddAtAndExpand(legend, histNum);
}
result = legend->AddEntry(hist,legendTitle, legOpt ? legOpt : fgLegendEntryOption.Data());
}
}
return result;
}
//_____________________________________________________
void GFHistManager::AddHistsSame(GFHistArray* hists, Int_t layer,
const char* legendTitle, const char* legOpt)
{
// adds hists to layer
// each hist is AddHistSame(hist, layer, pad = 0...n)
if(!hists){
this->Warning("AddHistsSame", "adding NULL pointer will be ignored!");
return;
}
for(Int_t i = 0; i < hists->GetEntriesFast(); ++i){
this->AddHistSame((*hists)[i], layer, i, legendTitle, legOpt);
}
}
//_____________________________________________________
void GFHistManager::AddHistsSame(GFHistArray* hists, Int_t layer, Int_t histNum)
{
// adds hists to layer to draw it in the same pad as histNum's histo of that layer
if(!hists){
this->Warning("AddHistsSame", "adding NULL pointer will be ignored!");
return;
}
GFHistArray* histsArray = this->GetHistsOf(layer, histNum, kTRUE);
if(histsArray) histsArray->AddAll(hists);
}
//_____________________________________________________
void GFHistManager::AddLayers(GFHistManager* other)
{
// append the layers from other to this, hists are not cloned, but legends?
if(!other) return;
const Int_t oldDepth = fDepth;
for(Int_t iLayer = 0; iLayer < other->GetNumLayers(); ++iLayer){
for(Int_t iPad = 0; iPad < other->GetNumHistsOf(iLayer); ++iPad){
GFHistArray* hists = other->GetHistsOf(iLayer, iPad);
this->AddHistsSame(hists, oldDepth + iLayer, iPad);
TLegend* leg = other->GetLegendOf(iLayer, iPad);
if(leg) this->AddLegend(static_cast<TLegend*>(leg->Clone()), iLayer, iPad);
}
}
}
//_____________________________________________________
void GFHistManager::AddLayer(GFHistManager* other, Int_t layer)
{
// append the layer 'layer' from other to this, hists are not cloned, but legends?
if(!other || layer >= other->GetNumLayers()) return;
const Int_t newLayer = fDepth;
for(Int_t iPad = 0; iPad < other->GetNumHistsOf(layer); ++iPad){
GFHistArray* hists = other->GetHistsOf(layer, iPad);
this->AddHist(hists->At(0), newLayer);
for(Int_t iHist = 1; iHist < hists->GetEntriesFast(); ++iHist){
this->AddHistSame(hists->At(iHist), newLayer, iPad);
}
TLegend* leg = other->GetLegendOf(layer, iPad);
if(leg) this->AddLegend(static_cast<TLegend*>(leg->Clone()), newLayer, iPad);
}
}
//_____________________________________________________
TLegend* GFHistManager::AddLegend(Int_t layer, Int_t histoNum,
const char* header, Bool_t referAll)
{
// adds a legend referencing all hists in same pad 'histoNum' of layer
//
// FIXME: use help of other AddLegend method?
if(!this->CheckHistNum("AddLegend", layer, histoNum)) return NULL;
TObjArray* legendsOfLayer = this->MakeLegends(layer);
TLegend* legend = (legendsOfLayer->GetSize() <= histoNum ?
NULL : static_cast<TLegend*>(legendsOfLayer->At(histoNum)));
if(!legend) {
legend = new TLegend(fLegendX1, fLegendY1, fLegendX2, fLegendY2);
#if ROOT_VERSION_CODE < ROOT_VERSION(5,6,0)
if (TString(gStyle->GetName()) == "Plain") legend->SetBorderSize(1);
#endif
legendsOfLayer->AddAtAndExpand(legend, histoNum);
}
if(header) legend->SetHeader(header);
GFHistArray* hists = this->GetHistsOf(layer, histoNum);
TList* legendEntries = legend->GetListOfPrimitives();
if(referAll){
TIter histsIter(hists);
while(TObject* hist = histsIter.Next()){
Bool_t addNew = kTRUE;
TIter legEntrIter(legendEntries);
while(TLegendEntry* entry = static_cast<TLegendEntry*>(legEntrIter())){
if(hist == entry->GetObject()) {addNew = kFALSE; break;}
}
if(addNew) legend->AddEntry(hist, hist->GetName(), fgLegendEntryOption);
}
}
if(layer < fCanArrays->GetEntriesFast()) {
this->Update(layer); // if canvas already drawn
}
return legend;
}
//_____________________________________________________
Bool_t GFHistManager::RemoveLegend(Int_t layer, Int_t nPad)
{
// true if there was a legend
if(!this->CheckHistNum("RemoveLegend", layer, nPad)) return kFALSE;
TLegend* leg = this->GetLegendOf(layer, nPad);
if(!leg) return kFALSE;
TObjArray* legendsOfLayer = this->MakeLegends(layer);
if(!legendsOfLayer->Remove(leg)) {
this->Error("RemoveLegend", "inconsistent state for layer %d, nPad %d", layer, nPad);
return kFALSE;
}
delete leg;
if(layer < fCanArrays->GetEntriesFast()) {
this->Update(layer); // if canvas already drawn
}
return kTRUE;
}
//_____________________________________________________
void GFHistManager::AddLegend(TLegend* leg, Int_t layer, Int_t histoNum)
{
// hist and layer must already exist
if(!this->CheckHistNum("AddLegend", layer, histoNum)) return;
TObjArray* legendsOfLayer = this->MakeLegends(layer);
TLegend* legend = (legendsOfLayer->GetSize() < histoNum ?
NULL : static_cast<TLegend*>(legendsOfLayer->At(histoNum)));
if(legend) {
this->Error("AddLegend", "legend exists, replacing it");
delete legend;
}
legend = leg;
legendsOfLayer->AddAtAndExpand(legend, histoNum);
if(layer < fCanArrays->GetEntriesFast()) {
this->Update(layer); // if canvas already drawn
}
}
//_____________________________________________________
void GFHistManager::AddObject(TObject* obj, Int_t layer, Int_t histoNum, Option_t* opt)
{
// hist and layer must already exist
if(!this->CheckHistNum("AddObject", layer, histoNum)) return;
TList* objList = this->MakeObjList(layer, histoNum);
objList->Add(obj, opt);
if(layer < fCanArrays->GetEntriesFast()) {
this->Update(layer); // if canvas already drawn
}
}
//_____________________________________________________
void GFHistManager::WriteCanvases(TFile* file)
{
// write canvases with their content to file (overwrite)
if(!file) {
this->Warning("WriteCanvases", "no file given, ignore!");
return;
}
TDirectory* saveDir = gDirectory;
file->cd();
for(Int_t i = 0; i < fDepth; ++i){
TIter canvases(static_cast<TObjArray*>(fCanArrays->At(i)));
while(TCanvas* can = static_cast<TCanvas*>(canvases.Next())){
can->Write(0, kOverwrite);
}
}
saveDir->cd();
}
//_____________________________________________________
void GFHistManager::WriteHistos(TFile* file)
{
// write histos to file (overwrite)
if(!file) {
this->Warning("WriteHistos", "no file given, ignore!");
return;
}
TDirectory* saveDir = gDirectory;
file->cd();
for(Int_t i = 0; i < fDepth; ++i){
TIter iterHistsArr(static_cast<TObjArray*>(fHistArrays->At(i)));
while(TObjArray* arr2 = static_cast<TObjArray*>(iterHistsArr.Next())){
TIter iterHistArr2(arr2);
while(TObject* hist = iterHistArr2.Next()){
hist->Write(0, kOverwrite);
}
}
}
saveDir->cd();
}
//_____________________________________________________
void GFHistManager::MakeCanvases(Int_t layer)
{
// no check done whether layer is consistent with depth...
Int_t nHists = static_cast<TObjArray*>(fHistArrays->At(layer))->GetEntriesFast();
Int_t nCanvases = nHists / (fNoX[layer] * fNoY[layer]);
if(nHists > nCanvases * fNoX[layer] * fNoY[layer]){
++nCanvases;
}
Bool_t oneCanvas = kFALSE;
while(nHists < fNoX[layer] * fNoY[layer]){
oneCanvas = kTRUE;
// fNoX[layer] > 1 ? --(fNoX[layer]) : --(fNoY[layer]);
(fNoX[layer] > 1 && fNoX[layer] >= fNoY[layer]) ? --(fNoX[layer]) : --(fNoY[layer]);
// if(nHists < fNoX[layer] * fNoY[layer]) fNoY[layer] > 1 ? --(fNoY[layer]) : --(fNoX[layer]);
if(nHists < fNoX[layer] * fNoY[layer])
(fNoY[layer] > 1 && fNoY[layer] >= fNoX[layer]) ? --(fNoY[layer]) : --(fNoX[layer]);
}
// if(oneCanvas && nHists > fNoX[layer] * fNoY[layer]) ++(fNoX[layer]);
// if(oneCanvas && nHists > fNoX[layer] * fNoY[layer])
// (fNoX[layer] > fNoY[layer]) ? ++(fNoY[layer]) : ++(fNoX[layer]);
while(oneCanvas && nHists > fNoX[layer] * fNoY[layer]){
(fNoX[layer] > fNoY[layer]) ? ++(fNoY[layer]) : ++(fNoX[layer]);
}
if(fCanArrays->GetSize() > layer && fCanArrays->At(layer)){
static_cast<TObjArray*>(fCanArrays->At(layer))->Delete();
} else {
fCanArrays->AddAtAndExpand(new TObjArray, layer);
}
TString canName("canvas");
(canName += layer) += "_";
for(Long_t i = 0; i < nCanvases; i++){
Int_t width = fCanvasWidth, height = fCanvasHeight;
// on screen this is nice, but Print for different canvas sizes in one .ps fails...
// if(fNoX[layer] < fNoY[layer]){
// width = (width * 11) / 14;
// height *= 73; height /= 50;
// } else if(fNoX[layer] > fNoY[layer]){ // new!
// width = (width * 73) / 50;
// // height *= 11; height /= 14;
// }
while(gROOT->FindObject(canName+i)){
canName += 'n';
}
TCanvas* can = new TCanvas(canName+i, canName+i, 10, 10, width, height);
if (fNoX[layer] != 1 || fNoY[layer] != 1) can->Divide(fNoX[layer], fNoY[layer]);
static_cast<TObjArray*>(fCanArrays->At(layer))->Add(can);
}
}
//________________________________________________________
Int_t GFHistManager::NumberOfSubPadsOf(TCanvas* can)
{
Int_t n = 0;
TIter next(can->GetListOfPrimitives());
while (TObject* obj = next()) {
if (obj->InheritsFrom(TPad::Class())){
++n;
}
}
return n;
}
//________________________________________________________
void GFHistManager::SetLegendX1Y1X2Y2(Double_t x1, Double_t y1, Double_t x2,Double_t y2)
{
fLegendX1 = x1;
fLegendY1 = y1;
fLegendX2 = x2;
fLegendY2 = y2;
}
//________________________________________________________
void GFHistManager::SetLegendX1(Double_t x1) {fLegendX1 = x1;}
//________________________________________________________
void GFHistManager::SetLegendY1(Double_t y1) {fLegendY1 = y1;}
//________________________________________________________
void GFHistManager::SetLegendX2(Double_t x2) {fLegendX2 = x2;}
//________________________________________________________
void GFHistManager::SetLegendY2(Double_t y2) {fLegendY2 = y2;}
//________________________________________________________
void GFHistManager::SetNumHistsX(UInt_t numX)
{
for(Int_t i = 0; i < fDepth; ++i){
fNoX[i] = numX;
}
}
//________________________________________________________
void GFHistManager::SetNumHistsX(UInt_t numX, Int_t layer)
{
if(this->CheckDepth("SetNumHistsX", layer, kFALSE)) {
fNoX[layer] = numX;
}
}
//________________________________________________________
void GFHistManager::SetNumHistsY(UInt_t numY)
{
for(Int_t i = 0; i < fDepth; ++i){
fNoY[i] = numY;
}
}
//________________________________________________________
void GFHistManager::SetNumHistsY(UInt_t numY, Int_t layer)
{
if(this->CheckDepth("SetNumHistsY", layer, kFALSE)) {
fNoY[layer] = numY;
}
}
//________________________________________________________
void GFHistManager::SetNumHistsXY(UInt_t numX, UInt_t numY)
{
this->SetNumHistsX(numX);
this->SetNumHistsY(numY);
}
//________________________________________________________
void GFHistManager::SetNumHistsXY(UInt_t numX, UInt_t numY, Int_t layer)
{
this->SetNumHistsX(numX, layer);
this->SetNumHistsY(numY, layer);
}
//________________________________________________________
void GFHistManager::SetLogY(Bool_t yesNo)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetLogY(i);
}
}
//________________________________________________________
void GFHistManager::SetLogY(Int_t layer, Bool_t yesNo)
{
if(this->CheckDepth("SetLogY", layer, kFALSE)) {
fLogY[layer] = yesNo ? 1 : 0;
if(layer < fCanArrays->GetEntriesFast()) {
this->Update(layer); // if canvas already drawn
}
}
}
//________________________________________________________
void GFHistManager::SetHistsOption(Option_t* option)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsOption(option, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsOption(Option_t* option, Int_t layer)
{
if(!this->CheckDepth("SetHistsOption", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
TString opt(option); opt.ToLower();
if(!hist->InheritsFrom(TH2::Class()) && opt.Contains("box")){
opt.ReplaceAll("box",0);
}
hist->SetOption(opt);
}
}
}
//________________________________________________________
void GFHistManager::SetHistsMinMax(Double_t minMax, Bool_t min)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsMinMax(minMax, min, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsMinMax(Double_t minMax, Bool_t min, Int_t layer)
{
if(!this->CheckDepth("SetHistsMinMax", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
if(min) hist->SetMinimum(minMax);
else hist->SetMaximum(minMax);
}
}
if(layer < fCanArrays->GetEntriesFast()) {
this->Update(layer); // if canvas already drawn
}
}
//________________________________________________________
void GFHistManager::AddHistsOption(Option_t* option)
{
for(Int_t i = 0; i < fDepth; ++i){
this->AddHistsOption(option, i);
}
}
//________________________________________________________
void GFHistManager::AddHistsOption(Option_t* option, Int_t layer)
{
// if 'layer' exists, add 'option' to all hists so far existing in this layer
// (ignore option 'box' for 1-D histograms)
if(!this->CheckDepth("AddHistsOption", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
TString opt(option); opt.ToLower();
if(!hist->InheritsFrom(TH2::Class()) && opt.Contains("box",TString::kIgnoreCase)){
opt.ReplaceAll("box",0);
}
hist->SetOption(opt += hist->GetOption());
}
}
}
//________________________________________________________
void GFHistManager::SetHistsXTitle(const char* title)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsXTitle(title, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsXTitle(const char* title, Int_t layer)
{
if(!this->CheckDepth("SetHistsXTitle", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
hist->SetXTitle(title);
}
}
}
//________________________________________________________
void GFHistManager::SetHistsYTitle(const char* title)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsYTitle(title, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsYTitle(const char* title, Int_t layer)
{
if(!this->CheckDepth("SetHistsYTitle", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr);// arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
hist->SetYTitle(title);
}
}
}
//________________________________________________________
void GFHistManager::SetHistsFillColor(Color_t color)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsFillColor(color, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsFillColor(Color_t color, Int_t layer)
{
if(!this->CheckDepth("SetHistsFillColor", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
hist->SetFillColor(color);
}
}
}
//________________________________________________________
void GFHistManager::SetHistsLineWidth(Width_t width)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsLineWidth(width, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsLineWidth(Width_t width, Int_t layer)
{
if(!this->CheckDepth("SetHistsLineWidth", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
hist->SetLineWidth(width);
}
}
}
//________________________________________________________
void GFHistManager::SetHistsLineStyle(Int_t s)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsLineStyle(s, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsLineStyle(Int_t s, Int_t layer, Int_t numHistInPad)
{
// sets style 's' toall hists in 'layer'.
// if numHistInPad >= 0: only the given histNum in each pad is changed in style
// (default is numHistInPad = -1)
if(!this->CheckDepth("SetHistsLineStyle", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(GFHistArray* arr = static_cast<GFHistArray*>(iter2.Next())){
if(numHistInPad < 0 || numHistInPad >= arr->GetEntriesFast()){ // all hist in pad
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
hist->SetLineStyle(s);
}
} else {
(*arr)[numHistInPad]->SetLineStyle(s);
}
}
}
//________________________________________________________
void GFHistManager::SetHistsLineColor(Color_t color)
{
for(Int_t i = 0; i < fDepth; ++i){
this->SetHistsLineColor(color, i);
}
}
//________________________________________________________
void GFHistManager::SetHistsLineColor(Color_t color, Int_t layer)
{
if(!this->CheckDepth("SetHistsLineColor", layer, kFALSE)) return;
TIter iter2(static_cast<TObjArray*>(fHistArrays->At(layer)));
while(TObjArray* arr = static_cast<TObjArray*>(iter2.Next())){
TIter iter(arr); // arr is GFHistArray* !
while(TH1* hist = static_cast<TH1*>(iter.Next())){
hist->SetLineColor(color);
}
}
}
//________________________________________________________
Bool_t GFHistManager::CheckDepth(const char* method, Int_t layer,
Bool_t mayExpand)
{
// true, if layer is possible, if (mayExpand) expands to layer >= 0
if(layer < 0){
this->Warning("CheckDepth", "Layer below 0 (%d) called in '%s'!",
layer, method);
return kFALSE;
}
if(layer > fDepth-1){
if(mayExpand) {
this->ExpandTo(layer);
return kTRUE;
} else {
this->Warning("CheckDepth", "Layer %d called in '%s', max. is %d",
layer, method, fDepth-1);
return kFALSE;
}
}
return kTRUE;
}
//________________________________________________________
void GFHistManager::ExpandTo(Int_t layer)
{
if(layer+1 <= fDepth){
this->Error("ExpandTo",
"Shrinking forbidden, fDepth = %d, should expand to = %d",
fDepth, layer+1);
return;
}
fNoX.Set(layer+1);
fNoY.Set(layer+1);
fLogY.Set(layer+1);
for(Int_t i = fDepth; i <= layer; ++i){
fNoX[i] = kDefaultPadsPerCanX;
fNoY[i] = kDefaultPadsPerCanY;
fLogY[i]= 0;
fHistArrays->AddAtAndExpand(new TObjArray, i);
fCanArrays->AddAtAndExpand(new TObjArray, i);
}
fDepth = layer+1;
}
//________________________________________________________
Bool_t GFHistManager::CheckHistNum(const char* method, Int_t layer,
Int_t histNum, Bool_t mayExpand)
{
// true if hist 'histNum' exists in 'layer'
// if(mayExpand == kTRUE) expands to this size if necessary! (default: kFALSE)
if(!this->CheckDepth(method, layer, mayExpand)) return kFALSE;
TObjArray * layerArr = static_cast<TObjArray*>(fHistArrays->At(layer));
if(histNum < 0) {
this->Warning("CheckHistNum", "histogram number %d requested!", histNum);
return kFALSE;
}
while(histNum >= layerArr->GetEntriesFast()){
if(mayExpand){
layerArr->AddAtAndExpand(new GFHistArray, layerArr->GetEntriesFast());
} else {
this->Warning("CheckHistNum", "layer %d has only %d histograms, number %d requested!",
layer, layerArr->GetEntriesFast(), histNum);
return kFALSE;
}
}
return kTRUE;
}
//________________________________________________________
TObjArray* GFHistManager::MakeLegends(Int_t layer)
{
// returns array of legends of 'layer' (to be called if 'layer' really exist!)
// creates if necessary
if(!fLegendArrays) fLegendArrays = new TObjArray(fDepth);
if(layer > fLegendArrays->GetLast() || !fLegendArrays->At(layer)) {
fLegendArrays->AddAtAndExpand(new TObjArray, layer);
}
return static_cast<TObjArray*>(fLegendArrays->At(layer));
}
//________________________________________________________
TList* GFHistManager::MakeObjList(Int_t layer, Int_t histoNum)
{
// return list of objects to be drawn upon hists in pad histoNum of 'layer'
// (to be called if 'layer' really exist!)
if(!fObjLists) fObjLists = new TObjArray(fDepth);
if(layer > fObjLists->GetLast() || !fObjLists->At(layer)){
fObjLists->AddAtAndExpand(new TObjArray(this->GetNumHistsOf(layer)),layer);
}
TObjArray* layerLists = static_cast<TObjArray*>(fObjLists->At(layer));
if(histoNum > layerLists->GetLast() || !layerLists->At(histoNum)){
layerLists->AddAtAndExpand(new TList, histoNum);
}
return static_cast<TList*>(layerLists->At(histoNum));
}
//________________________________________________________
GFHistArray* GFHistManager::GetHistsOf(Int_t layer, Int_t histNum, Bool_t mayExpand)
{
// returns array of histograms for pad 'histNum' of 'layer'
// if(mayExpand) creates if necessary!
if(!this->CheckHistNum("GetHistsOf", layer, histNum, mayExpand)) return NULL;
TObjArray* layerHists = static_cast<TObjArray*>(fHistArrays->At(layer));
return static_cast<GFHistArray*>(layerHists->At(histNum));
}
//________________________________________________________
TList* GFHistManager::GetObjectsOf(Int_t layer, Int_t histNo)
{
if(!this->CheckHistNum("GetObjectsOf", layer, histNo, kFALSE)) return NULL;
if(fObjLists && layer <= fObjLists->GetLast() && fObjLists->At(layer)){
TObjArray* layerLists = static_cast<TObjArray*>(fObjLists->At(layer));
if(histNo <= layerLists->GetLast() && layerLists->At(histNo)){
return static_cast<TList*>(layerLists->At(histNo));
}
}
return NULL;
}
//________________________________________________________
Int_t GFHistManager::GetNumHistsOf(Int_t layer)
{
if(!this->CheckDepth("GetNumHistsOf", layer, kFALSE)) return 0;
TObjArray* layerHists = static_cast<TObjArray*>(fHistArrays->At(layer));
if(layerHists) return layerHists->GetEntriesFast();
return 0;
}
//________________________________________________________
TLegend* GFHistManager::GetLegendOf(Int_t layer, Int_t histoNum)
{
// if it already exists!
if(!this->CheckHistNum("AddLegend", layer, histoNum)) return NULL;
TObjArray* legendsOfLayer = this->MakeLegends(layer);
TLegend* legend = (legendsOfLayer->GetSize() < histoNum ?
NULL : static_cast<TLegend*>(legendsOfLayer->At(histoNum)));
return legend;
}
//________________________________________________________
void GFHistManager::MakeDifferentStyle(GFHistArray* hists)
{
// easy version: adjust the histogram lines to colors
// kBlack, kRed, kGreen, kBlue, kYellow, kMagenta, kCyan (c.f. $ROOTSYS/include/Gtypes.h)
// 1 2 3 4 5 6 7 (skip 3 and 5: kGreen hardly visible...)
// (... kYellow dito)
// also set line style, set marker color to line color
Color_t color = 0;
for(Int_t i = 0; i < hists->GetEntriesFast(); ++i){
// Color_t color = i+1;
++color;
Style_t style = i+1;
while(style > 4) style -= 4;
if(color == 3) ++color; //omit kGreen
if(color == 5) ++color; // and kYellow
if(color > 7 ) {
::Error("GFHistManager::MakeDifferentStyle", "Out of colors");
break;
}
(*hists)[i]->SetLineColor(color);
(*hists)[i]->SetMarkerColor(color);
(*hists)[i]->SetLineStyle(style);
}
}
//________________________________________________________
Double_t GFHistManager::MaxOfHist(const TH1* h) const
{
// Take bin with max content, adds error and returns (no *1.05 applied!),
// but cares that - together with an error bar - another bin might be higher...
// If the hists option contains nothing about errors: error is NOT added!
TString option = h->GetOption();
option.ToLower();
option.ReplaceAll("same", 0);
Int_t maxBin = h->GetMaximumBin();
Double_t result = h->GetBinContent(maxBin);
if(option.Contains('e') || (h->GetSumw2N() && !option.Contains("hist"))){
for(Int_t bin = 1; bin <= h->GetNbinsX(); ++bin){ //FIXME: for 2/3D: loop over y/z!
result = TMath::Max(result, (h->GetBinContent(bin) + h->GetBinError(bin)));
}
}
return result;
}
//________________________________________________________
Double_t GFHistManager::MaxOfHists(const TObjArray* hists) const
{
Double_t result = 0.;
TIter nextHist(hists);
while(TObject* hist = nextHist()){
if(hist->InheritsFrom(TH1::Class())){
result = TMath::Max(result, this->MaxOfHist(static_cast<TH1*>(hist)));
} else {
this->Warning("MaxOfHists", "Entry in input array is not a histogram!");
}
}
return result;
}
//________________________________________________________
Double_t GFHistManager::MinOfHists(const TObjArray* hists) const
{
Double_t result = DBL_MAX;
TIter nextHist(hists);
while(TObject* hist = nextHist()){
if(hist->InheritsFrom(TH1::Class())){
result = TMath::Min(result, static_cast<TH1*>(hist)->GetMinimum());
} else {
this->Warning("MinOfHists", "Entry in input array is not a histogram!");
}
}
return result;
}
//________________________________________________________
TCanvas* GFHistManager::GetCanvas(Int_t layer, Int_t number)
{
// after draw!!
if(!fCanArrays || fCanArrays->GetEntriesFast() <= layer) return NULL;
TObjArray* cans = static_cast<TObjArray*>(fCanArrays->At(layer));
if(cans && cans->GetEntriesFast() > number){
return static_cast<TCanvas*>(cans->At(number));
}
return NULL;
}
//________________________________________________________
Int_t GFHistManager::GetNumHistsX(Int_t layer) const
{
if(layer >= 0 && layer < fDepth) return fNoX[layer];
else return 0;
}
//________________________________________________________
Int_t GFHistManager::GetNumHistsY(Int_t layer) const
{
if(layer >= 0 && layer < fDepth) return fNoY[layer];
else return 0;
}
//________________________________________________________
void GFHistManager::GetLegendX1Y1X2Y2(Double_t& x1, Double_t& y1,
Double_t& x2, Double_t& y2) const
{
x1 = fLegendX1;
y1 = fLegendY1;
x2 = fLegendX2;
y2 = fLegendY2;
}
//________________________________________________________
void GFHistManager::DrawFuncs(const TH1* hist) const
{
// calls Draw("SAME") for all TF1 in hist's GetListOfFunctions if necessary
if(!hist || !TString(hist->GetOption()).Contains("HIST", TString::kIgnoreCase)) return;
TIter nextprim(hist->GetListOfFunctions());
while(TObject* next = nextprim()){
if(next->InheritsFrom(TF1::Class())){
next->Draw("SAME");
}
}
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.