//_HADES_CLASS_DESCRIPTION 
////////////////////////////////////////////////////////////////////////////////
//
// Peter's Tools
// 
//            Author: Peter W. Zumbruch
//           Contact: P.Zumbruch@gsi.de
//           Created: Mar 21, 2002
// 
// File: $RCSfile: ptools.cc,v $ 
// Version: $Revision: 1.75 $
// Modified by $Author: halo $ on $Date: 2006/08/12 13:05:25 $  
////////////////////////////////////////////////////////////////////////////////

using namespace std;

#include <cstdio>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>

#include "TArrayC.h"
#include "TArrayD.h"
#include "TArrayF.h"
#include "TArrayI.h"
#include "TArrayL.h"
#include "TArrayS.h"
#include "TApplication.h"
#include "TAxis.h"
#include "TCanvas.h"
#include "TEllipse.h"
#include "TError.h"
#include "TFile.h"
#include "TGaxis.h"
#include "TGraphErrors.h"
#include "TH1.h"
#include "TH2.h"
#include "TH3.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TH3D.h"
#include "THashList.h"
#include "THStack.h"
#include "TLatex.h"
#include "TLegend.h"
#include "TLegendEntry.h"
#include "TLine.h"
#include "TMath.h"
#include "TObject.h"
#include "TObjString.h"
#include "TPaveText.h"
#include "TPad.h"
#include "TROOT.h"
#include "TStopwatch.h"
#include "TSystem.h"
#include "TString.h"
#include "TStyle.h"
#include "TTree.h"
#include "TUnixSystem.h"

#include "ptools.h"
#include <cmath>

ClassImp(PTools)

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(TCanvas *canv, 
				 Int_t xpads, 
				 Int_t ypads) 
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // returns pointer to pad of divided TPad

  TString title;
  if (canv) title = canv->GetTitle();
  else title ="";

  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title.Data(), (Char_t*)0, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(TCanvas *canv, 
			       Int_t xpads, 
			       Int_t ypads,			       
			       const Char_t * title) 
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // returns pointer to pad of divided TPad
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, (Char_t*)0, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(TCanvas *canv, 
			       Int_t xpads, 
			       Int_t ypads,			       
			       const Char_t * title,
			       const Char_t * filename) 
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // returns pointer to pad of divided TPad
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(TCanvas *canv, 
			       Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries)
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // returns pointer to pad of divided TPad

  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, nentries,(TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(TCanvas *canv,
			       Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename,
			       Int_t nentries, 
			       const Char_t * info)
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad

  TPaveText *infotext = new TPaveText(0,0,1,1);
  infotext->SetTextSize(10);
  infotext->AddText(info);
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, nentries, infotext );
};

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(TCanvas *canv, 
			       Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries, 
			       const TString info)
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad

  return (!canv) ? NULL : getDividedSubPad(canv , xpads, ypads, title, filename, nentries, info.Data());
};

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,
			       Int_t xsize, Int_t ysize) 
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(canv->GetName());

  TString title;

  if (canv) title = canv->GetTitle();
  else title ="";

  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title.Data(), (Char_t*)0, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,
			       Int_t xsize, Int_t ysize,
			       const Char_t * title) 
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // adds a header with title 
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(title);

  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, (Char_t*)0, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,	
			       Int_t xsize, Int_t ysize,		       
			       const Char_t * title,
			       const Char_t * filename) 
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(title);
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,
			       Int_t xsize, Int_t ysize, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries)
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(title);
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, nentries,(TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,
			       Int_t xsize, Int_t ysize, 
			       const Char_t * title, 
			       const Char_t * filename,
			       Int_t nentries, 
			       const Char_t * info)
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(title);
  TPaveText *infotext = new TPaveText(0,0,1,1);
  infotext->SetTextSize(10);
  infotext->AddText(info);
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, nentries, infotext );
};

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
 			       Int_t ypads,
			       Int_t xsize, Int_t ysize, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries, 
			       const TString info)
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(title);
  return (!canv) ? NULL : getDividedSubPad(canv , xpads, ypads, title, filename, nentries, info.Data());
};
////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
 			       Int_t ypads,
			       Int_t xsize, Int_t ysize, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries, 
			       TPaveText *info)
{
  // divides new canvas mycanvas of size xsizy * ysize 
  // into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetWindowSize(xsize,ysize);
  canv->Resize();
  canv->SetTitle(title);
  return (!canv) ? NULL : getDividedSubPad(canv , xpads, ypads, title, filename, nentries, info);
};

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads) 
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetTitle(canv->GetName());

  TString title;

  if (canv) title = canv->GetTitle();
  else title ="";

  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title.Data(), (Char_t*)0, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,			       
			       const Char_t * title) 
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetTitle(title);

  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, (Char_t*)0, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads,			       
			       const Char_t * title,
			       const Char_t * filename) 
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetTitle(title);
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, 0, (TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries)
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetTitle(title);
  return getDividedSubPad(canv, xpads, ypads, title, filename, nentries,(TPaveText*)0 );
}

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename,
			       Int_t nentries, 
			       const Char_t * info)
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetTitle(title);
  TPaveText *infotext = new TPaveText(0,0,1,1);
  infotext->SetTextSize(10);
  TString str(info);
  while(str.Length() != 0)
    {
      if (str.First("/n") != str.Length())
	{
	  infotext->AddText((str(0,str.First("/n")-1)).Data());
	  str=str(str.First("/n")+1,str.Length());
	}
      else
	{
	  infotext->AddText(info);
	  str="";
	}
    }
  return (!canv) ? NULL : getDividedSubPad(canv, xpads, ypads, title, filename, nentries, infotext );
};

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries, 
			       const TString info)
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use

  TCanvas *canv = new TCanvas();
  canv->SetTitle(title);
  return getDividedSubPad(canv , xpads, ypads, title, filename, nentries, info.Data());
};

////////////////////////////////////////////////////////////////////////////////

 TPad* PTools::getDividedSubPad(Int_t xpads, 
			       Int_t ypads, 
			       const Char_t * title, 
			       const Char_t * filename, 
			       Int_t nentries, 
			       TPaveText *info)
{
  // divides new canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad
  // memory leak! only for CINT use
  
  TCanvas *canv = new TCanvas();
  canv->SetTitle(title);
  return (!canv) ? NULL : getDividedSubPad(canv , xpads, ypads, title, filename, nentries, info);
};

////////////////////////////////////////////////////////////////////////////////
 TPad* PTools::getDividedSubPad(TCanvas   *mycanvas,
			       Int_t      xpads, 
			       Int_t      ypads, 
			       const Char_t  *titlehead, 
			       const Char_t  *mytextfilename, 
			       Int_t      nentries, 
			       TPaveText *info)
{
  // divides given canvas mycanvas into xpad times ypads pads 
  // adds a header with title 
  // containing filename and 
  // number of entries
  // creates an info box at the right of the canvas
  // returns pointer to pad of divided TPad

  if (!mycanvas) return NULL;

  Char_t name[200];
  mycanvas->cd();
  sprintf(name,"%s_header",gPad->GetName());
  mycanvas->SetFillColor(0);
  
  TPad *mycanvas_header = new TPad(name,name,0.01,0.95,0.99,0.99);
  mycanvas_header->Draw();
  mycanvas_header->cd();
  
  printHeader(titlehead,mytextfilename,nentries,mycanvas_header);
  
  mycanvas->cd();
  
  TPad *mycanvas_body;
  
  if (info)
    {
      sprintf(name,"%s_info",gPad->GetName());
      TPad *mycanvas_info = new TPad(name,name,0.80,0.01,0.99,0.94);
      mycanvas_info->Draw();
      mycanvas_info->cd();
      gPad->SetFillStyle(4000);
      
      info->SetX1NDC(0.051);
      info->SetY1NDC(0.02);
      info->SetX2NDC(0.95);
      info->SetY2NDC(0.98);
      info->SetTextSize(0.08);
      info->SetBorderSize(0);
//       while (info->GetListOfLines()->LastIndex() < 2*(Int_t)((1/info->GetTextSize())-2)) info->AddText(" ");
      info->SetFillColor(0);
      info->Draw();
      
      mycanvas->cd();
      
      sprintf(name,"%s_body",gPad->GetName());
      
      mycanvas_body = new TPad(name,name,0.01,0.01,0.79,0.94);
    }
  else 
    {
      sprintf(name,"%s_body",gPad->GetName());
      mycanvas_body = new TPad(name,name,0.01,0.01,0.99,0.94);
    }
  
  mycanvas_body->Draw();
  mycanvas_body->cd();
  gPad->SetFillStyle(4000);
  
  if (xpads > 1 || ypads > 1) 
    {
      mycanvas_body->Divide(xpads,ypads);
      mycanvas_body->cd(1);
    }

  return mycanvas_body;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::printHeader(const Char_t *titlehead, const Char_t *mytextfilename, Int_t nentries, TPad *parentPad)
{
  // prints header of canvas containing in the parent pad
  // header contains filename and number of entries
 
  if (!parentPad) gPad->cd();
  else parentPad->cd();

  const TDatime daytime;
  Char_t texText[200];

  sprintf(texText,"%s",(titlehead)?titlehead:" ");
  TLatex *tex = new TLatex(0.01,0.15,texText);
  tex->SetTextSize(0.35);
  tex->SetLineWidth(2);
  tex->Draw();

  if (mytextfilename!=0 && nentries!=0)
    {
      sprintf(texText,"%i Events - File %s",nentries,mytextfilename);
    }
  else if (nentries==0 && mytextfilename==0)
    {
      sprintf(texText," ");
    }
  else if (nentries==0 && mytextfilename!=0)
    {
      sprintf(texText,"File %s",mytextfilename);
    }
  else 
    {
      sprintf(texText,"%i Events",nentries);
    }

  TLatex *tex2 = new TLatex(0.01,0.6,texText);
  tex2->SetTextSize(0.35);
  tex2->SetLineWidth(2);
  tex2->Draw();
  
  sprintf(texText,"%s",daytime.AsSQLString());

  TLatex *tex3 = new TLatex(0.85,0.15,texText);
  tex3->SetTextSize(0.35);
  tex3->SetLineWidth(2);
  tex3->Draw();

  return;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::evalStopwatch(TStopwatch *timer, Int_t nevts)
{
  // evaluates Stopwatch for given number of events 
  // also plots the machine where it was running on
  
  Double_t realtime=(*timer).RealTime();
  Double_t cputime =(*timer).CpuTime();
  Int_t    realHour=(Int_t) ((realtime/3600));
  Int_t    realMin =(Int_t) (((realtime-realHour*3600)/60));
  Int_t    realSec =(Int_t) ((realtime-realHour*3600-realMin*60));
  Int_t    realmSec=(Int_t) (((realtime - (Int_t) (realtime-realHour*3600-realMin*60))*1000));
  Int_t     cpuHour=(Int_t) (( cputime/3600));
  Int_t     cpuMin =(Int_t) ((( cputime- cpuHour*3600)/60));
  Int_t     cpuSec =(Int_t) (( cputime- cpuHour*3600- cpuMin*60));
  Int_t     cpumSec=(Int_t) ((( cputime - (Int_t) ( cputime- cpuHour*3600- cpuMin*60))*1000));
  
  printf("------------------------------------------------------n");
  printf("Events processed: %in",nevts);  
  printf("Real time(hh:mm:ss.ms): %02i:%02i:%02i.%03in",
	 realHour,realMin,realSec,realmSec);
  printf("Cpu time (hh:mm:ss.ms): %02i:%02i:%02i.%03in", 
	 cpuHour, cpuMin, cpuSec, cpumSec);
  if (nevts && cputime >0) printf("cpu  Performance: %f s/ev or %f.2 ev/s n",(float) ( cputime/nevts),(float) (nevts/ cputime));
  if (nevts && realtime>0) printf("real Performance: %f s/ev or %f.2 ev/s n",(float) (realtime/nevts),(float) (nevts/realtime));
  gSystem->Exec("cat /proc/cpuinfo | perl -ne 'print if(/cpu MHz/i || /model name/i )'");
  return;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setTitleArts( TH1* histogramm, const Char_t *xtitle, const Char_t *ytitle, TString color, int type)
{
  // sets titles of x axis, y axis, fill color and font type for histogramm
  // with colors "black","red","bright green","bright blue","yellow","hot pink","aqua","green","blue","default"

  const TString col[11]={"","black","red","bright green","bright blue","yellow","hot pink","aqua","green","blue","default"};

  color.ToLower();
  int i;
  for (i = 1; i <= 10; i++)
    {
      if (color.CompareTo(col[i])==0) break;
    }
  if (i==11) 
    {
      Info("setTitleArts","no valid name for color chosen %s ... setting to default: %s",color.Data(),col[4].Data());
      i=4;
    }

  setTitleArts( histogramm, xtitle, ytitle, i , type);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setTitleArts( TH1* histogramm, const TString xtitle, const TString ytitle, TString color, int type)
{
  // sets titles of x axis, y axis, fill color and font type for histogramm
  // with colors "black","red","bright green","bright blue","yellow","hot pink","aqua","green","blue","default"
  setTitleArts( histogramm, xtitle.Data(), ytitle.Data(), color, type);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setTitleArts( TH1* histogramm, const TString xtitle, const TString ytitle, 
			   Int_t fillColor, Int_t titleFont)
{
  // sets titles of x axis, y axis, fill color and font type for histogramm
  setTitleArts( histogramm, xtitle.Data(), ytitle.Data(), fillColor, titleFont);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setTitleArts( TH1* histogramm, const Char_t *xtitle, const Char_t * ytitle, 
			   Int_t fillColor, Int_t titleFont)
{
  // sets titles of x axis, y axis, fill color and font type for histogramm
  // with colors "black","red","bright green","bright blue","yellow","hot pink","aqua","green","blue","default"

  histogramm->SetXTitle(xtitle);
  histogramm->SetYTitle(ytitle);
  if (fillColor >= 0 ) histogramm->SetFillColor(fillColor);
  ((TAxis*)histogramm->GetXaxis())->CenterTitle();
  ((TAxis*)histogramm->GetXaxis())->SetTitleFont(titleFont);
  ((TAxis*)histogramm->GetXaxis())->SetTitleColor(1);
  ((TAxis*)histogramm->GetXaxis())->SetTitleOffset(1.2);
  ((TAxis*)histogramm->GetYaxis())->SetTitleFont(titleFont);
  ((TAxis*)histogramm->GetYaxis())->SetTitleOffset(1.2);
  ((TAxis*)histogramm->GetYaxis())->SetTitleColor(1);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setTitleArts( THStack* histogrammStack, const TString xtitle, const TString ytitle, 
			   Int_t titleFont)
{
  // sets titles of x axis, y axis, font type for histogramm for histogramm stack
  
  setTitleArts( histogrammStack, xtitle.Data(), ytitle.Data(), titleFont);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setTitleArts( THStack* histogrammStack, const Char_t *xtitle, const Char_t * ytitle, 
			   Int_t titleFont)
{
  // sets titles of x axis, y axis, font type for histogramm for histogramm stack
  
  ((TAxis*)histogrammStack->GetXaxis())->SetTitle(xtitle);
  ((TAxis*)histogrammStack->GetYaxis())->SetTitle(ytitle);
  ((TAxis*)histogrammStack->GetXaxis())->CenterTitle();
  ((TAxis*)histogrammStack->GetXaxis())->SetTitleFont(titleFont);
  ((TAxis*)histogrammStack->GetXaxis())->SetTitleOffset(1.2);
  ((TAxis*)histogrammStack->GetYaxis())->SetTitleFont(titleFont);
  //  ((TAxis*)histogrammStack->GetYaxis())->SetTitleOffset(1.2);
}

////////////////////////////////////////////////////////////////////////////////

 TCanvas* PTools::drawCanvas(const Char_t * name, 
			    const Char_t * title, 
			    TH1 **histarray, 
			    Int_t xsize, 
			    Int_t ysize)
{
  // draws default canvas divided xsize times ysize and fills it with the contents of histarray[i] at pad(i) using plot option
  // only useful for 6 pads!!
#ifndef __CINT__
  static Int_t calls;
#else
  Int_t calls=0;
#endif

  TCanvas *canv = new TCanvas(name,title,0+calls*25,0+calls*25,1000,800);

  canv->Divide(xsize,ysize);

  for (Int_t time=0 ;time  < 6 ; time++)
    {
      canv->cd(time+1);
      if (histarray[time]->GetEntries()>0)
	{
	  histarray[time]->DrawCopy();
	  gPad->SetLogy();
	}
      else delete gPad;
    }
  
  calls++;
  return canv;
}

////////////////////////////////////////////////////////////////////////////////

 TCanvas* PTools::draw32Canvas(const Char_t * name, const Char_t * title, TH1F *histarray[])
{
  // draws default canvas divided 3 times 2 and fills it with the contents of histarray[i] at pad(i) using plot option

#ifndef __CINT__
  static Int_t calls;
#else
  Int_t calls=0;
#endif

  TCanvas *canv = new TCanvas(name,title,0+calls*25,0+calls*25,1000,800);
  canv->Divide(3,2);

  for (Int_t time=0 ;time  < 6 ; time++)
    {
      canv->cd(time+1);
      if (histarray[time]->GetEntries()>0)
	{
	  histarray[time]->DrawCopy();
	  gPad->SetLogy();
	}
      else delete gPad;
    }
  
  calls++;
  return canv;
}

////////////////////////////////////////////////////////////////////////////////

 TCanvas* PTools::draw32CanvasTH2(const Char_t * name, const Char_t * title, TH2F *histarray[], const Char_t * option)
{
  // draws default canvas divided 3 times 2 and fills it with the contents of histarray[i] at pad(i) using plot option "option"

#ifndef __CINT__
  static Int_t calls;
#else
  Int_t calls=0;
#endif

  TCanvas *canv = new TCanvas(name,title,0+calls*25,0+calls*25,1000,800);
  canv->Divide(3,2);

  for (Int_t time=0 ;time  < 6 ; time++)
    {
      canv->cd(time+1);

      if (histarray[time]->GetEntries()>0)
	{
	  if (!option) histarray[time]->DrawCopy();
	  else histarray[time]->DrawCopy(option);
	  //gPad->SetLogz();
	}
      else {}// delete gPad;
    }
  
  calls++;
  return canv;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::cutEnd(Char_t * infi, Char_t * end)
{
  // cuts from infi end from the end

  Char_t textfile[200];
  sprintf(textfile,"tempvar="%s" ; echo ${tempvar%%%s}",infi,end);
  Char_t *tmp = myexec(textfile);
  sprintf(infi,"%s",myexec(textfile));
  delete[] tmp;
}

////////////////////////////////////////////////////////////////////////////////

 char * PTools::myexec(char * in)
{
  // executes command in
  // and returns char pointer to result string
  // user have to delete return string

  Char_t *tmp = new Char_t[1000];
  Char_t textfile[1000];
  FILE *pipe = gSystem->OpenPipe(in,"r");
  fscanf(pipe,"%s",textfile);
  gSystem->ClosePipe(pipe);
  sprintf(tmp,"%s",textfile);
  return tmp;
}

////////////////////////////////////////////////////////////////////////////////

 TString PTools::myexec(TString in)
{
  // executes command in
  // and returns char pointer to result string
  // user have to delete return string

  const char* tmp = myexec(in.Data());
  TString st(tmp);
  delete tmp;
  return TString(st);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::mdb(int called)
{
  // small minidebug message, with increasing static counter
  // prints out called if called different from -1
  // useful example
  // PTools::mdb(__LINE__)

  static int call;
  if (called==-1)
    {
      call++;
      cerr << "here" << call << endl;
    }
  else cerr << "here" << called << endl;
  return;
}

////////////////////////////////////////////////////////////////////////////////

 TDirectory *PTools::Mkdir(TDirectory *dirOld, 
			  const Char_t *newDirName, 
			  Int_t index, 
			  Int_t precision)    //! Makes new Dir, changes to Dir, returns pointer to new Dir
{
  // Function to create subdirectories
  // of dirOld with name newDirName
  // if index differs from -99 then index is attached to the name with the precision of precision
  // changes to the new created directory
  // returns the pointer to the new directory 
  //Thanks to J.Kempter (J.Markert)

  dirOld->cd();

  TString newName(newDirName);
  
  while (newName.Contains("/"))
  {
    TString directory = newName;
    Int_t pos = directory.First("/");
    PTools::Mkdir(gDirectory,directory.Remove(pos));
    newName = newName(pos+1,newName.Length()-pos-1).Data();
    dirOld=gDirectory;
  }
  
  static Char_t sDir[255];
  static Char_t sFmt[10];
  if (index!=-99) 
    {
      sprintf(sFmt, "%%s %%0%1ii", precision);
      sprintf(sDir, sFmt, newName.Data(), index);
    }
  else 
    {
      sprintf(sFmt, "%%s");
      sprintf(sDir, sFmt, newName.Data());
    }
  TDirectory *dirNew;
  if (!dirOld->FindKey(sDir)) 
    {
      dirNew = dirOld->mkdir(sDir);
    }
  else 
    {
      dirNew = (TDirectory *) dirOld->Get(sDir);
    }
  dirOld->cd(sDir);
  return dirNew;
}

////////////////////////////////////////////////////////////////////////////////

 TDirectory *PTools::Mkdir(TDirectory *dirOld,
			  const TString newDirName, 
			  Int_t index, 
			  Int_t precision)    //! Makes new Dir, changes to Dir, returns pointer to new Dir
{
  // see:   PTools::Mkdir(TDirectory *dirOld, const Char_t *newDirName, Int_t index, Int_t precision 
  return Mkdir(dirOld, newDirName.Data(), index, precision);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::getHistogramLimits(TH1* hist, 
				Int_t& nbinsx  , Axis_t& xmin  , Axis_t& xmax, 
				Int_t& nbinsy  , Axis_t& ymin  , Axis_t& ymax,
				Int_t& nbinsz  , Axis_t& zmin  , Axis_t& zmax)
{
  // returns the limits of hist

  getHistogramLimits(hist, nbinsx, xmin, xmax, nbinsy, ymin, ymax);
  if (nbinsz) nbinsz = hist->GetNbinsZ();
  if (zmin  ) zmin   = hist->GetZaxis()->GetXmin();
  if (zmax  ) zmax   = hist->GetZaxis()->GetXmax();
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::getHistogramLimits(TH1* hist, 
				Int_t& nbinsx  , Axis_t& xmin  , Axis_t& xmax, 
				Int_t& nbinsy  , Axis_t& ymin  , Axis_t& ymax)
{
  // returns the limits of hist

  //   if (nbinsx) nbinsx = hist->GetNbinsX();
  //   if (xmin  ) xmin   = hist->GetXaxis()->GetXmin();
  //   if (xmax  ) xmax   = hist->GetXaxis()->GetXmax();
  getHistogramLimits(hist, nbinsx, xmin, xmax);
  if (nbinsy) nbinsy = hist->GetNbinsY();
  if (ymin  ) ymin   = hist->GetYaxis()->GetXmin();
  if (ymax  ) ymax   = hist->GetYaxis()->GetXmax();

}

////////////////////////////////////////////////////////////////////////////////

 void PTools::getHistogramLimits(TH1* hist, 
				Int_t& nbinsx  , Axis_t& xmin  , Axis_t& xmax)
{
  // returns the limits of hist

  if (nbinsx) nbinsx = hist->GetNbinsX();
  if (xmin  ) xmin   = hist->GetXaxis()->GetXmin();
  if (xmax  ) xmax   = hist->GetXaxis()->GetXmax();
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::printHistogramLimits(TH1* hist)
{
  // prints the limits of hist

  Int_t nbinsx;
  Axis_t xmin, xmax;

  getHistogramLimits(hist, nbinsx, xmin, xmax);
  printf("nbinsx: %i nxmin: t %f nxmax: t %fn",nbinsx, xmin, xmax);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::printHistogramLimits(TH2* hist)
{
  // prints the limits of hist

  Int_t nbinsx, nbinsy;
  Axis_t xmin, xmax, ymin, ymax;

  getHistogramLimits(hist, nbinsx, xmin, xmax, nbinsy, ymin, ymax);
  printf("nbinsx: %i nxmin: t %f nxmax: t %fn",nbinsx, xmin, xmax);
  printf("nbinsy: %i nymin: t %f nymax: t %fn",nbinsy, ymin, ymax);
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::printHistogramLimits(TH3* hist) 
{
  // prints the limits of hist

  Int_t nbinsx, nbinsy, nbinsz;
  Axis_t xmin, xmax, ymin, ymax, zmin, zmax;

  getHistogramLimits(hist, nbinsx, xmin, xmax, nbinsy, ymin, ymax , nbinsz, zmin, zmax);

  printf("nbinsx: %i nxmin: t %f nxmax: t %fn",nbinsx, xmin, xmax);
  printf("nbinsy: %i nymin: t %f nymax: t %fn",nbinsy, ymin, ymax);
  printf("nbinsz: %i nzmin: t %f nzmax: t %fn",nbinsz, zmin, zmax);
  printHistogramLimits((TH2*) hist);
}

////////////////////////////////////////////////////////////////////////////////

 Bool_t PTools::compareHistogramLimits(TH1* hist1, TH1* hist2, Bool_t exitIfNotEqual )
{
  // compares limits of hist1 with limits hist2 (nbins, min, max)
  // if exitIfNotEqual is set exit.
  
  Bool_t ok = kTRUE;

  Int_t nbinsx1, nbinsy1;
  Axis_t xmin1, xmax1, ymin1, ymax1;
  Int_t nbinsx2, nbinsy2;
  Axis_t xmin2, xmax2, ymin2, ymax2;

  getHistogramLimits(  hist1, nbinsx1, xmin1, xmax1, nbinsy1, ymin1, ymax1);
  getHistogramLimits(  hist2, nbinsx2, xmin2, xmax2, nbinsy2, ymin2, ymax2);
  
  if ( nbinsx1 != nbinsx2 ) ok = kFALSE; 
  if ( nbinsy1 != nbinsy2 ) ok = kFALSE; 
  if ( xmin1 != xmin2 ) ok = kFALSE; 
  if ( xmax1 != xmax2 ) ok = kFALSE; 
  if ( ymin1 != ymin2 ) ok = kFALSE; 
  if ( ymax1 != ymax2 ) ok = kFALSE; 

  if (!ok)
    {
      Error("checkRanges()",
	    "parameters nbinsx(%i,%i),n nbinsy(%i,%i), n xmin(%f,%f), n xmax(%f,%f), n ymin(%f,%f), n ymax(%f,%f) of hist1:%s and hist2:%s are not identical %s",
	    (!exitIfNotEqual)?"!":"... exiting!", 
	    nbinsx1,
	    nbinsx2,
	    nbinsy1,
	    nbinsy2,
	    xmin1,
	    xmin2,
	    xmax1,
	    xmax2,
	    ymin1,
	    ymin2,
	    ymax1,
	    ymax2,
	    hist2->GetName(),
	    hist2->GetName()
	    );
      if (exitIfNotEqual)
	{
	  exit(EXIT_FAILURE);
	}
    }
    
  return ok;
}

////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::getNFilledBins(TH1 * hist, Double_t min, Double_t max)
{
  // get number of filled bins where the
  // bin contents are within the limits of min and max 
  
  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();

  if ( min==-1 && max == -1)
    {
      min = hist->GetMinimum();
      max = hist->GetMaximum();
    }
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;
  Double_t g;

  Int_t ctr=0;  

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      g = hist->GetBinContent(bin);
	      
	      if (binx==0) continue;
	      if (nbinsy !=-1) { if (biny==0) continue;}
	      if (nbinsz !=-1) { if (binz==0) continue;}
	      if (binx==nbinsx+1) continue;
	      if (nbinsy !=-1){if (biny==nbinsy+1) continue;}
	      if (nbinsz !=-1){if (binz==nbinsz+1) continue;}
	      
	      if (g >=min && g <=max) 
		{
		  if (g!=0.) ctr++;
		}

	    }
	}
    }
  return ctr;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::cleanHistogram(TH1 * hist, Double_t min, Double_t max, Int_t errorMode)
{
  // cleans histograms
  // bin contents out of the limits of min and max 
  // are set to 0 
  // errors are set to 0
  // 
  // if errorMode is not equal [default=0]
  // then instead of the binContent
  // the min-max condition is applied on the errors
  //
  // errorMode = 0: bin contents 
  // errorMode > 0: absolute Values are compared
  // errorMode < 0: relative Errors are considere
  // (for this purpose the function getErrorsOfHistogram() is used, see there for definitions of exceptions)  

  if (!hist)
    {
      ::Error("cleanHistogram"," hist is NULL pointer ... return NULL");
      return;
    }

  if (errorMode>0) errorMode = 1;
  if (errorMode<0) errorMode =-1;

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;
  Double_t g=-100.;
  bin=0;

  TH1* errHist;

  switch(errorMode)
    {
    case 0:
      errHist = NULL;
      break;
    case 1:
      errHist = (TH1*) getErrorsOfHistogram(hist,kFALSE);
      break;
    case -1:
      errHist = (TH1*) getErrorsOfHistogram(hist,kTRUE);
      break;
    default:
      errHist = NULL;
      break;
    }
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      switch(errorMode)
		{
		case 0:
		  bin = hist->GetBin(binx,biny,binz);
		  g = hist->GetBinContent(bin);
		  break;
		case 1:
		  bin = errHist->GetBin(binx,biny,binz);
		  g = errHist->GetBinContent(bin);
		  break;
		case -1:
		  bin = errHist->GetBin(binx,biny,binz);
		  g = errHist->GetBinContent(bin);
		  break;
		default:
		  break;
		}

	      if(bin>=0)
		{
		  if (g < min || g > max)
		    {
		      hist->SetBinContent(bin,0);
		      hist->SetBinError(bin,0);
		    }
		}
	    }
	}
    }

  if (errorMode != 0 && errHist) 
    {
      delete errHist;
    }
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::prefixToName(TNamed *name, TString prefix)
{
  prefix+="_";
  prefix+= name->GetName();
  name->SetName(prefix.Data());
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::prefixToTitle(TNamed *name, TString prefix)
{
  prefix+=" - ";
  prefix+= name->GetTitle();
  name->SetTitle(prefix.Data());
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::prefixToNameTitle(TNamed *name, TString prefix)
{
  TString prefixTitle = prefix;
  prefix+="_";
  prefix+= name->GetName();
  name->SetName(prefix.Data());
  prefixTitle+=" - ";
  prefixTitle+= name->GetTitle();
  name->SetTitle(prefixTitle.Data());
  
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::postfixToName(TNamed *name, TString postfix)
{
  // attaches to the name of TNamed name "_postfix"
  // and      " - postfix" to its title
  
  TString postfixTitle = postfix;

  postfix=name->GetName()+TString("_")+postfix;
  name->SetName(postfix.Data());
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::postfixToTitle(TNamed *name, TString postfix)
{
  // attaches to TNamed name " - postfix" to its title
  
  TString postfixTitle = postfix;

  postfixTitle=name->GetTitle()+TString(" - ")+postfixTitle;
  name->SetTitle(postfixTitle.Data());
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::postfixToNameTitle(TNamed *name, TString postfix)
{
  // attaches to the name of TNamed name "_postfix"
  // and      " - postfix" to its title
  
  TString postfixTitle = postfix;

  postfix=name->GetName()+TString("_")+postfix;
  name->SetName(postfix.Data());

  postfixTitle=name->GetTitle()+TString(" - ")+postfixTitle;
  name->SetTitle(postfixTitle.Data());
}

// void PTools::prefixToName      (TNamed *name, Char_t  *prefix){TString aa =  prefix;  prefixToName     (name,aa);};
// void PTools::prefixToTitle     (TNamed *name, Char_t  *prefix){TString aa =  prefix;  prefixToTitle    (name,aa);};
// void PTools::prefixToNameTitle (TNamed *name, Char_t  *prefix){TString aa =  prefix;  prefixToNameTitle(name,aa);};
// void PTools::postfixToName     (TNamed *name, Char_t *postfix){TString aa = postfix; postfixToName     (name,aa);};
// void PTools::postfixToTitle    (TNamed *name, Char_t *postfix){TString aa = postfix; postfixToTitle    (name,aa);};
// void PTools::postfixToNameTitle(TNamed *name, Char_t *postfix){TString aa = postfix; postfixToNameTitle(name,aa);};

////////////////////////////////////////////////////////////////////////////////

 void PTools::cutHistogram(TH2* hist, TCutG *cut, Bool_t complement)
{
  // cuts 2-dim histogram hist by using the graphical cut 
  // complement inverts the selection

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;
  Double_t gx,gy;
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      gx = hist->GetXaxis()->GetBinCenter(binx);
	      gy = hist->GetYaxis()->GetBinCenter(biny);
	      
	      if ((!complement && !cut->IsInside(gx,gy)) || (complement && cut->IsInside(gx,gy)))
		{
		  hist->SetBinContent(bin,0);
		  hist->SetBinError(bin,0);
		}
	    }
	}
    }
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::cutHistogram(TH2* hist, TObjArray *cutarray, Bool_t complement)
{
  // cuts 2-dim histogram hist by using logical or of the graphical cuts in the cutarray
  // complement inverts the selection
  
  TIterator *iter = cutarray->MakeIterator();
  
  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;
  Double_t gx,gy;
  TCutG *cut;
  Bool_t keep;
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      gx = hist->GetXaxis()->GetBinCenter(binx);
	      gy = hist->GetYaxis()->GetBinCenter(biny);
	      
	      cut=0;
	      iter->Reset();
	      if (!complement)
		{
		  keep=kFALSE;
		  while( (cut = (TCutG*) iter->Next()) != NULL )
		    {
		      if (cut->IsInside(gx,gy))
			{
			  keep=kTRUE;
			  break;
			}
		    }
		  if (!keep)
		    {
		      hist->SetBinContent(bin,0);
		      hist->SetBinError(bin,0);
		    }
		}
	      else
		{
		  keep=kTRUE;
		  while( (cut = (TCutG*) iter->Next()) != NULL )
		    {
		      if (cut->IsInside(gx,gy))
			{
			  keep = keep & kFALSE;
			  continue;
			}
		    }	
		  if (!keep)
		    {
		      hist->SetBinContent(bin,0);
		      hist->SetBinError(bin,0);
		    }
		}
	    }
	}
    }
}

////////////////////////////////////////////////////////////////////////////////

 void  PTools::plotCounts(TH1* hist, Int_t color, TString format)
{
  // plots above each bin of hist 
  // the bin content 
  // in color
  // format can specify via e.g. %2.4f special output formats
  // but only fixed to floating precisions, so if you want to display just integers e.g. choose %4.0f

  if (hist->GetDimension()>1) 
    {    
      Error("plotCounts","this function can only be applied to 1-dimensional histograms");
      return;
    }

  Int_t first = hist->GetXaxis()->GetFirst();
  Int_t last = hist->GetXaxis()->GetLast();
  for (Int_t binx=first; binx<=last;binx++)
    {
      Double_t count = hist->GetBinContent(binx);
      Double_t xpos = hist->GetBinCenter(binx);
      Double_t ypos = (gPad->GetLogy())?log10(count):count;
      TString val="";
      if (format.IsNull())
	{
	  val+=count;
	}
      else
	{
	  val+=Form(format.Data(),count);
	}
      if (!(count>0 || count<0)) continue;

      hist->SetMaximum(hist->GetMaximum()* ((gPad->GetLogy())?5:1.05));
      
      TLatex *tex = drawLatexPadCoords(val, xpos, ypos, color, 0.025, 13, 72, 90);
      tex->SetLineWidth(2);
    }

}

////////////////////////////////////////////////////////////////////////////////

 TH1F* PTools::getTH1F(TString name, TString title, 
		      Int_t xbin, Double_t xmin, Double_t xmax, 
		      TString xtitle, TString ytitle)
{
  // one command for initializing a TH1F histogramm
  // object has to be deleted by user
  TH1F *hist = new TH1F(name,title, xbin,xmin,xmax);
  setTitleArts(hist,xtitle,ytitle);
  return hist;
}
////////////////////////////////////////////////////////////////////////////////
 TH2F* PTools::getTH2F(TString name, TString title, 
		      Int_t xbin, Double_t xmin, Double_t xmax, 
		      Int_t ybin, Double_t ymin, Double_t ymax, 
		      TString xtitle, TString ytitle, TString ztitle)
{
  // one command for initializing a TH2F histogramm
  // object has to be deleted by user

  TH2F *hist = new TH2F(name,title, xbin,xmin,xmax, ybin,ymin,ymax );

  if (! ztitle.IsNull()) 
    {
      hist->SetZTitle(ztitle.Data());
      ((TAxis*)hist->GetZaxis())->CenterTitle();
      ((TAxis*)hist->GetZaxis())->SetTitleFont(42);
      ((TAxis*)hist->GetZaxis())->SetTitleColor(1);
      ((TAxis*)hist->GetZaxis())->SetTitleOffset(1.2);
    }

  setTitleArts(hist,xtitle,ytitle);
  return hist;
}
////////////////////////////////////////////////////////////////////////////////
 TH3F* PTools::getTH3F(TString name, TString title, 
		      Int_t xbin, Double_t xmin, Double_t xmax, 
		      Int_t ybin, Double_t ymin, Double_t ymax, 
		      Int_t zbin, Double_t zmin, Double_t zmax, 
		      TString xtitle, TString ytitle, TString ztitle)
{
  // one command for initializing a TH3F histogramm
  // object has to be deleted by user
  TH3F *hist = new TH3F(name,title, xbin,xmin,xmax, ybin,ymin,ymax, zbin,zmin,zmax );
  setTitleArts(hist,xtitle,ytitle);
  hist->SetZTitle(ztitle.Data());
  ((TAxis*)hist->GetZaxis())->CenterTitle();
  ((TAxis*)hist->GetZaxis())->SetTitleFont(42);
  ((TAxis*)hist->GetZaxis())->SetTitleColor(1);
  ((TAxis*)hist->GetZaxis())->SetTitleOffset(1.2);
  return hist;
}
////////////////////////////////////////////////////////////////////////////////

 TH1D* PTools::getTH1D(TString name, TString title, 
		      Int_t xbin, Double_t xmin, Double_t xmax, 
		      TString xtitle, TString ytitle)
{
  // one command for initializing a TH1D histogramm
  // object has to be deleted by user
  TH1D *hist = new TH1D(name,title, xbin,xmin,xmax);
  setTitleArts(hist,xtitle,ytitle);
  return hist;
}
////////////////////////////////////////////////////////////////////////////////
 TH2D* PTools::getTH2D(TString name, TString title, 
		      Int_t xbin, Double_t xmin, Double_t xmax, 
		      Int_t ybin, Double_t ymin, Double_t ymax, 
		      TString xtitle, TString ytitle, TString ztitle)
{
  // one command for initializing a TH2D histogramm
  // object has to be deleted by user

  TH2D *hist = new TH2D(name,title, xbin,xmin,xmax, ybin,ymin,ymax );

  if (! ztitle.IsNull()) 
    {
      hist->SetZTitle(ztitle.Data());
      ((TAxis*)hist->GetZaxis())->CenterTitle();
      ((TAxis*)hist->GetZaxis())->SetTitleFont(42);
      ((TAxis*)hist->GetZaxis())->SetTitleColor(1);
      ((TAxis*)hist->GetZaxis())->SetTitleOffset(1.2);
    }

  setTitleArts(hist,xtitle,ytitle);
  return hist;
}
////////////////////////////////////////////////////////////////////////////////
 TH3D* PTools::getTH3D(TString name, TString title, 
		      Int_t xbin, Double_t xmin, Double_t xmax, 
		      Int_t ybin, Double_t ymin, Double_t ymax, 
		      Int_t zbin, Double_t zmin, Double_t zmax, 
		      TString xtitle, TString ytitle, TString ztitle)
{
  // one command for initializing a TH3D histogramm
  // object has to be deleted by user
  TH3D *hist = new TH3D(name,title, xbin,xmin,xmax, ybin,ymin,ymax, zbin,zmin,zmax );
  setTitleArts(hist,xtitle,ytitle);
  hist->SetZTitle(ztitle.Data());
  ((TAxis*)hist->GetZaxis())->CenterTitle();
  ((TAxis*)hist->GetZaxis())->SetTitleFont(42);
  ((TAxis*)hist->GetZaxis())->SetTitleColor(1);
  ((TAxis*)hist->GetZaxis())->SetTitleOffset(1.2);
  return hist;
}

////////////////////////////////////////////////////////////////////////////////
 TH1* PTools::reverseXAxis(TH1* hist)
{
  // reverses the X-Axis of the histogramm
  // creates a new histogramm 

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin,bin2;

  TString name2 = hist->GetName(); name2 +="_Xreverse";

  TH1 * hist2 = (TH1*) hist->Clone(name2.Data()); 
  hist2->Reset();

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      bin2 = hist->GetBin(nbinsx+1-binx,biny,binz);
	      hist2->SetBinContent(bin2,hist->GetBinContent(bin));
	      if (hist->GetSumw2N())
		{
		  if (! hist2->GetSumw2N()) hist2->Sumw2();
		  hist2->SetBinError(bin2,hist->GetBinError(bin));
		}
	    }
	}
    }
  hist2->SetEntries(hist->GetEntries());
  return hist2;
}


////////////////////////////////////////////////////////////////////////////////
 TH2* PTools::reverseYAxis(TH2* hist)
{
  // reverses the Y-Axis of the histogramm
  // creates a new histogramm 

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) {Error("reverseYAxis","dimension %i to small ... exiting!",hist->GetDimension()<2); exit(EXIT_FAILURE);} 
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin,bin2;

  TString name2 = hist->GetName(); name2 +="_Yreverse";

  TH2 * hist2 = (TH2*) hist->Clone(name2.Data()); 
  hist2->Reset();

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      bin2 = hist->GetBin(binx,nbinsy+1-biny,binz);
	      hist2->SetBinContent(bin2,hist->GetBinContent(bin));
	      if (hist->GetSumw2N())
		{
		  if (! hist2->GetSumw2N()) hist2->Sumw2();
		  hist2->SetBinError(bin2,hist->GetBinError(bin));
		}
	    }
	}
    }
  hist2->SetEntries(hist->GetEntries());
  return hist2;
}


////////////////////////////////////////////////////////////////////////////////

 TH3* PTools::reverseZAxis(TH3* hist)
{
  // reverses the Z-Axis of the histogramm
  // creates a new histogramm 

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) {Error("reverseZAxis","dimension %i to small ... exiting!",hist->GetDimension()<2); exit(EXIT_FAILURE);} 
  if (hist->GetDimension()<3) {Error("reverseZAxis","dimension %i to small ... exiting!",hist->GetDimension()<2); exit(EXIT_FAILURE);} 

  Int_t binx,biny,binz,bin,bin2;

  TString name2 = hist->GetName(); name2 +="_Zreverse";

  TH3 * hist2 = (TH3*) hist->Clone(name2.Data()); 
  hist2->Reset();

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++) 
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      bin2 = hist->GetBin(binx,biny,nbinsz+1-binz);
	      hist2->SetBinContent(bin2,hist->GetBinContent(bin));
	      if (hist->GetSumw2N())
		{
		  if (! hist2->GetSumw2N()) hist2->Sumw2();
		  hist2->SetBinError(bin2,hist->GetBinError(bin));
		}
	    }
	}
    }
  hist2->SetEntries(hist->GetEntries());
  return hist2;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::plotPolarAxis(Double_t min, Double_t max, Int_t divisions, Float_t direction)
{
  // plots polar axis
  // starting from min
  // ending at max
  // pointing in direction (angle [rad])
  // with n divisions 

  direction*=(acos(-1.)/180.0);
  Float_t radius = 0.58;

  TGaxis *axis1 = new TGaxis(0,0, radius*cos(direction) ,radius*sin(direction) ,min,max,divisions,"+");
  axis1->SetLabelColor(1);
  axis1->Draw();
  //   TGaxis *axis2 = new TGaxis(0.002,0, (radius+0.002)*cos(direction) , (radius+0.002)*sin(direction) ,min,max,divisions,"+");
  //   axis2->Draw();
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::plotPolarAxis(TH2* hist, Int_t divisions, Float_t direction)
{
  // plots polar axis using the limits of hist
  // see plotPolarAxis
  if (!hist) 
    {
      Error("plotPolarAxis","hist has a NULL pointer ... nothing done");
      return;
    }
  plotPolarAxis(hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax(),divisions,direction);
  
}
////////////////////////////////////////////////////////////////////////////////

 void PTools::plotPolarGrid(Int_t division)
{
  // plots in polar coordiates 
  // a circular grid
  // with the hades naming of phi angles
  // 

  if (division == 0) 
    {
      Error("plotPolarGrid","division of %i not realistic ... nothing done",division);
      return;
    }
  
  Float_t radius = 0.58;
  TEllipse *kDeg; 
  TEllipse *kDeg2; 
  {
    for (int iter = 1; iter <= division; iter++) 
      {
	kDeg = new TEllipse(0,0,(radius/division)*iter);
	kDeg->SetLineWidth(2);
	kDeg->SetLineColor(10);
	kDeg->Draw();
	kDeg2 = new TEllipse(0,0,(radius/division)*iter);
	kDeg2->SetLineWidth(1);
	kDeg2->Draw();
      }
  }
}


////////////////////////////////////////////////////////////////////////////////

 void PTools::plotPolarSectorGridHADES()
{
  // plots in polar coordiates 
  // a line axis grid
  // with the hades naming of phi angles

  TLine *lDeg[6];
  TLine *lDeg2[6];
  TString label[6]={"180#circ","120#circ","60#circ","0#circ","300#circ","240#circ"};
  TLatex * tex[6];
  
  for (int iter = 0; iter < 6; iter++)
    {
      Float_t radius = 0.65;
      lDeg[iter] = new TLine(0,0,radius*cos(iter*60*acos(-1.)/180),radius*sin(iter*60*acos(-1.)/180));
      //lDeg[iter]->SetLineStyle(2);
      lDeg[iter]->SetLineWidth(2);
      lDeg[iter]->SetLineColor(10);
      lDeg[iter]->Draw(); 
      lDeg2[iter] = new TLine(0,0,radius*cos(iter*60*acos(-1.)/180),radius*sin(iter*60*acos(-1.)/180));
      //      lDeg2[iter]->SetLineStyle(2);
      lDeg2[iter]->SetLineWidth(1);
      lDeg2[iter]->SetLineColor(1);
      lDeg2[iter]->Draw(); 
      
      radius+=0.07;
      tex[iter]  = new TLatex(radius*cos(iter*60*acos(-1.)/180),radius*sin(iter*60*acos(-1.)/180),label[iter].Data());
      tex[iter]->Draw();
    }
}


/////////////////////////////////////////////////////////////////////////////////

 void PTools::saveToPdf(TCanvas* canvas,TString path,TString filename,Bool_t separate, Int_t selection)
{
  // saves canvas to pdf
  // to path
  // using filename 
  // if separate is used 
  // each sub pad is printed to its own file
  // (requieres external function ps2pdf)
  // Thanks to Jochen Markert, GSI
  // selection selects one specific subpad number if selection > 0
  // produced now output in compatiblity mode 1.4 (Acrobat 5 and higher)
  saveToPdf((TPad*) canvas,path,filename,separate, selection);
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::saveToPdf(TPad* pad,TString path,TString filename,Bool_t separate, Int_t selection)
{
  // saves pad to pdf
  // to path
  // using filename 
  // if separate is used 
  // each sub pad is printed to its own file
  // (requieres external function ps2pdf)
  // Thanks to Jochen Markert, GSI
  // selection selects one specific subpad number if selection > 0
  // produced now output in compatiblity mode 1.4 (Acrobat 5 and higher)

  if (filename.IsNull()) filename=pad->GetName();

  TString File    =filename;
  TString Path    =path;
  if (!Path.EndsWith("/") && !Path.IsNull()) 
    {
      Path = Path + "/";
    }
  TString command ="";
  TString totalin ="";
  TString totalout="";
  TString converter="ps2pdf -dCompatibilityLevel=1.4 -dEmbedAllFonts=true";

  TString check = TString("which ")+ converter + TString(" > /dev/null");
  
  if (gSystem->Exec(check.Data()))
  {
    Error("saveToPdf","external program "%s" not available ... nothing is done",converter.Data());
    return;
  }

  File.ReplaceAll(".ps","");
  if(!separate)
    {
      totalin = Path + File + ".ps";
      totalout= Path + File + ".pdf";
      pad->SaveAs(totalin.Data());
      command= converter + " " + totalin + " " + totalout;
      gSystem->Exec(command.Data());
      command= "rm " + totalin;
      gSystem->Exec(command.Data());
    }else{
      TString subpad="";
      Int_t npads= pad->GetListOfPrimitives()->GetSize();
      for(Int_t i=1;i<=npads;i++)
        {
	  if (selection > 0 && i!=selection) 
	    {
	      continue;
	    }
	  subpad="";
	  subpad+=i;
	  totalin = Path + File + "_" + subpad + ".ps";
	  totalout= Path + File + "_" + subpad + ".pdf";
	  pad->cd(i);
	  TPad *clone = (TPad*) gPad->Clone();
	  Bool_t batch = gROOT->IsBatch();
	  gROOT->SetBatch();
	  TCanvas *dummy = new TCanvas("dummy","dummy",1000,800);
	  dummy->cd();
	  clone->Draw();
	  clone->SetPad(0,0,1,1);
	  dummy->SaveAs(totalin.Data());
	  command= converter + " " + totalin + " " + totalout;
	  gSystem->Exec(command.Data());
	  command= "rm " + totalin;
	  gSystem->Exec(command.Data());
	  dummy->Close();
	  gROOT->SetBatch(batch);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::saveToPng(TCanvas* canvas,TString path,TString filename,Bool_t separate, Int_t selection)
{
  // saves canvas to png
  // to path
  // using filename 
  // if separate is used 
  // each sub pad is printed to its own file
  // (requieres external function convert)
  // Thanks to Jochen Markert, GSI
  // selection selects one specific subpad number if selection > 0

  saveToPng((TPad*)canvas,path, filename, separate, selection);
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::saveToPng(TPad* pad,TString path,TString filename,Bool_t separate, Int_t selection)
{
  // saves pad to png
  // to path
  // using filename 
  // if separate is used 
  // each sub pad is printed to its own file
  // (requieres external function convert)
  // Thanks to Jochen Markert, GSI
  // selection selects one specific subpad number if selection > 0

  if (filename.IsNull()) {filename=pad->GetName();}

  TString File    =filename;
  TString Path    =path;
  if (!Path.EndsWith("/") && !Path.IsNull()) 
    {
      Path = Path + "/";
    }
  TString command ="";
  TString totalin ="";
  TString totalout="";
  TString converter="convert";

  TString check = TString("which ")+ converter  + TString(" > /dev/null");
  
  if (gSystem->Exec(check.Data()))
  {
    Error("saveToPng","external program "%s" not available ... nothing is done",converter.Data());
    return;
  }

  File.ReplaceAll(".png","");
  if(!separate)
    {
      totalin = Path + File + ".ps";
      totalout= Path + File + ".png";
      pad->SaveAs(totalin.Data());
      command= converter + " " + totalin + " " + totalout;
      gSystem->Exec(command.Data());
      command= converter + " -rotate 90 " + totalout + " " + totalout;
      gSystem->Exec(command.Data());
      command= "rm " + totalin;
      gSystem->Exec(command.Data());
    }else{
      TString subpad="";
      Int_t npads= pad->GetListOfPrimitives()->GetSize();
      for(Int_t i=1;i<=npads;i++)
        {
	  if (selection > 0 && i!=selection) 
	    {
	      continue;
	    }
	  subpad="";
	  subpad+=i;
	  totalin = Path + File + "_" + subpad + ".ps";
	  totalout= Path + File + "_" + subpad + ".png";
	  pad->cd(i);
	  TPad *clone = (TPad*) gPad->Clone();
	  Bool_t batch = gROOT->IsBatch();
	  gROOT->SetBatch();
	  TCanvas *dummy = new TCanvas("dummy","dummy",1000,800);
	  dummy->cd();
	  clone->Draw();
	  clone->SetPad(0,0,1,1);
	  dummy->SaveAs(totalin.Data());
	  command= converter + " " + totalin + " " + totalout;
	  gSystem->Exec(command.Data());
	  command= converter + " -rotate 90 " + totalout + " " + totalout;
	  gSystem->Exec(command.Data());
	  command= "rm " + totalin;
	  gSystem->Exec(command.Data());
	  dummy->Close();
	  gROOT->SetBatch(batch);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::saveGifToPdf(TCanvas* canvas,TString path,TString filename,Bool_t separate, Int_t selection)
{
  // saves canvas to gif
  // to path
  // using filename 
  // if separate is used 
  // each sub pad is printed to its own file
  // (requieres external function convert)
  // Thanks to Jochen Markert, GSI
  // selection selects one specific subpad number if selection > 0

  saveGifToPdf((TPad*)canvas , path, filename, separate, selection);
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::saveGifToPdf(TPad* pad,TString path,TString filename,Bool_t separate, Int_t selection)
{
  // saves pad to gif
  // to path
  // using filename 
  // if separate is used 
  // each sub pad is printed to its own file
  // (requieres external function convert)
  // Thanks to Jochen Markert, GSI
  // selection selects one specific subpad number if selection > 0

  if (filename.IsNull()) filename=pad->GetName();

  TString File    =filename;
  TString Path    =path;
  if (!Path.EndsWith("/") && !Path.IsNull()) 
    {
      Path = Path + "/";
    }
  TString command ="";
  TString totalin ="";
  TString totalout="";
  TString converter="convert";
  TString check = TString("which ")+ converter  + TString(" > /dev/null");
  
  if (gSystem->Exec(check.Data()))
  {
    Error("saveGifToPdf","external program "%s" not available ... nothing is done",converter.Data());
    return;
  }

  File.ReplaceAll(".pdf","");
  if(!separate)
    {
      totalin = Path + File + ".gif";
      totalout= Path + File + ".pdf";
      pad->SaveAs(totalin.Data());
      command= converter + " " + totalin + " " + totalout;
      gSystem->Exec(command.Data());
      command= "rm " + totalin;
      gSystem->Exec(command.Data());
    }
  else
    {
      TString subpad="";
      Int_t npads= pad->GetListOfPrimitives()->GetSize();
      for(Int_t i=1;i<=npads;i++)
        {
	  if (selection > 0 && i!=selection) 
	    {
	      continue;
	    }
	  subpad="";
	  subpad+=i;
	  totalin = Path + File + "_" + subpad + ".ps";
	  totalout= Path + File + "_" + subpad + ".pdf";
	  pad->cd(i);
	  TPad *clone = (TPad*) gPad->Clone();
	  Bool_t batch = gROOT->IsBatch();
	  gROOT->SetBatch();
	  TCanvas *dummy = new TCanvas("dummy","dummy",1000,800);
	  dummy->cd();
	  clone->Draw();
	  clone->SetPad(0,0,1,1);
	  dummy->SaveAs(totalin.Data());
	  command= converter + " " + totalin + " " + totalout;
	  gSystem->Exec(command.Data());
	  command= "rm " + totalin;
	  gSystem->Exec(command.Data());
	  dummy->Close();
	  gROOT->SetBatch(batch);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::getColorJM(Int_t i)
{
  // Thanks to Jochen Markert, GSI
  Int_t colors[]   ={2,4,6,8,38,46,14,1,30,43};
  i%=((int)(sizeof(colors)/sizeof(Int_t)));
  return colors[i];
}

/////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::getMarkerJM(Int_t i)
{
  // Thanks to Jochen Markert, GSI
  Int_t style[]   ={20,21,22,23,24,25,26,27,28,29};
  i%=((int)(sizeof(style)/sizeof(Int_t)));
  return style[i];
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::setGraph(TGraph* graph,Int_t mycolorindex,Int_t markerstyle,Int_t markercolor,Float_t markersize,Int_t linecolor)
{
  // Thanks to Jochen Markert, GSI
  if(mycolorindex<0)
    {
      graph->SetMarkerColor(markercolor);
      graph->SetMarkerSize(markersize);
      graph->SetMarkerStyle(markerstyle);
      graph->SetLineColor(linecolor);
    }
  else
    {
      if     (markercolor>=0)graph->SetMarkerColor(PTools::getColorJM(mycolorindex));
      else if(markercolor<0) graph->SetMarkerColor(PTools::getColorJM(-markercolor));
      graph->SetMarkerSize(markersize);
      if     (markerstyle>=0)graph->SetMarkerStyle(PTools::getMarkerJM(mycolorindex));
      else if(markerstyle<0) graph->SetMarkerStyle(PTools::getMarkerJM(-markerstyle));
      graph->SetLineColor(linecolor);
    }
}

/////////////////////////////////////////////////////////////////////////////////

 void PTools::setHist(TH1* hist,Int_t mycolorindex,Int_t markerstyle,Int_t markercolor,Float_t markersize,Int_t linecolor)
{
  // Thanks to Jochen Markert, GSI
  if(mycolorindex==-99)
    {
      hist->SetMarkerColor(markercolor);
      hist->SetMarkerSize(markersize);
      hist->SetMarkerStyle(markerstyle);
      hist->SetLineColor(linecolor);
    }
  else
    {
      if     (markercolor>=0)hist->SetMarkerColor(PTools::getColorJM(mycolorindex));
      else if(markercolor<0) hist->SetMarkerColor(PTools::getMarkerJM(-markercolor));
      hist->SetMarkerSize(markersize);
      if     (markerstyle>=0)hist->SetMarkerStyle(PTools::getMarkerJM(mycolorindex));
      else if(markerstyle<0) hist->SetMarkerStyle(PTools::getMarkerJM(-markerstyle));
      hist->SetLineColor(linecolor);
    }
}

/////////////////////////////////////////////////////////////////////////////////

 TLegend* PTools::plotLegend(TString pos,TString Title,
			    Float_t scaleX,Float_t scaleY,
			    Float_t offsetX,Float_t offsetY,
			    TString Comment,
			    Int_t commencolor)
{
  // Thanks to Jochen Markert, GSI
    Float_t left  =gPad->GetLeftMargin()*1.15;
    Float_t right =1-gPad->GetRightMargin();
    Float_t top   =1-gPad->GetTopMargin();
    Float_t bottom=gPad->GetBottomMargin()*1.15;
    Float_t mid   =gPad->GetLeftMargin() + (1-(gPad->GetRightMargin()+gPad->GetLeftMargin()))/2;
    Float_t width =(right-left)/2;
    Float_t heith =(top-bottom)/2;
    TLegend* legend = NULL;
    TLine* dummy=new TLine();
    dummy->SetLineColor(10);

    if(pos.CompareTo("left_top")==0)    legend=new TLegend(left+offsetX,top+offsetY-(scaleY*heith),left+offsetX+(scaleX*width),top+offsetY,Title.Data());                           // left top
    if(pos.CompareTo("mid_top")==0)     legend=new TLegend(mid+offsetX-((scaleX*width)/2),top+offsetY-(scaleY*heith),mid+offsetX+((scaleX*width)/2),top+offsetY,Title.Data());      // mid up
    if(pos.CompareTo("right_top")==0)   legend=new TLegend(right+offsetX-(scaleX*width),top+offsetY-(scaleY*heith),right+offsetX,top+offsetY,Title.Data());                         // right top
    if(pos.CompareTo("left_bottom")==0) legend=new TLegend(left+offsetX,bottom+offsetY,left+offsetX+(scaleX*width),bottom+offsetY+(scaleY*heith),Title.Data());                     // left bottom
    if(pos.CompareTo("mid_bottom")==0)  legend=new TLegend(mid+offsetX-((scaleX*width)/2),bottom+offsetY,mid+offsetX+((scaleX*width)/2),bottom+offsetY+(scaleY*heith),Title.Data());// mid down
    if(pos.CompareTo("right_bottom")==0)legend=new TLegend(right+offsetX-(scaleX*width),bottom+offsetY,right+offsetX,bottom+offsetY+(scaleY*heith),Title.Data());                   // right bottom

    if (!legend) return NULL;
    legend->SetFillStyle(0);
    legend->SetBorderSize(0);
    legend->SetMargin(0.15);

    if(Comment.CompareTo("")!=0)
    {   // comment below header
        TLegendEntry* entry=legend->AddEntry(dummy,Comment.Data());
        entry->SetTextColor(1);
        entry->SetTextFont(62);
        entry->SetOption("l");
    }
    return legend;
}

/////////////////////////////////////////////////////////////////////////////////

 TLegendEntry* PTools::setLegendEntry(TLegend* legend,TObject* object,TString label,Int_t col,TString opt)
{
    // add entry for object with label and color and option to legend
    //
  // Thanks to Jochen Markert, GSI
    TLegendEntry* entry=legend->AddEntry((TObject*)object,label.Data());
    entry->SetTextColor(col);
    entry->SetOption(opt.Data());
    return entry;
}

/////////////////////////////////////////////////////////////////////////////////

 TLatex* PTools::plotTopLegend(char* label,Float_t x,Float_t y,Float_t size,Int_t color)
{
  // Thanks to Jochen Markert, GSI
    // coordinates in NDC!
    if(x<0||y<0)
    {   // defaults
        x=gPad->GetLeftMargin()*1.15;
        y=(1-gPad->GetTopMargin())*1.02;
    }
    TLatex* text=new TLatex(x,y,label);
    text->SetTextSize(size);
    text->SetNDC();
    text->SetTextColor(color);
    text->Draw();
    return text;
}

/////////////////////////////////////////////////////////////////////////////////

 Double_t PTools::getMeanErrorRangeUser(TH1* hist, Axis_t minX, Axis_t maxX, TString pos)
{
  // calculates the error of arithmetic mean of a TH1 
  // in a range between minX and maxX
  // position: determines the value of the bin taken
  //           "center" : bin center value [default]
  //           "up"     : bin upper edge
  //           "low"    : bin lower edge value

  if (!hist) {::Error("getMeanErrorRangeUser","no valid histogramm NULL pointer"); exit(EXIT_FAILURE);}
  return getMeanErrorRange(hist, hist->FindBin(minX), hist->FindBin(maxX),pos);
}

/////////////////////////////////////////////////////////////////////////////////

 Double_t PTools::getMeanErrorRange(TH1* hist, Int_t minX, Int_t maxX, TString pos)
{
  // calculates the error of arithmetic mean of a TH1 
  // in a range between bin minX and bin maxX
  // position: determines the value of the bin taken
  //           "center" : bin center value [default]
  //           "up"     : bin upper edge
  //           "low"    : bin lower edge value

  pos.ToLower();
  Int_t p=-10;
  
  if (pos.CompareTo("center")==0) p=0;
  if (pos.CompareTo("up")==0) p=1;
  if (pos.CompareTo("low")==0) p=-1;
  
  if (p==-10) { Error("getMeanErrorRange","wrong position parameter %s",pos.Data());exit(EXIT_FAILURE);}

  if (!hist) {::Error("getMeanErrorRange","no valid histogramm NULL pointer"); exit(EXIT_FAILURE);}

  Int_t nbinsx = hist->GetNbinsX();
  
  if (hist->GetDimension()>2) {::Error("getMeanErrorRange","cannot be used for TH2 and TH3"); exit(EXIT_FAILURE);} 
  
  Int_t binx;
  
  Double_t bin,binval=0,binError;
  Double_t sumw2=0;
  Double_t sum=0;
  Double_t sumv=0;
   
  for (binx=0;binx<=nbinsx+1;binx++)
    {
      if (minX>binx) continue;
      if (maxX<binx) continue;
      switch (p)
	{
	case 0:
	  binval=hist->GetXaxis()->GetBinCenter(binx);
	  break;
	case -1:
	  binval=hist->GetXaxis()->GetBinLowEdge(binx);
	  break;
	case 1:
	  binval=hist->GetXaxis()->GetBinUpEdge(binx);
	  break;
	default:
	  binval=0;
	  break;
	}
      bin = hist->GetBinContent(binx);
      sum+=bin;
      sumv+=(bin*binval);
    }

  for (binx=0;binx<=nbinsx+1;binx++)
    {
      if (minX>binx) continue;
      if (maxX<binx) continue;
      switch (p)
	{
	case 0:
	  binval=hist->GetXaxis()->GetBinCenter(binx);
	  break;
	case -1:
	  binval=hist->GetXaxis()->GetBinLowEdge(binx);
	  break;
	case 1:
	  binval=hist->GetXaxis()->GetBinUpEdge(binx);
	  break;
	default:
	  binval=0;
	  break;
	}
      
      bin = hist->GetBinContent(binx);
      binError = hist->GetBinError(binx);
      sumw2+=( ((binval*sum)-sumv)*binError*((binval*sum)-sumv)*binError);
    }
  
  // cout << sumv << " " << (sumv/sum) << endl;
  
  sumw2=(((sum*sum*sum*sum)>0) || ((sum*sum*sum*sum)<0))?sumw2/(sum*sum*sum*sum):-1;
  return (sumw2<0)?-1: ::std::sqrt(sumw2);
}

////////////////////////////////////////////////////////////////////////////////

 Double_t PTools::getMeanRangeUser(TH1* hist, Axis_t minX, Axis_t maxX, TString pos)
{
  // calculates the arithmetic mean of a TH1 
  // in a range between minX and maxX
  // position: determines the value of the bin taken
  //           "center" : bin center value [default]
  //           "up"     : bin upper edge
  //           "low"    : bin lower edge value

  if (!hist) {::Error("getMeanErrorRangeUser","no valid histogramm NULL pointer"); exit(EXIT_FAILURE);}
  return getMeanErrorRange(hist, hist->FindBin(minX), hist->FindBin(maxX),pos);
}

/////////////////////////////////////////////////////////////////////////////////

 Double_t PTools::getMeanRange(TH1* hist, Int_t minX, Int_t maxX, TString pos)
{
  // calculates the arithmetic mean of a TH1 
  // in a range between bin minX and bin maxX
  // position: determines the value of the bin taken
  //           "center" : bin center value [default]
  //           "up"     : bin upper edge
  //           "low"    : bin lower edge value

  pos.ToLower();
  Int_t p=-10;
  
  if (pos.CompareTo("center")==0) p=0;
  if (pos.CompareTo("up")==0) p=1;
  if (pos.CompareTo("low")==0) p=-1;
  
  if (p==-10) { Error("getMeanErrorRange","wrong position parameter %s",pos.Data());exit(EXIT_FAILURE);}

  if (!hist) {::Error("getMeanErrorRange","no valid histogramm NULL pointer"); exit(EXIT_FAILURE);}

  Int_t nbinsx = hist->GetNbinsX();
  
  if (hist->GetDimension()>2) {::Error("getMeanErrorRange","cannot be used for TH2 and TH3"); exit(EXIT_FAILURE);} 
  
  Int_t binx;
  
  Double_t bin,binval;
  Double_t sum=0;
  Double_t sumv=0;
   
  for (binx=0;binx<=nbinsx+1;binx++)
    {
      if (minX>binx) continue;
      if (maxX<binx) continue;
      switch (p)
	{
	case 0:
	  binval=hist->GetXaxis()->GetBinCenter(binx);
	  break;
	case -1:
	  binval=hist->GetXaxis()->GetBinLowEdge(binx);
	  break;
	case 1:
	  binval=hist->GetXaxis()->GetBinUpEdge(binx);
	  break;
	default:
	  binval=0;
	  break;
	}

      bin = hist->GetBinContent(binx);
      sum+=bin;
      sumv+=(bin*binval);
    }

  return (sum>0 || sum <0)?sumv/sum:-1;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::sqrt(TH1* hist)
{
  // calculates the sqrt of each histogram bin

  if (! hist->GetSumw2N()) hist->Sumw2();

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<3) nbinsz = -1;
  if (hist->GetDimension()<2) nbinsy = -1;

  Int_t binx,biny,binz,bin;
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      if (nbinsz!=-1)
	{
	  if (binz == 0       ) continue;
	  if (binz == nbinsz+1) continue;
	}
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  if (nbinsy!=-1)
	    {
	      if (biny == 0       ) continue;
	      if (biny == nbinsy+1) continue;
	    }
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      if (nbinsx!=-1)
		{
		  if (binx == 0       ) continue;
		  if (binx == nbinsx+1) continue;
		}
	      bin = hist->GetBin(binx,biny,binz);

	      if (hist->GetBinContent(bin) < 0)
		{
		  Error("histogram %s contains negative values, cannot perform sqrt() operation ... exiting",
			hist->GetName());
		  exit(EXIT_FAILURE);
		}
	    }
	}
    }

  Stat_t val=0;
  Stat_t err=0;
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      if (nbinsz!=-1)
	{
	  if (binz == 0       ) continue;
	  if (binz == nbinsz+1) continue;
	}
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  if (nbinsy!=-1)
	    {
	      if (biny == 0       ) continue;
	      if (biny == nbinsy+1) continue;
	    }
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      if (nbinsx!=-1)
		{
		  if (binx == 0       ) continue;
		  if (binx == nbinsx+1) continue;
		}
	      bin = hist->GetBin(binx,biny,binz);

	      val = hist->GetBinContent(bin);
	      err = hist->GetBinError(bin);
	      
	      hist->SetBinContent(bin, ::std::sqrt(val));

	      if (val==0.0 ||  ::std::sqrt(val) == 0.0)
		{
		  hist->SetBinError(bin,0);
		}
	      else
		{
		    hist->SetBinError(bin, ( err*0.5 * 1./ ::std::sqrt(val)));
		}
	    }
	}
    }

}

////////////////////////////////////////////////////////////////////////////////

 TNamed* PTools::Clone(TNamed *name, TString newname, TString title)
{
  // Clones named object name and sets the name no newname and its title to title 
  // if newname and or title are empty
  // title and name are extended by "_clone"
  
  if (newname.IsNull())
    {
      newname=name->GetName();
      newname+="_clone";
    }
  if (title.IsNull())
    {
      title=name->GetTitle();
      title+="_clone";
    }

  TNamed *named = (TNamed*) name->Clone(newname.Data());
  named->SetTitle(title.Data());

  return named;
}

//memomory leak?
////////////////////////////////////////////////////////////////////////////////

 TH1* PTools::copyToTHxD(TH1 * hist)
{
  // copies any THx histogramm to THxD histograms
  // you have to cast to the corresponding type
  // attaches to name "_THxD"

  if (! hist)
    {
      ::Error("copyToTHxD","histogram has NULL pointer ... exiting");
      exit(EXIT_FAILURE);
      return NULL;
    }
  
  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();

  TH1* histD = NULL;

  switch(hist->GetDimension())
    {
    case 1:
      {
	Int_t s = 0;
	s = 
	  ((int)(hist->GetXaxis()->GetXbins()->fN > 0)) * 1; 
	TString name = hist->GetName()+TString("_TH1D");

	switch(s)
	  {
	  case 0:
	    histD = new TH1D(name.Data(),hist->GetTitle(),
			     nbinsx,
			     hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax());
	    break;
	  case 1:
	    histD = new TH1D(name.Data(),hist->GetTitle(),
			     nbinsx,
			     hist->GetXaxis()->GetXbins()->fArray);
	    break;
	  default:
	    
	    break;
	  }
	break;
      }
    case 2:
      {
	Int_t s = 0;
	s = ((int)(hist->GetXaxis()->GetXbins()->fN > 0)) * 1 + ((int)( hist->GetYaxis()->GetXbins()->fN > 0)) * 10;
	TString name = hist->GetName()+TString("_TH2D");
	
	switch(s)
	  {
	  case 0:
	    histD = new TH2D(name.Data(),hist->GetTitle(),
			     nbinsx,
			     hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax(),
			     nbinsy,
			     hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax());
	    break;
	  case 1:
	    histD = new TH2D(name.Data(),hist->GetTitle(),
			     nbinsx,
			     hist->GetXaxis()->GetXbins()->fArray,
			     nbinsy,
			     hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax());
	    
	    break;
	  case 10:
	    histD = new TH2D(name.Data(),hist->GetTitle(),
			     nbinsx,
			     hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax(),
			     nbinsy,
			     hist->GetYaxis()->GetXbins()->fArray);
	    break;
	  default:
	    
	    break;
	  }
	break;
      }
    case 3:
      {
	TString name = hist->GetName()+TString("_TH3D");

	histD = new TH3D(name.Data(),hist->GetTitle(),
			 nbinsx,
			 hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax(),
			 nbinsy,
			 hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax(),
			 nbinsz,
			 hist->GetZaxis()->GetXmin(),hist->GetZaxis()->GetXmax());

	importAxisAttributes(hist->GetXaxis(), histD->GetXaxis(), kTRUE);
	importAxisAttributes(hist->GetYaxis(), histD->GetYaxis(), kTRUE);
	importAxisAttributes(hist->GetZaxis(), histD->GetZaxis(), kTRUE);
	break;
      }
    }
  
  importAxisAttributes(hist->GetXaxis(), histD->GetXaxis(), kTRUE);
  importAxisAttributes(hist->GetYaxis(), histD->GetYaxis(), kTRUE);
  importAxisAttributes(hist->GetZaxis(), histD->GetZaxis(), kTRUE);

  histD->SetEntries(hist->GetEntries());
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      histD->SetBinContent(bin, hist->GetBinContent(bin));
	      if (hist->GetSumw2N())
		{
		  histD->SetBinError(bin,hist->GetBinError(bin));
		}
	    }
	}
    }
  return histD;
}

////////////////////////////////////////////////////////////////////////////////

 TH1D PTools::copyToTH1D(TH1 * hist)
{
  // copy any TH1 histogramm to TH1D histogramm
  
  TH1D* tmp = (TH1D*) copyToTHxD(hist);
  TH1D h(*tmp);
  tmp->Delete();
  return TH1D(h);
}

////////////////////////////////////////////////////////////////////////////////

 TH2D PTools::copyToTH2D(TH2 * hist)
{
  // copy any TH2 histogramm to TH2D histogramm
  TH2D* tmp = (TH2D*) copyToTHxD(hist);
  TH2D h(*tmp);
  tmp->Delete();
  return TH2D(h);
}

////////////////////////////////////////////////////////////////////////////////

 TH3D PTools::copyToTH3D(TH3 * hist)
{
  // copy any TH3 histogramm to TH3D histogramm
  TH3D* tmp = (TH3D*) copyToTHxD(hist);
  TH3D h(*tmp);
  tmp->Delete();
  return TH3D(h);
}

////////////////////////////////////////////////////////////////////////////////

 TH1D* PTools::createTH1D(TH1 * hist)
{
  // copy any TH1 histogramm to TH1D histogramm
  // returned histogram has to be deleted by user

  return (hist) ? (TH1D*) copyToTHxD(hist) :  NULL;
}

////////////////////////////////////////////////////////////////////////////////

 TH2D* PTools::createTH2D(TH2 * hist)
{
  // copy any TH2 histogramm to TH2D histogramm
  // returned histogram has to be deleted by user
  
  return (hist) ? (TH2D*) copyToTHxD(hist) :  NULL;
}

////////////////////////////////////////////////////////////////////////////////

 TH3D* PTools::createTH3D(TH3 * hist)
{
  // copy any TH3 histogramm to TH3D histogramm
  // returned histogram has to be deleted by user

  return (hist) ? (TH3D*) copyToTHxD(hist) :  NULL;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::importAxisAttributes(TAxis *in, TAxis *out, Bool_t includeLabels)
{
// Copy TAxis attributes 

  if (!in || !out)
    {
      Warning("importAxisAttributes","in or output axis is NULL ... nothing done");
    }

   out->SetAxisColor  (in->GetAxisColor());
   out->SetTitleColor (in->GetTitleColor());
   out->SetTitleFont  (in->GetTitleFont());
   out->SetLabelColor (in->GetLabelColor());
   out->SetLabelFont  (in->GetLabelFont());
   out->SetLabelSize  (in->GetLabelSize());
   out->SetLabelOffset(in->GetLabelOffset());
   out->SetTickLength (in->GetTickLength());
   out->SetTitle      (in->GetTitle());
   out->SetTitleOffset(in->GetTitleOffset());
   out->SetTitleSize  (in->GetTitleSize());
   out->SetBit(TAxis::kCenterTitle, in->TestBit(TAxis::kCenterTitle));
   out->SetBit(TAxis::kRotateTitle, in->TestBit(TAxis::kRotateTitle));
   out->SetBit(TAxis::kNoExponent,   in->TestBit(TAxis::kNoExponent));
   out->SetBit(TAxis::kTickPlus,     in->TestBit(TAxis::kTickPlus));
   out->SetBit(TAxis::kTickMinus,    in->TestBit(TAxis::kTickMinus));
   out->SetTimeFormat(in->GetTimeFormat());
   if (includeLabels) 
     {
       importAxisLabels(in,out);
     }
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::importAxisLabels(TAxis *in, TAxis *out)
{
  // copies bin labels from one axis to the other
  // if bin numbers differ overlap is taken 

  THashList* labels = in->GetLabels();

  if(labels !=NULL)
    {
      if(in->GetNbins() != out->GetNbins())
	{
	  ::Warning("ImportAxisAttributes","axises do not have same binning copying labels for overlap");
	}
      TIter next(labels);
      TObjString *obj;
      while((obj=(TObjString*) next()))
	{
	  out->SetBinLabel((Int_t)obj->GetUniqueID(),obj->GetName());
	}
    }
}

////////////////////////////////////////////////////////////////////////////////

 Int_t  PTools::checkHistogramCompatibility(TH1* h1, TH1 *h2)
{
  // checks whether h1 and h1 
  //
  //   * have the same type       +(0000001)
  //   * have the same dimension  +(0000100)
  //   * have the same binning    +(0010000)
  //   * have the same limits     +(1000000)
  //
  // returns the sum of conditions not matched
  // i.e. not same type && not same binning =>  1000001;
  // returns 0, if all conditions match
  // returns -1, if h1 or h2 is a NULL pointer 

  // check for not NULL pointer
  if (!h1 || !h2)
    {
      Error("checkHistogrammCompatibility","can't compare, h1 (%p) or h2 (%p) is null pointer, returning -1",h1, h2);
      return -1;
    }

  Int_t val = 0;

  // type
  const TString n1 = h1->ClassName();
  const TString n2 = h2->ClassName();

  if (n1.CompareTo(n2))
    {
      val += 1;
    }

  // dimension
  if (h1->GetDimension() != h2->GetDimension())
    {
      val += 100;
    }

  //   binning
  if ( h1->GetNbinsX() != h2->GetNbinsX() || 
       h1->GetNbinsY() != h2->GetNbinsY() || 
       h1->GetNbinsZ() != h2->GetNbinsZ())
    {
      val += 10000;
    }
  
  // variable sized binning

  if (!areArraysCompatible(h1->GetXaxis()->GetXbins(),h2->GetXaxis()->GetXbins()) ||
      !areArraysCompatible(h1->GetYaxis()->GetXbins(),h2->GetYaxis()->GetXbins()) ||
      !areArraysCompatible(h1->GetZaxis()->GetXbins(),h2->GetZaxis()->GetXbins()))
    {
      val += 100000;
    }

  // limits
  if (h1->GetXaxis()->GetXmin() != h2->GetXaxis()->GetXmin() ||
      h1->GetXaxis()->GetXmax() != h2->GetXaxis()->GetXmax() ||
      h1->GetYaxis()->GetXmin() != h2->GetYaxis()->GetXmin() ||
      h1->GetYaxis()->GetXmax() != h2->GetYaxis()->GetXmax() ||
      h1->GetZaxis()->GetXmin() != h2->GetZaxis()->GetXmin() ||
      h1->GetZaxis()->GetXmax() != h2->GetZaxis()->GetXmax()) 
    {
      val += 1000000;
    }
  return val;
}

////////////////////////////////////////////////////////////////////////////////

 Bool_t PTools::areHistogramsCompatible(TH1* h1, TH1 *h2)
{
  // checks whether h1 and h1 
  //
  //   * have the same binning
  //   * have the same dimension
  //   * have the same limits
  //
  //   NOTE: it allows differences in the types (ClassNames)
  //   if you want to check for this use checkHistogramCompatibility directly
  //
  // returns kTRUE if they are compatible to these checks
  // returns kFALSE if not
  // returns also kFALSE, if h1 or h2 is a NULL pointer 

  int val = checkHistogramCompatibility(h1, h2);
  
  if ( -1 < val && val < 100)
    {
      return kTRUE;
    }
  
  return kFALSE;
}

////////////////////////////////////////////////////////////////////////////////

 Bool_t PTools::areArraysCompatible(const TArray* array1, const TArray* array2)
{
  // compares two TArrays 
  // in size, type and values
  //
  // if identical kTRUE is returned
  // else kFALSE
  // returns also kFALSE, if array1 or array2 is a NULL pointer 
  // 
  // supported types are TArrayC, TArrayD, TArrayF, TArrayI, TArrayL, TArrayS
  //
 
  // check for not NULL pointer
  if (!array1 || !array2)
    {
      Error("areArraysCompatible","can't compare, array1 (%p) or array2 (%p) is null pointer, returning -1",array1, array2);
      return -1;
    }

  // size 

  int arraySize1 = array1->GetSize();
  int arraySize2 = array2->GetSize();

  if (arraySize1 != arraySize2) 
    { 
      return kFALSE; 
    }

  // class names
  TString n1 = array1->IsA()->GetName();
  TString n2 = array2->IsA()->GetName();
  
  // type ???
  if (n1.CompareTo(n2))
    {
      return kFALSE;
    }

  // determine type number
  int number = -1;

  if ( array1->IsA()->InheritsFrom("TArrayC") ) { number = 1; }
  if ( array1->IsA()->InheritsFrom("TArrayD") ) { number = 2; }
  if ( array1->IsA()->InheritsFrom("TArrayF") ) { number = 3; }
  if ( array1->IsA()->InheritsFrom("TArrayI") ) { number = 4; }
  if ( array1->IsA()->InheritsFrom("TArrayL") ) { number = 5; }
  if ( array1->IsA()->InheritsFrom("TArrayS") ) { number = 6; }

  // values

  switch(number)
    {
    case 1:
      for ( int index=0; index < arraySize1; index++)
	{
	  if ( ((TArrayC*)array1)->At(index) != ((TArrayC*)array2)->At(index))
	    {
	      return kFALSE;
	    }
	}
      break;
    case 2:
      for ( int index=0; index < arraySize1; index++)
	{
	  if ( ((TArrayD*)array1)->At(index) != ((TArrayD*)array2)->At(index))
	    {
	      return kFALSE;
	    }
	}
      break;
    case 3:
      for ( int index=0; index < arraySize1; index++)
	{
	  if ( ((TArrayF*)array1)->At(index) != ((TArrayF*)array2)->At(index))
	    {
	      return kFALSE;
	    }
	}
      break;
    case 4:
      for ( int index=0; index < arraySize1; index++)
	{
	  if ( ((TArrayI*)array1)->At(index) != ((TArrayI*)array2)->At(index))
	    {
	      return kFALSE;
	    }
	}
      break;
    case 5:
      for ( int index=0; index < arraySize1; index++)
	{
	  if ( ((TArrayL*)array1)->At(index) != ((TArrayL*)array2)->At(index))
	    {
	      return kFALSE;
	    }
	}
      break;
    case 6:
      for ( int index=0; index < arraySize1; index++)
	{
	  if ( ((TArrayS*)array1)->At(index) != ((TArrayS*)array2)->At(index))
	    {
	      return kFALSE;
	    }
	}
      break;
    default:
      ::Error("areArraysCompatible","unsupported type: "%s", returning kFALSE",array1->IsA()->ClassName());
      return kFALSE;
      break;
    }
  return kTRUE;

}

////////////////////////////////////////////////////////////////////////////////

 TGraphErrors* PTools::fillGraphErr(TH1 *hist, TString name, TString position, Bool_t xerrors)
{
  // fills an TH1 histogramm hist to a TGraphError
  // depending on position
  // the x value is chosen 
  // "center" or "middle": in the middle of the bin
  // "low" or "left"     : at the lower edge of the bin
  // "up" or "right"     : at the upper edge of the bin
  //
  // if name is set, name is assigned as the objects name, otherwise "_graph" is put to the name of hist
  //
  // if xerrors is set xerrors are taken as 50% of the bin width
  //
  // returns pointer to TGraphError
  // if hist does not exists,
  //   NULL pointer ist returned
  // if invalid position is chosen (case insensitive)
  //   NULL pointer ist returned

  if (!hist)
    {
      Error(" fillGraphErr","hist is NULL, returning NULL pointer");
      return NULL;
    }

  if (name.IsNull())
    {
      name=hist->GetName();
      name+="_graph";
    }

  position.ToLower();
  int swit = -1;
  if (!position.CompareTo("center")) {swit=1;}
  if (!position.CompareTo("middle")) {swit=1;}
  if (!position.CompareTo("low"))    {swit=2;}
  if (!position.CompareTo("left"))   {swit=2;}
  if (!position.CompareTo("up"))     {swit=3;}
  if (!position.CompareTo("right"))  {swit=3;}

  if (swit == -1)
    {
      Error("fillGraphErr",
	    "no valid position name %s (center,middle,low,left,up,right) chosen, returning NULL",
	    position.Data());
      return NULL;
    }

  Int_t nbinsx = hist->GetNbinsX();

  TArrayD xval(nbinsx);
  TArrayD yval(nbinsx);
  TArrayD xerrval(nbinsx);
  TArrayD yerrval(nbinsx);

  Int_t bin;

  for (int binx=1; binx <= nbinsx; binx++)
    {
      bin = hist->GetBin(binx);
      yval[bin-1] = hist->GetBinContent(bin);
      yerrval[bin-1] = hist->GetBinError(bin);
      xerrval[bin-1] = 0.5*hist->GetBinWidth(bin);
      
      switch(swit)
	{
	case 1: // center middle
	  xval[bin-1] = hist->GetXaxis()->GetBinCenter(bin);
	  break;
	case 2: // left low
	  xval[bin-1] = hist->GetXaxis()->GetBinLowEdge(bin);
	  break;
	case 3: // right up
	  xval[bin-1] = hist->GetXaxis()->GetBinUpEdge(bin);
	  break;
	}
    }


  TGraphErrors* graph = NULL;
  if (xerrors)
    {
      graph = new TGraphErrors(nbinsx, 
			       xval.GetArray(), 
			       yval.GetArray(), 
			       xerrval.GetArray(),  
			       yerrval.GetArray());
    }
  else
    {
      graph = new TGraphErrors(nbinsx, 
			       xval.GetArray(), 
			       yval.GetArray(), 
			       0,  
			       yerrval.GetArray());
    }

  return graph;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStats(TH1 *hist, Bool_t quiet)
{
  // returns for a given (plotted) histogramm the pointer to the statistics TPaveStat
  
  if (hist)
    {
      TPaveStats* stats = ((TPaveStats*) hist->GetListOfFunctions()->FindObject("stats"));
      if (stats)
	{
	  return stats;
	}
      else
	{
	  if (! quiet) {::Error("getHistStats","stats do not exists, returning NULL pointer");}
	  return stats;
	}
    }
  else
    {
      ::Error("getHistStats","histogram is NULL pointer, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStats(TPad* pad, TString name, Bool_t quiet, Bool_t noUpdate)
{
  // returns for a given TCanvas/TPad pointer to the statistics TPaveStat of a
  // histogram with name "name"
  // before calling getHistStats(hist) a pad->Update() is executed
  // 

  if (pad)
    {
      if (!noUpdate) pad->Update();
      return getHistStats(((TH1*) pad->FindObject(name.Data())), quiet);
    }  
  else
    {
      if (!quiet){::Error("getHistStats()","pad does not exist, returning NULL pointer");}
      return NULL;
    }
}


////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsYPosNDC(TH1 *hist, Double_t y1, Double_t y2)
{
  // sets y1 and y2 position in NDC coordinates of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	stats->SetY1NDC(y1);
	stats->SetY2NDC(y2);
      }
    else
      {
	::Warning("setHistStatsYPosNDC","couldn't change position");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsYPosNDC(TPad* pad, TString name, Double_t y1, Double_t y2)
{
  // sets y1 and y2 position in NDC coordinates of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return setHistStatsYPosNDC(((TH1*) pad->FindObject(name.Data())),y1,y2);
    }  
  else
    {
      ::Error("setHistStatsYPosNDC()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsXPosNDC(TH1 *hist, Double_t x1, Double_t x2)
{
  // sets x1 and x2 position in NDC coordinates of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	stats->SetX1NDC(x1);
	stats->SetX2NDC(x2);
      }
    else
      {
	::Warning("setHistStatsXPosNDC","couldn't change position");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsXPosNDC(TPad* pad, TString name, Double_t x1, Double_t x2)
{
  // sets x1 and x2 position in NDC coordinates of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return setHistStatsXPosNDC(((TH1*) pad->FindObject(name.Data())),x1,x2);
    }  
  else
    {
      ::Error("setHistStatsXPosNDC()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsPosNDC(TH1 *hist, Double_t x1, Double_t x2, Double_t y1, Double_t y2)
{
  // sets x1,y1 and x2,y2 position in NDC coordinates of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	stats->SetX1NDC(x1);
	stats->SetX2NDC(x2);
	stats->SetY1NDC(y1);
	stats->SetY2NDC(y2);
      }
    else
      {
	::Warning("setHistStatsPosNDC","couldn't change position");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsPosNDC(TPad* pad, TString name, Double_t x1, Double_t x2, Double_t y1, Double_t y2)
{
  // sets x1,y1 and x2,y2 position in NDC coordinates of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return setHistStatsPosNDC(((TH1*) pad->FindObject(name.Data())),x1,x2,y1,y2);
    }  
  else
    {
      ::Error("setHistStatsPosNDC()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStatsYPosNDC(TH1 *hist, Double_t& y1, Double_t& y2)
{
  // gets y1 and y2 position in NDC coordinates of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	y1 = stats->GetY1NDC();
	y2 = stats->GetY2NDC();
      }
    else
      {
	::Warning("getHistStatsYPosNDC","couldn't change position");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStatsYPosNDC(TPad* pad, TString name, Double_t& y1, Double_t& y2)
{
  // gets y1 and y2 position in NDC coordinates of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return getHistStatsYPosNDC(((TH1*) pad->FindObject(name.Data())),y1,y2);
    }  
  else
    {
      ::Error("getHistStatsYPosNDC()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStatsXPosNDC(TH1 *hist, Double_t& x1, Double_t& x2)
{
  // gets x1 and x2 position in NDC coordinates of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	x1 = stats->GetX1NDC();
	x2 = stats->GetX2NDC();
      }
    else
      {
	::Warning("getHistStatsXPosNDC","couldn't change position");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStatsXPosNDC(TPad* pad, TString name, Double_t& x1, Double_t& x2)
{
  // gets x1 and x2 position in NDC coordinates of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return getHistStatsXPosNDC(((TH1*) pad->FindObject(name.Data())),x1,x2);
    }  
  else
    {
      ::Error("getHistStatsXPosNDC()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStatsPosNDC(TH1 *hist, Double_t& x1, Double_t& x2, Double_t& y1, Double_t& y2)
{
  // gets x1,y1 and x2,y2 position in NDC coordinates of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	x1 = stats->GetX1NDC();
	x2 = stats->GetX2NDC();
	y1 = stats->GetY1NDC();
	y2 = stats->GetY2NDC();
      }
    else
      {
	::Warning("getHistStatsPosNDC","couldn't change position");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::getHistStatsPosNDC(TPad* pad, TString name, Double_t& x1, Double_t& x2, Double_t& y1, Double_t& y2)
{
  // gets x1,y1 and x2,y2 position in NDC coordinates of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return getHistStatsPosNDC(((TH1*) pad->FindObject(name.Data())),x1,x2,y1,y2);
    }  
  else
    {
      ::Error("getHistStatsPosNDC()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsTextColor(TH1 *hist, Int_t color)
{
  // sets text color of stats box of histogramm
  // returns pointer to stats' TPaveStats

  TPaveStats *stats = getHistStats(hist);
    if (stats)
      {
	stats->SetTextColor(color);
      }
    else
      {
	::Warning("setHistStatsTextColorNDC","couldn't change textColorition");
      }
    return stats;
}

////////////////////////////////////////////////////////////////////////////////

 TPaveStats* PTools::setHistStatsTextColor(TPad* pad, TString name, Int_t color)
{
  // sets text color of stats box of histogramm
  // with name "name" in pad 
  // returns pointer to stats' TPaveStats

  if (pad)
    {
      return setHistStatsTextColor(((TH1*) pad->FindObject(name.Data())),color);
    }  
  else
    {
      ::Error("setHistStatsTextColor()","pad does not exist, returning NULL pointer");
      return NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setLatexArts(TLatex * tex, 
			  Double_t x, Double_t y, 
			  Int_t color, Float_t size, Int_t align, 
			  Int_t font, Float_t angle, Bool_t ndc)
{
  // sets attributes of TLatex object tex:
  // x,y positions (choose setLatexArtsNDC for NDC coords)
  // color
  // size
  // alignment
  // font
  // angle
  // ndc: use ndc coordinates
  //
  // see TAttText for detailed information

  if (tex)
    {
      tex->SetNDC(ndc);
      tex->SetX(x);
      tex->SetY(y);
      tex->SetTextColor(color);
      tex->SetTextSize(size);
      tex->SetTextAlign(align);
      tex->SetTextFont(font);
      tex->SetTextAngle(angle);
    }
  else
    {
      ::Error("setLatexArts()","tex pointer does not exist, no changes");
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

 void PTools::setLatexArtsNDC(TLatex * tex, 
			     Double_t x, Double_t y, 
			     Int_t color, Float_t size, Int_t align, 
			     Int_t font, Float_t angle)
{
  // sets attributes of TLatex object tex:
  // x,y positions in NDC coords
  // color
  // size
  // alignment
  // font
  // angle
  // see TAttText for detailed information

  setLatexArts(tex,x,y,color,size,align,font,angle,kTRUE);
}

////////////////////////////////////////////////////////////////////////////////

 Bool_t  PTools::loadMacro(const char *macro)
{
  // loads Macro only if macro has not yet been loaded before
  // returns true if macro is loaded
  // returns true if no action is necessary

    if (!gInterpreter 
	|| 
	(gInterpreter && (!gInterpreter->IsLoaded(macro))))
      {
	gROOT->LoadMacro(macro);
	return kTRUE;
      }
    return kFALSE;
}

////////////////////////////////////////////////////////////////////////////////

 Bool_t  PTools::loadMacro(TString macro)
{
  // loads Macro only if macro has not yet been loaded before
  // returns true if macro is loaded
  // returns true if no action is necessary
  
  return loadMacro(macro.Data());
}

////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::getLinearIndex( Int_t x1, UInt_t x1max, 
			      Int_t x2, UInt_t x2max, 
			      Int_t x3, UInt_t x3max, 
			      Int_t x4, UInt_t x4max, 
			      Int_t x5, UInt_t x5max)
{
  // Translates i.e. array coordinate 0,2,3 of array[3][8][1]
  // in a linear unique coordinate starting from 0
  // 
  // coordinates starting from 0 !!!
  //
  // if x(i) is < 0 then only the x(i-1) coords are taken into account
  // if indizes are out of bounds -1 is returned

  Int_t x[5];
  UInt_t xmax[5];

  x[0] = x1;
  x[1] = x2;
  x[2] = x3;
  x[3] = x4;
  x[4] = x5;

  xmax[0] = x1max;
  xmax[1] = x2max;
  xmax[2] = x3max;
  xmax[3] = x4max;
  xmax[4] = x5max;

  unsigned int dim = 5;
  for (unsigned int iter = 1; iter < dim; iter++)
    {
      if (x[iter] < 0 )
	{
	  dim =iter;

	  for (unsigned fiter = iter-1; fiter < dim-1; fiter++)
	    {
	      x[iter] = 0;
	      xmax[fiter]=0;	      
	    }
	  break;
	}
    }

  for (unsigned int iter = 1; iter < dim; iter++)
    {
      if ((UInt_t) x[iter] >= xmax[iter])
	{
	  cout << x[iter] << endl;
	  cout << xmax[iter] << endl;
	  ::Error("getLinearIndex","index %i out of bounds %i, returning -1",x[iter],xmax[iter]);
	  return -1;
	}
    }

  Int_t index = x[0];
  int add;
  for (unsigned int iter = 1; iter < dim; iter++)
    {
      add = 1;
      for (unsigned int iter2 = 0; iter2 < iter; iter2++)
	{	
	  add *= xmax[iter2];
	}
      index += x[iter]*add;
    }

  return index;  
}

////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::getLinearIndex( Int_t *x, UInt_t *xmax, UInt_t dim)
{
  // Translates i.e. array coordinate 0,2,3 of array[3][8][1]
  // in a linear unique coordinate starting from 0
  // 
  // coordinates starting from 0 !!!
  //
  // if x(i) is < 0 then only the x(i-1) coords are taken into account
  // x is contains the coordinates and has dimension dim
  // xmax are the sizes and is of dimension dim
  // if indizes are out of bounds -1 is returned

  if (x[0]<0)
    {
      ::Error("getLinearIndex","Bad Index return -1");
    }
   

  for (unsigned int iter = 1; iter < dim; iter++)
    {
      if (x[iter] < 0 )
	{
	  for (unsigned fiter = iter-1; fiter < dim-1; fiter++)
	    {
	      x[iter] = 0;
	      xmax[fiter]=0;	      
	    }
	  break;
	}
    }

  for (unsigned int iter = 1; iter < dim; iter++)
    {
      if ((UInt_t) x[iter] >= xmax[iter])
	{
// 	  cout << x[iter] << endl;
// 	  cout << xmax[iter] << endl;
	  ::Error("getLinearIndex","index %i out of bounds %i, returning -1",x[iter],xmax[iter]);
	  return -1;
	}
    }

//   UInt_t index = x[dim-1];
//   for (unsigned int ai = dim-1; ai > 1 ; ai--)
//     {
//       index = x[ai-1] + xmax[ai-1] * index;
//     }

  Int_t index = x[0];
  int add;
  for (unsigned int iter = 1; iter < dim; iter++)
    {
      add = 1;
      for (unsigned int iter2 = 0; iter2 < iter; iter2++)
	{	
	  add *= xmax[iter2];
	}
      index += x[iter]*add;
    }

  return index;  
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatexWC(TString text, Double_t x, Double_t y, 
			     Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y not in NDC but it WC
  // using setLatexArtsNDC
  // returns pointer to new created TLatex object (user must care of removal)
  TLatex *tex   = new TLatex(0,0,text.Data());
  PTools::setLatexArts(tex, x, y, color, size, align, font, angle);
  tex->Draw();
  return tex;
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatexWC(const char* text, Double_t x, Double_t y, 
			   Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y not in NDC but it WC
  // using setLatexArtsNDC
  // returns pointer to new created TLatex object (user must care of removal)
  return drawLatexWC(TString(text), x, y, color, size, align, font, angle);
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatexNDC(const char* text, Double_t x, Double_t y, 
			      Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y in NDC
  // using setLatexArtsNDC
  // returns pointer to new created TLatex object (user must care of removal)
  return drawLatexPadCoords(text, x, y, color , size, align ,font , angle);
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatexNDC(TString text, Double_t x, Double_t y, 
			      Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y in NDC
  // using setLatexArtsNDC
  // returns pointer to new created TLatex object (user must care of removal)
  return drawLatexPadCoords(text, x, y, color , size, align ,font , angle);
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatex(TString text, Double_t x, Double_t y, 
			   Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y in NDC
  // using setLatexArtsNDC
  // returns pointer to new created TLatex object (user must care of removal)
  TLatex *tex   = new TLatex(0,0,text.Data());
  PTools::setLatexArtsNDC(tex, x, y, color, size, align, font, angle);
  tex->Draw();
  return tex;
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatex(const char* text, Double_t x, Double_t y, 
			   Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y in NDC
  // using setLatexArtsNDC
  // returns pointer to new created TLatex object (user must care of removal)
  return drawLatex(TString(text), x, y, color, size, align, font, angle);
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatexPadCoords(TString text, Double_t x, Double_t y, 
				    Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y in NDC
  // using setLatexArts
  // returns pointer to new created TLatex object (user must care of removal)
  TLatex *tex   = new TLatex(0,0,text.Data());
  PTools::setLatexArts(tex, x, y, color, size, align, font, angle);
  tex->Draw();
  return tex;
}

////////////////////////////////////////////////////////////////////////////////

 TLatex * PTools::drawLatexPadCoords(const char* text, Double_t x, Double_t y, 
				    Int_t color, Float_t size, Int_t align, Int_t font, Float_t angle)
{
  // Draws text as TLatex in current pad 
  // at pos x,y in NDC
  // using setLatexArts
  // returns pointer to new created TLatex object (user must care of removal)
  return drawLatexPadCoords(TString(text), x, y, color, size, align, font, angle);
}

////////////////////////////////////////////////////////////////////////////////

 TH1* PTools::getErrorsOfHistogram(TH1 * hist, Bool_t relativeError)
{
  // creates histogram 
  // which contains the errors of hist
  // if an error occurs NULL is returned
  // the name and title of the new histogramm will expanded by "_Error" or "_relError"
  // relativeError is kTRUE then |relativeError| is calculated
  //   (if hist does not contain in a bin the relative error is set to -1)
  // otherwise the absolute error is given

  if (!hist)
    {
      ::Error("getErrorsOfHistogram"," hist is NULL pointer ... return NULL");
      return NULL;
    }

  TH1* err = (TH1*) hist->Clone();
  err->Reset();

  TString name  = hist->GetName();
  TString title = hist->GetTitle();

  if (!relativeError)
    {
      name+="_Error";
      title+="_Error";
    }
  else
    {
      name+="_relError";
      title+="_relError";
    }

  err->SetName(name.Data());
  err->SetTitle(title.Data());

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      if (! relativeError)
		{
		  err->SetBinContent(bin,hist->GetBinError(bin));
		}
	      else
		{
		  if (hist->GetBinContent(bin))
		    {
		     err->SetBinContent(bin,fabs(hist->GetBinError(bin)/hist->GetBinContent(bin)));
		    }
		  else
		    {
		      err->SetBinContent(bin,-1);
		    }
		}
	    }
	}
    }
  return err;

}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setErrorsOfHistogram(TH1 * hist, TH1 *err)
{
  // sets the errors of histogram hist with the bin contents of hist err
  // provided the histograms are compatible
  //
  // if hist or err are NULL pointer, or the histograms are not compatible, 
  // an error message is issued, but nothing happens  
   
  if (!hist)
    {
      ::Error("setErrorsOfHistogram"," hist is NULL pointer ... nothing done");
      return;
    }

  if (!err)
    {
      ::Error("setErrorsOfHistogram"," err is NULL pointer ... nothing done");
      return;
    }

  // compatibility

  int check = checkHistogramCompatibility(hist, err);
  if (check > 0)
    {
      ::Error("setErrorsOfHistogram"," err and hist are not compatible %i ... nothing done",check);
      return;
    }

  //

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      hist->SetBinError(bin, err->GetBinContent(bin));
	    }
	}
    }
}

////////////////////////////////////////////////////////////////////////////////

 TH1* PTools::copyToUnitBinsPlusLabels(TH1* hist , Double_t binningX, Double_t binningY, Double_t binningZ)
{
  // copies any THx histogramm to THxD histograms
  // you have to cast to the corresponding type
  // attaches to name "_THxD"
  // the histogramm has as many bins as the original but a binning of binningXYZ [default =1]

  if (! hist)
    {
      ::Error("copyToUnitBinsPlusLabels","histogram has NULL pointer ... returning NULL");
      return NULL;
    }
  
  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();

  TH1* histD = NULL;

  switch(hist->GetDimension())
    {
    case 1:
      {
	TString name = hist->GetName()+TString("_TH1D");
	histD = new TH1D(name.Data(),hist->GetTitle(),
			 nbinsx,
			 0, 
			 binningX*nbinsx);
	break;
      }
    case 2:
      {
	TString name = hist->GetName()+TString("_TH2D");
	
	histD = new TH2D(name.Data(),hist->GetTitle(),
			 nbinsx,
			 0, 
			 binningX*nbinsx,
			 nbinsy,
			 0, 
			 binningY*nbinsy);
	break;
      }
    case 3:
      {
	TString name = hist->GetName()+TString("_TH3D");

	histD = new TH3D(name.Data(),hist->GetTitle(),
			 nbinsx,
			 0, 
			 binningX*nbinsx,
			 nbinsy,
			 0, 
			 binningY*nbinsy,
			 nbinsz,
			 0, 
			 binningZ*nbinsz);

	break;
      }
    }
  
  importAxisAttributes(hist->GetXaxis(), histD->GetXaxis(), kTRUE);
  importAxisAttributes(hist->GetYaxis(), histD->GetYaxis(), kTRUE);
  importAxisAttributes(hist->GetZaxis(), histD->GetZaxis(), kTRUE);

  histD->SetEntries(hist->GetEntries());
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      histD->SetBinContent(bin, hist->GetBinContent(bin));
	      if (hist->GetSumw2N())
		{
		  histD->SetBinError(bin,hist->GetBinError(bin));
		}
	    }
	}
    }
  return histD;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::substractFromHist(TH1 * hist, Double_t val, Bool_t inverse)
{
  // substracts from each bin of histogram the value val newbin = bin - val
  // if inverse = kTRUE: newbin = val - bin

  if (!hist)
    {
      ::Error("substractFromHist"," hist is NULL pointer ... cannot act on a NULL pointer.");
      return;
    }

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      if (!inverse)
		{
		  hist->SetBinContent(bin,hist->GetBinContent(bin) - val);
		}
	      else
		{
		  hist->SetBinContent(bin,val - hist->GetBinContent(bin));
		}
	    }
	}
    }
  return;

}

////////////////////////////////////////////////////////////////////////////////
 TH1D *PTools::getBinContentDistribution(TH1* hist, Int_t binning, Bool_t excludeUnderAndOverFlowBins)
{
    // returns a pointer to a histogram containing the distribution of the bin contents
    // by default in 1000 bins
    //
    // The histogram range is determined by searching for the minimum and maximum bin content
    // and then setting the output histograms minimum to the found minimum,
    // the maximum to maximum+(maximum - minimum)/binning, i.e. maximum+binWidth
    // this one bin more is accounted for by having not binning, but binning + 1 bins.
    //
    // if hist is NULL ... NULL is returned
    //
    // Also the underflow and overflow bins are by default taken into account
    // -- those can be excluded by setting excludeUnderAndOverFlowBins to kTRUE

    if (!hist)
    {
	::Error("getBinContentDistribution"," hist is NULL pointer ... cannot act on a NULL pointer.");
	return NULL;
    }

    Int_t nbinsx = hist->GetNbinsX();
    Int_t nbinsy = hist->GetNbinsY();
    Int_t nbinsz = hist->GetNbinsZ();

    if (hist->GetDimension()<2) nbinsy = -1;
    if (hist->GetDimension()<3) nbinsz = -1;

    Int_t binx,biny,binz,bin;

    Double_t value;
    Double_t maximum = -FLT_MAX/10;
    Double_t minimum =  FLT_MAX/10;

    for (binz=0;binz<=nbinsz+1;binz++)
    {
	if (excludeUnderAndOverFlowBins && nbinsz != -1 && ( binz == 0 || binz == nbinsz+1)) { continue; }
	for (biny=0;biny<=nbinsy+1;biny++)
	{
	    if (excludeUnderAndOverFlowBins && nbinsy != -1 && ( biny == 0 || biny == nbinsy+1)) { continue; }
	    for (binx=0;binx<=nbinsx+1;binx++)
	    {
		if (excludeUnderAndOverFlowBins && nbinsx != -1 && ( binx == 0 || binx == nbinsx+1)) { continue; }
		bin = hist->GetBin(binx,biny,binz);
		value = hist->GetBinContent(bin);

		if (value > maximum) { maximum = value;}
		if (value < minimum) { minimum = value;}
	    }
	}
    }

    if (binning<1)
    {
	binning=1000;
    }

    TH1D* dist = new TH1D(Form("binContent_of_%s",hist->GetName()),
			  Form("bin content distribution of : %s",hist->GetTitle()),
			  binning+1,minimum,maximum+(maximum-minimum)/binning);
    for (binz=0;binz<=nbinsz+1;binz++)
    {
	if (excludeUnderAndOverFlowBins && nbinsz != -1 && ( binz == 0 || binz == nbinsz+1)) { continue; }
	for (biny=0;biny<=nbinsy+1;biny++)
	{
	    if (excludeUnderAndOverFlowBins && nbinsy != -1 && ( biny == 0 || biny == nbinsy+1)) { continue; }
	    for (binx=0;binx<=nbinsx+1;binx++)
	    {
		if (excludeUnderAndOverFlowBins && nbinsx != -1 && ( binx == 0 || binx == nbinsx+1)) { continue; }
		bin = hist->GetBin(binx,biny,binz);
		dist->Fill(hist->GetBinContent(bin));
	    }
	}
    }
    return dist;
}

////////////////////////////////////////////////////////////////////////////////

 TH1 *PTools::getOneOverHist(TH1* hist)
{
  // returns a pointer to a histogram containing for each bin the value 1/value
  // if value = 0, the ratio is set to 0
  //
  // the name is "OneOverHist" and the title "1/hist"
  // if hist is NULL ... NULL is returned

  if (!hist)
    {
      ::Error("getOneOverHist"," hist is NULL pointer ... cannot act on a NULL pointer.");
      return NULL;
    }

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;

  Double_t value, error;
  
  TH1* inv = (TH1*) copyToTHxD(hist);
  TString name = Form("OneOver_%s",inv->GetName());
  TString title = Form("1./%s",inv->GetTitle());

  inv->SetNameTitle(name.Data(), title.Data());
  inv->Reset();
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      value = hist->GetBinContent(bin);
	      error = hist->GetBinError(bin);
	      inv->SetBinContent(bin,(value==0)?0.:1./value);
	      inv->SetBinError(bin,(pow(value,2)==0)?0.:error/pow(value,2));
	    }
	}
    }
  return inv;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::setHistErrors(TH1* h,TH1* h2)
{
  // sets bincontent of hist h2 as errors of h
  // lent from jochen
  if(h!=0&&h2!=0)
    {
      TString classname=h->ClassName();
      Int_t type=0;
      
      if(classname.Contains("TH1")==1)type=1;
      if(classname.Contains("TH2")==1)type=2;
      
      Int_t binsX=0,binsY=0;
      
      binsX=h->GetNbinsX();
      if(type==2)binsY=h->GetNbinsY();
      
      Double_t bincontent;
      
      if(type==1)
        {
	  for(Int_t x=0;x<=binsX;x++)
            {
	      bincontent= h2->GetBinContent(x+1);
	      h->SetBinError(x+1,bincontent);
            }
        }
      if(type==2)
        {
	  for(Int_t x=0;x<=binsX;x++)
            {
	      for(Int_t y=0;y<=binsY;y++){
		bincontent= h2->GetBinContent(x+1,y+1);
		h->SetBinError(x+1,y+1,bincontent);
	      }
            }
        }
    }
    else
      {
        cout<<"Warning: PTools::cleanHist : ZERO pointer for hist recieved!"<<endl;
      }
}
////////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////////


// TH1* PTools::divide(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2, Option_t *option)
// {
//   // following calculation
//   //
//   // h1 = c1*h1/(c2*h2)
//   //
//   //   if errors are defined (see TH1::Sumw2), errors are also recalculated
//   //   Note that if h1 or h2 have Sumw2 set, Sumw2 is automatically called for this
//   //   if not already set.
//   //   The resulting errors are calculated assuming uncorrelated histograms.
//   //   However, if option ="B" is specified, Binomial errors are computed.
//   //
//   // IMPORTANT NOTE: If you intend to use the errors of this histogram later
//   // you should call Sumw2 before making this operation.
//   // This is particularly important if you fit the histogram after TH1::Divide

//    TString opt = option;
//    opt.ToLower();
//    Bool_t binomial = kFALSE;
//    if (opt.Contains("b")) binomial = kTRUE;

//   if (!h1)
//     {
//       ::Error("setErrorsOfHistogram"," h1 is NULL pointer ... nothing done");
//       return;
//     }

//   if (!h2)
//     {
//       ::Error("setErrorsOfHistogram"," h2 is NULL pointer ... nothing done");
//       return;
//     }

//   // compatibility

//   int check = checkHistogramCompatibility(h1, h2);
//   if (check > 0)
//     {
//       ::Error("setErrorsOfHistogram"," h2 and h1 are not compatible %i ... nothing done",check);
//       return;
//     }

//   //

//   Int_t nbinsx = h1->GetNbinsX();
//   Int_t nbinsy = h1->GetNbinsY();
//   Int_t nbinsz = h1->GetNbinsZ();
  
//   if (h1->GetDimension()<2) nbinsy = -1;
//   if (h1->GetDimension()<3) nbinsz = -1;

//   //    Create Sumw2 if h1 or h2 have Sumw2 set
//   if (h1->GetSumw2N() == 0 || h2->GetSumw2N() != 0) h1->Sumw2();
//   if (h1->GetSumw2N() != 0 || h2->GetSumw2N() == 0) h2->Sumw2();

//   //    Reset the kCanRebin option. Otherwise SetBinContent on the overflow bin
//   //    would resize the axis limits!
//   ResetBit(kCanRebin);

//    Int_t bin, binx, biny, binz;
//    Double_t b1,b2,w,d1,d2;
//    d1 = c1*c1;
//    d2 = c2*c2;
//    for (binz=0;binz<=nbinsz+1;binz++) {
//       for (biny=0;biny<=nbinsy+1;biny++) {
//          for (binx=0;binx<=nbinsx+1;binx++) {
//             bin = binx +(nbinsx+2)*(biny + (nbinsy+2)*binz);
//             b1  = h1->GetBinContent(bin);
//             b2  = h2->GetBinContent(bin);
//             if (b2) w = c1*b1/(c2*b2);
//             else    w = 0;
//             SetBinContent(bin,w);
//             fEntries++;
//             if (fSumw2.fN) {
//                Double_t e1 = h1->GetBinError(bin);
//                Double_t e2 = h2->GetBinError(bin);
//                Double_t b22= b2*b2*d2;
//                if (!b2) { fSumw2.fArray[bin] = 0; continue;}
//                if (binomial) {
//                   fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/b2);
//                } else {
//                   fSumw2.fArray[bin] = d1*d2*(e1*e1*b2*b2 + e2*e2*b1*b1)/(b22*b22);
//                }
//             }
//          }
//       }
//    }

//   Int_t binx,biny,binz,bin;

//   for (binz=0;binz<=nbinsz+1;binz++)
//     {
//       for (biny=0;biny<=nbinsy+1;biny++)
// 	{
// 	  for (binx=0;binx<=nbinsx+1;binx++)
// 	    {
// 	      bin = hist->GetBin(binx,biny,binz);
// 	      hist->SetBinError(bin, err->GetBinContent(bin));
// 	    }
// 	}
//     }
// }


//   // modified Divide from TH1 of 400-08 
// //   -*-*-*Replace contents of this histogram by the division of h1 by h2*-*-*
// //         ==============================================================
// //
// //   hist = c1*h1/(c2*h2)
// //

// //   - Reset statistics
//    Double_t nEntries = fEntries;
//    fEntries = fTsumw = 0;

//    SetMinimum();
//    SetMaximum();

// //   - Loop on bins (including underflows/overflows)


//    Stat_t s[10];
//    GetStats(s);
//    PutStats(s);
//    if (nEntries == 0) nEntries = h1->GetEntries();
//    if (nEntries == 0) nEntries = 1;
//    SetEntries(nEntries);
// }


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

 TH2D *PTools::reBinHistX(TH2* hist,Int_t factor)
{
  // returns a pointer to a histogram containing for each bin the value 1/value
  // if value = 0, the ratio is set to 0
  //
  // the name is "OneOverHist" and the title "1/hist"
  // if hist is NULL ... NULL is returned

  if (!hist)
    {
      ::Error("getOneOverHist"," hist is NULL pointer ... cannot act on a NULL pointer.");
      return NULL;
    }

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin=0;

  Double_t value, error;
  
  TString name = hist->GetName();
  name+="_rebin";

  TH2D* inv = new TH2D(name.Data(),name.Data(),
		       int (nbinsx/factor), hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax(),
		       int (nbinsy), hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax());
  
  importAxisAttributes(hist->GetXaxis(), inv->GetXaxis(), kTRUE);
  importAxisAttributes(hist->GetYaxis(), inv->GetYaxis(), kTRUE);
  importAxisAttributes(hist->GetZaxis(), inv->GetZaxis(), kTRUE);

  inv->Reset();
  Int_t index=0;

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      if (binx==0 || binx == nbinsx+1)
		{
		  bin = hist->GetBin(binx,biny,binz);
		  value = hist->GetBinContent(bin);
		  error = hist->GetBinError(bin);
		  inv->SetBinContent(bin,(value==0)?0.:1./value);
		  inv->SetBinError(bin,(pow(value,2)==0)?0.:error/pow(value,2));
		}
	      else
		{
		  value=0;
		  error=0;
		  for (Int_t fctr=0; fctr < factor; fctr++)
		    {
		      if (fctr==nbinsx+1) {break;}
		      
		      bin    = hist->GetBin(binx+fctr,biny,binz);
		      value += hist->GetBinContent(bin);
		      error += pow(hist->GetBinError(bin),2);
		    }
		  inv->SetBinContent(index,value);
		  inv->SetBinError(index,::std::sqrt(error));
		  binx+=(factor-1);
		}
	      index++;
	    }
	}
    }
  inv->SetStats(0);
  return inv;
}

////////////////////////////////////////////////////////////////////////////////

 void PTools::cleanHistogramPtyOnP(TH2 * hist, Double_t mass, Double_t min, Double_t max, Double_t replaceBy)
{
  // cleans histograms
  // bin contents out of the limits for p min and max 
  // are set to replaceBy
  // errors are set to error 0
  // mass of particle needed 

  if (!hist)
    {
      ::Error("cleanHistogram"," hist is NULL pointer ... return NULL");
      return;
    }

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  nbinsz = -1;

  Int_t binx,biny,binz,bin;
  Double_t p=0.;
  Double_t pt;
  Double_t y;

  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  pt = hist->GetYaxis()->GetBinCenter(biny);
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      y = hist->GetXaxis()->GetBinCenter(binx);
	      p = sinh(y)*::std::sqrt(2 *(pow(pt,2)+pow(mass,2)));

	      if (p < min || p > max)
		{
		  hist->SetBinContent(bin,replaceBy);
		  hist->SetBinError(bin,0);
		}
	    }
	}
    }
}

////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::findEndOfDistribution(TH1* hist, Int_t min, Double_t threshold, Bool_t compact)
{
  // returns bin number where distribution ends 
  // i.e where no data is beyond threshold
  // starting from left to right at bin number min
  // returns -1 if hist is NULL
  // if compact is set no bin larger min is accepted to be below threshold
  // otherwise wholes of 1 bins are allowed

  if (!hist)
    {
      ::Error("findEndOfDistribution"," hist is NULL pointer ... return -1");
      return -1;
    }

  if (min<1) {min=1;}

  Int_t nbinsx = hist->GetNbinsX();

  Int_t binIter;

  for (binIter=min; binIter<=nbinsx; binIter++)
    {
      if (hist->GetBinContent(binIter) > threshold) { continue;}
      if (compact)
	{
	  if ((binIter+1 > nbinsx) ||(hist->GetBinContent(binIter+1) <= threshold)) break;
	}
      else
	{
	  if ( ((binIter+1 > nbinsx) ||(hist->GetBinContent(binIter+1) <= threshold)) &&
	       ((binIter+2 > nbinsx) ||(hist->GetBinContent(binIter+2) <= threshold))) break;
	}
    }
  return binIter;
} 

////////////////////////////////////////////////////////////////////////////////

 Int_t PTools::findBeginOfDistribution(TH1* hist, Int_t max, Double_t threshold, Bool_t compact)
{
  // returns bin number where distribution begins 
  // i.e where no data is beyond threshold
  // starting from right to left at bin number max
  // returns -1 if hist is NULL
  // if compact is set no bin smaller than max is accepted to be below threshold
  // otherwise wholes of 1 bins are allowed

  if (!hist)
    {
      ::Error("findBeginOfDistribution"," hist is NULL pointer ... return -1");
      return -1;
    }

  Int_t nbinsx = hist->GetNbinsX();

  Int_t binIter;
  if (max>nbinsx) { max = nbinsx; }

  for (binIter=max; binIter>0; binIter--)
    {
      if (hist->GetBinContent(binIter) > threshold) { continue;}
      if (compact)
	{
	  if ( ((binIter-1 <= 0) ||(hist->GetBinContent(binIter-1) <= threshold))) break;
	}
      else
	{
	  if ( ((binIter-1 <= 0) ||(hist->GetBinContent(binIter-1) <= threshold)) &&
	       ((binIter-2 <= 0) ||(hist->GetBinContent(binIter-2) <= threshold))) break;
	}

    }
  return binIter;
} 

////////////////////////////////////////////////////////////////////////////////

 void PTools::scaleHistErrors(TH1* hist, Double_t scaleFactor)
{
  // scales Errors of hist by scaleFactor
  
  if (!hist)
    {
      ::Error("scaleHistErrors"," hist is NULL pointer ... cannot act on a NULL pointer.");
      return;
    }

  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();
  
  if (hist->GetDimension()<2) nbinsy = -1;
  if (hist->GetDimension()<3) nbinsz = -1;

  Int_t binx,biny,binz,bin;

  Double_t error;
  
  for (binz=0;binz<=nbinsz+1;binz++)
    {
      for (biny=0;biny<=nbinsy+1;biny++)
	{
	  for (binx=0;binx<=nbinsx+1;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      error = hist->GetBinError(bin);
	      hist->SetBinError(bin,hist->GetBinError(bin)*scaleFactor);
	    }
	}
    }
  return;
}

////////////////////////////////////////////////////////////////////////////////

 TH1* PTools::copyBinSubsetOfHist(TH1* hist, 
					Int_t xbinmin, Int_t xbinmax, 
					Int_t ybinmin, Int_t ybinmax, 
					Int_t zbinmin, Int_t zbinmax  
					)
{
  // copies subsection of any THx histogramm hist to THxD histograms
  // you have to speciy via xbinmin [default:-1], xbinmax [default:-1], 
  //                        ybinmin [default:-1], ybinmax [default:-1], 
  //                        zbinmin [default:-1], zbinmax [default:-1]
  // the bin range you want to select
  // (NOTE: To choose the coordinates you have to use ((TAxis*)hist->GetXaxis())->FindBin(value); )
  // (NOTE: you have to cast to the corresponding type of histogram)
  //
  // attaches to name "_subset_X_xminbin-xmaxbin"
  //                  "_subset_X_xminbin-xmaxbin_Y_yminbin-ymaxbin"
  //                  "_subset_X_xminbin-xmaxbin_Y_yminbin-ymaxbin_Z_zminbin-zmaxbin
  //
  // if hist is NULL, NULL is returned
  // in case dimension doesn't match with bin minima and maxima dimensions
  // the choice is ignored.
  // if xbinmin, xbinmax, ybinmin, yzbinmax, zbinmin, yxbinmax are negativ the full range is taken
  // if minima > maxima NULL is returned
  //
  // The entries are copied from the original histogram, because they cannot calculated 
  
  // check for valid histogram pointer
  if (! hist)
    {
      ::Error("copyBinSubsetOfHist","histogram has NULL pointer ... returning NULL");
      return NULL;
    }

  // check for valid limit order / excluding negativ values for full range
  if ( xbinmin > xbinmax && xbinmax > 0) 
    {
      ::Error("copyBinSubsetOfHist","invalid choice of bin ranges xmin (%i) > xmax (%i) ... returning NULL",
	      xbinmin, xbinmax);
      return NULL;
    }
  if ( ybinmin > ybinmax && ybinmax > 0) 
    {
      ::Error("copyBinSubsetOfHist","invalid choice of bin ranges ymin (%i) > ymax (%i) ... returning NULL",
	      ybinmin, ybinmax);
      return NULL;
    }
  if ( zbinmin > zbinmax && zbinmax > 0) 
    {
      ::Error("copyBinSubsetOfHist","invalid choice of bin ranges zmin (%i) > zmax (%i) ... returning NULL",
	      zbinmin, zbinmax);
      return NULL;
    }
  
  // get number of bins
  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();

  // get dimension;
  Int_t dimension = hist->GetDimension();

  // check if choice exceeds maximum bin
 if (dimension >= 1)
    {
      if ( xbinmax > nbinsx )
	{
	  ::Error("copyBinSubsetOfHist","xbinmax: %i exceeds histograms bin range of %i ... returning NULL"
		  , xbinmax, nbinsx);
	  return NULL;
	}
    }

 if (dimension >= 2)
    {
      if ( ybinmax > nbinsy )
	{
	  ::Error("copyBinSubsetOfHist","ybinmax: %i exceeds histograms bin range of %i ... returning NULL"
		  , ybinmax, nbinsy);
	  return NULL;
	}
    }
  if (dimension >= 3)
    {
      if ( zbinmax > nbinsz )
	{
	  ::Error("copyBinSubsetOfHist","zbinmax: %i exceeds histograms bin range of %i ... returning NULL"
		  , zbinmax, nbinsz);
	  return NULL;
	}
    }


  // if ranges are negativ take maximum/minimum possible value;
  if (xbinmin < 0 ) xbinmin = 0;
  if (xbinmax < 0 ) xbinmax = nbinsx+1;
  if (ybinmin < 0 ) ybinmin = 0;
  if (ybinmax < 0 ) ybinmax = nbinsy+1;
  if (zbinmin < 0 ) zbinmin = 0;
  if (zbinmax < 0 ) zbinmax = nbinsz+1;

  if (dimension<2) {nbinsy = -1; ybinmin=0; ybinmax=0;}
  if (dimension<3) {nbinsz = -1; zbinmin=0; zbinmax=0;}

  // create new histogram
  TString name;
  TString title;
  TH1* histD = NULL;

  switch(dimension)
    {
    case 1:
      {
	name = Form("%s_subset_X_%i-%i",
		    hist->GetName(),
		    (xbinmin==0       )? 1     :xbinmin,
		    (xbinmax==nbinsx+1)? nbinsx:xbinmax);
	title = Form("%s ( subset X: bin %i - bin %i )",
		     hist->GetTitle(),
		    (xbinmin==0       )? 1     :xbinmin,
		    (xbinmax==nbinsx+1)? nbinsx:xbinmax);
	histD = new TH1D(name.Data(),title.Data(),
			 xbinmax-xbinmin+1,
			 hist->GetXaxis()->GetBinLowEdge(xbinmin), 
			 hist->GetXaxis()->GetBinUpEdge (xbinmax)
			 );
	break;
      }
    case 2:
      {
	name = Form("%s_subset_X_%i-%i_Y_%i-%i",
		    hist->GetName(),
		    (xbinmin==0       )? 1     :xbinmin,
		    (xbinmax==nbinsx+1)? nbinsx:xbinmax,
		    (ybinmin==0       )? 1     :ybinmin,
		    (ybinmax==nbinsy+1)? nbinsy:ybinmax);
	title = Form("%s ( subset X: bin %i - bin %i, Y: bin %i - bin %i )",
		     hist->GetTitle(),
		     (xbinmin==0       )? 1     :xbinmin,
		     (xbinmax==nbinsx+1)? nbinsx:xbinmax,
		     (ybinmin==0       )? 1     :ybinmin,
		     (ybinmax==nbinsy+1)? nbinsy:ybinmax);
	histD = new TH2D(name.Data(),title.Data(),
			 xbinmax-xbinmin+1,
			 hist->GetXaxis()->GetBinLowEdge(xbinmin), 
			 hist->GetXaxis()->GetBinUpEdge (xbinmax),
			 ybinmax-ybinmin+1,
			 hist->GetYaxis()->GetBinLowEdge(ybinmin), 
			 hist->GetYaxis()->GetBinUpEdge (ybinmax)
			 );
	break;
      }
    case 3:
      {
	name = Form("%s_subset_X_%i-%i_Y_%i-%i_Z_%i-%i",
		    hist->GetName(),
		    (xbinmin==0       )? 1     :xbinmin,
		    (xbinmax==nbinsx+1)? nbinsx:xbinmax,
		    (ybinmin==0       )? 1     :ybinmin,
		    (ybinmax==nbinsy+1)? nbinsy:ybinmax,
		    (zbinmin==0       )? 1     :zbinmin,
		    (zbinmax==nbinsz+1)? nbinsz:zbinmax);
	title = Form("%s ( subset X: bin %i - bin %i, Y: bin %i - bin %i, Z: bin %i - bin %i )",
		     hist->GetTitle(),
		    (xbinmin==0       )? 1     :xbinmin,
		    (xbinmax==nbinsx+1)? nbinsx:xbinmax,
		    (ybinmin==0       )? 1     :ybinmin,
		    (ybinmax==nbinsy+1)? nbinsy:ybinmax,
		    (zbinmin==0       )? 1     :zbinmin,
		    (zbinmax==nbinsz+1)? nbinsz:zbinmax);
	histD = new TH3D(name.Data(),title.Data(),
			 xbinmax-xbinmin+1,
			 hist->GetXaxis()->GetBinLowEdge(xbinmin), 
			 hist->GetXaxis()->GetBinUpEdge (xbinmax),
			 ybinmax-ybinmin+1,
			 hist->GetYaxis()->GetBinLowEdge(ybinmin), 
			 hist->GetYaxis()->GetBinUpEdge (ybinmax),
			 zbinmax-zbinmin+1,
			 hist->GetZaxis()->GetBinLowEdge(zbinmin), 
			 hist->GetZaxis()->GetBinUpEdge (zbinmax)
			 );
	break;
      }
    default:
      {
	::Error("copyBinSubsetOfHist","invalid dimension: %i ... returning NULL",dimension);
	return NULL;
	break;
      }
    }
  
  // copy axis attributes
  importAxisAttributes(hist->GetXaxis(), histD->GetXaxis(), kTRUE);
  importAxisAttributes(hist->GetYaxis(), histD->GetYaxis(), kTRUE);
  importAxisAttributes(hist->GetZaxis(), histD->GetZaxis(), kTRUE);

  // misc settings
  histD->SetEntries(hist->GetEntries());
  if (hist->GetSumw2N()) {hist->Sumw2();}

  Int_t binx,biny,binz,bin,newbin;
  
  for (binz=zbinmin;binz<=zbinmax;binz++)
    {
      for (biny=ybinmin;biny<=ybinmax;biny++)
	{
	  for (binx=xbinmin;binx<=xbinmax;binx++)
	    {
	      bin = hist->GetBin(binx,biny,binz);
	      newbin = histD->GetBin(
				     histD->GetXaxis()->FindBin( hist->GetXaxis()->GetBinCenter(binx)),
				     histD->GetYaxis()->FindBin( hist->GetYaxis()->GetBinCenter(biny)),
				     histD->GetZaxis()->FindBin( hist->GetZaxis()->GetBinCenter(binz))
				     );
	      histD->SetBinContent(newbin, hist->GetBinContent(bin));
	      if (hist->GetSumw2N())
		{
		  histD->SetBinError(newbin,hist->GetBinError(bin));
		}
	    }
	}
    }
  return histD;
}

////////////////////////////////////////////////////////////////////////////////
const Double_t PTools::copySubsetOfHistDefaultValue = -1.35791e-300;

 TH1* PTools::copySubsetOfHist(TH1* hist,  
			      Double_t xmin, Double_t xmax, 
			      Double_t ymin, Double_t ymax, 
			      Double_t zmin, Double_t zmax  
			      )
{
  // copies subsection of any THx histogramm hist to THxD histograms
  // you have to speciy via xmin [default: PTools::copySubsetOfHistDefaultValue], 
  //                        xmax [default: PTools::copySubsetOfHistDefaultValue], 
  //                        ymin [default: PTools::copySubsetOfHistDefaultValue], 
  //                        ymax [default: PTools::copySubsetOfHistDefaultValue], 
  //                        zmin [default: PTools::copySubsetOfHistDefaultValue], 
  //                        zmax [default: PTools::copySubsetOfHistDefaultValue]
  // the range you want to select
  // via ((TAxis*)hist->GetXaxis())->FindBin(value); the corresponding bin range is calculated
  //
  // Following copyBinSubsetOfHist is called and afterwards the name and title of the histogram are just adopted
  // 
  //          to name "_subset_X_xmin-xmax"
  //                  "_subset_X_xmin-xmax_Y_ymin-ymax"
  //                  "_subset_X_xmin-xmax_Y_ymin-ymax_Z_zmin-zmax
  //
  // if hist is NULL, NULL is returned
  // in case dimension doesn't match with bin minima and maxima dimensions
  // the choice is ignored.
  // if xbinmin, xbinmax, ybinmin, yzbinmax, zbinmin, yxbinmax are PTools::copySubsetOfHistDefaultValue
  // the full range is taken
  // if minima > maxima NULL is returned
  //
  // The entries are copied from the original histogram, because they cannot calculated 
  //
  // (NOTE: you have to cast to the corresponding type of histogram)

  // check for valid histogram pointer
  if (! hist)
    {
      ::Error("copySubsetOfHist","histogram has NULL pointer ... returning NULL");
      return NULL;
    }
  
  Int_t dimension = hist->GetDimension();
  Int_t xbinmin=-1,xbinmax=-1,ybinmin=-1,ybinmax=-1,zbinmin=-1,zbinmax=-1;

  // get number of bins
  Int_t nbinsx = hist->GetNbinsX();
  Int_t nbinsy = hist->GetNbinsY();
  Int_t nbinsz = hist->GetNbinsZ();

  if (dimension > 0)
    {
      xbinmin = (xmin==PTools::copySubsetOfHistDefaultValue) ? -1 : hist->GetXaxis()->FindBin(xmin);
      // overflow/underflow bin check
      if (xbinmin<1 || xbinmin>nbinsx)
	{
	  ::Error("copySubsetOfHist","xmin: %f exceeds range of x-axis [%f,%f] ... returning NULL",
		  hist->GetXaxis()->GetBinLowEdge(1),hist->GetXaxis()->GetBinUpEdge(nbinsx));
	  return NULL;
	}
      xbinmax = (xmax==PTools::copySubsetOfHistDefaultValue) ? -1 : hist->GetXaxis()->FindBin(xmax);
      // overflow/underflow bin check
      if (xbinmax<1 || xbinmax>nbinsx)
	{
	  ::Error("copySubsetOfHist","xmax: %f exceeds range of x-axis [%f,%f] ... returning NULL",
		  hist->GetXaxis()->GetBinLowEdge(1),hist->GetXaxis()->GetBinUpEdge(nbinsx));
	  return NULL;
	}
      if (xbinmax!=-1) xbinmax--;
    }
  if (dimension > 1)
    {
      ybinmin = (ymin==PTools::copySubsetOfHistDefaultValue) ? -1 : hist->GetYaxis()->FindBin(ymin);
      // overflow/underflow bin check
      if (ybinmin<1 || ybinmin>nbinsy)
	{
	  ::Error("copySubsetOfHist","ymin: %f exceeds range of y-axis [%f,%f] ... returning NULL",
		  hist->GetYaxis()->GetBinLowEdge(1),hist->GetYaxis()->GetBinUpEdge(nbinsy));
	  return NULL;
	}
      ybinmax = (ymax==PTools::copySubsetOfHistDefaultValue) ? -1 : hist->GetYaxis()->FindBin(ymax);
      // overflow/underflow bin check
      if (ybinmax<1 || ybinmax>nbinsy)
	{
	  ::Error("copySubsetOfHist","ymax: %f exceeds range of y-axis [%f,%f] ... returning NULL",
		  hist->GetYaxis()->GetBinLowEdge(1),hist->GetYaxis()->GetBinUpEdge(nbinsy));
	  return NULL;
	}
      if (ybinmax!=-1) ybinmax--;
    }
  if (dimension > 2)
    {
      zbinmin = (zmin==PTools::copySubsetOfHistDefaultValue) ? -1 : hist->GetZaxis()->FindBin(zmin);
      // overflow/underflow bin check
      if (zbinmin<1 || zbinmin>nbinsz)
	{
	  ::Error("copySubsetOfHist","zmin: %f exceeds range of z-axis [%f,%f] ... returning NULL",
		  hist->GetZaxis()->GetBinLowEdge(1),hist->GetZaxis()->GetBinUpEdge(nbinsz));
	  return NULL;
	}
      zbinmax = (zmax==PTools::copySubsetOfHistDefaultValue) ? -1 : hist->GetZaxis()->FindBin(zmax);
      // overflow/underflow bin check
      if (zbinmax<1 || zbinmax>nbinsz)
	{
	  ::Error("copySubsetOfHist","zmax: %f exceeds range of z-axis [%f,%f] ... returning NULL",
		  hist->GetZaxis()->GetBinLowEdge(1),hist->GetZaxis()->GetBinUpEdge(nbinsz));
	  return NULL;
	}
      if (ybinmax!=-1) zbinmax--;
    }

  TH1* histD = copyBinSubsetOfHist(hist, xbinmin, xbinmax, ybinmin, ybinmax, zbinmin, zbinmax);  

  // check for valid pointer
  if (!histD) return NULL;

  // rename histogram

  // create new histogram
  TString name;
  TString title;

  switch(dimension)
    {
    case 1:
      {
	name = Form("%s_subset_X_%2.2g-%2.2g",
		    hist->GetName(),
		    (xbinmin==0       )? hist->GetXaxis()->GetBinLowEdge(1)     :xmin,
		    (xbinmax==nbinsx+1)? hist->GetXaxis()->GetBinLowEdge(nbinsx):xmax);
	title = Form("%s ( subset X:  %2.2g -  %2.2g )",
		     hist->GetTitle(),
		    (xbinmin==0       )? hist->GetXaxis()->GetBinLowEdge(1)     :xmin,
		    (xbinmax==nbinsx+1)? hist->GetXaxis()->GetBinLowEdge(nbinsx):xmax);
	break;
      }
    case 2:
      {
	name = Form("%s_subset_X_%2.2g-%2.2g_Y_%2.2g-%2.2g",
		    hist->GetName(),
		    (xbinmin==0       )? hist->GetXaxis()->GetBinLowEdge(1)     :xmin,
		    (xbinmax==nbinsx+1)? hist->GetXaxis()->GetBinLowEdge(nbinsx):xmax,
		    (ybinmin==0       )? hist->GetYaxis()->GetBinLowEdge(1)     :ymin,
		    (ybinmax==nbinsy+1)? hist->GetYaxis()->GetBinLowEdge(nbinsy):ymax);
	title = Form("%s ( subset X:  %2.2g -  %2.2g, Y:  %2.2g -  %2.2g )",
		     hist->GetTitle(),
		     (xbinmin==0       )? hist->GetXaxis()->GetBinLowEdge(1)     :xmin,
		     (xbinmax==nbinsx+1)? hist->GetXaxis()->GetBinLowEdge(nbinsx):xmax,
		     (ybinmin==0       )? hist->GetYaxis()->GetBinLowEdge(1)     :ymin,
		     (ybinmax==nbinsy+1)? hist->GetYaxis()->GetBinLowEdge(nbinsy):ymax);
	break;
      }
    case 3:
      {
	name = Form("%s_subset_X_%2.2g-%2.2g_Y_%2.2g-%2.2g_Z_%2.2g-%2.2g",
		    hist->GetName(),
		    (xbinmin==0       )? hist->GetXaxis()->GetBinLowEdge(1)     :xmin,
		    (xbinmax==nbinsx+1)? hist->GetXaxis()->GetBinLowEdge(nbinsx):xmax,
		    (ybinmin==0       )? hist->GetYaxis()->GetBinLowEdge(1)     :ymin,
		    (ybinmax==nbinsy+1)? hist->GetYaxis()->GetBinLowEdge(nbinsy):ymax,
		    (zbinmin==0       )? hist->GetZaxis()->GetBinLowEdge(1)     :zmin,
		    (zbinmax==nbinsz+1)? hist->GetZaxis()->GetBinLowEdge(nbinsz):zmax);
	title = Form("%s ( subset X: %2.2g - %2.2g, Y:  %2.2g -  %2.2g, Z:  %2.2g -  %2.2g )",
		     hist->GetTitle(),
		    (xbinmin==0       )? hist->GetXaxis()->GetBinLowEdge(1)     :xmin,
		    (xbinmax==nbinsx+1)? hist->GetXaxis()->GetBinLowEdge(nbinsx):xmax,
		    (ybinmin==0       )? hist->GetYaxis()->GetBinLowEdge(1)     :ymin,
		    (ybinmax==nbinsy+1)? hist->GetYaxis()->GetBinLowEdge(nbinsy):ymax,
		    (zbinmin==0       )? hist->GetZaxis()->GetBinLowEdge(1)     :zmin,
		    (zbinmax==nbinsz+1)? hist->GetZaxis()->GetBinLowEdge(nbinsz):zmax);
	break;
      }
    default:
      {
	::Error("copySubsetOfHist","invalid dimension: %i ... returning NULL",dimension);
	return NULL;
	break;
      }
    }

  histD->SetNameTitle(name.Data(),title.Data());

  return histD;
}


ROOT page - Class index - Class Hierarchy - 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.