ROOT logo
// @(#)root/hist:$Id: TH3.cxx 32491 2010-03-08 07:15:22Z brun $
// Author: Rene Brun   27/10/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TROOT.h"
#include "TClass.h"
#include "THashList.h"
#include "TH3.h"
#include "TProfile2D.h"
#include "TH2.h"
#include "TF1.h"
#include "TVirtualPad.h"
#include "TVirtualHistPainter.h"
#include "THLimitsFinder.h"
#include "TRandom.h"
#include "TError.h"
#include "TMath.h"
#include "TObjString.h"

ClassImp(TH3)

//______________________________________________________________________________
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*
//*-*  The 3-D histogram classes derived from the 1-D histogram classes.
//*-*  all operations are supported (fill, fit).
//*-*  Drawing is currently restricted to one single option.
//*-*  A cloud of points is drawn. The number of points is proportional to
//*-*  cell content.
//*-*
//
//  TH3C a 3-D histogram with one byte per cell (char)
//  TH3S a 3-D histogram with two bytes per cell (short integer)
//  TH3I a 3-D histogram with four bytes per cell (32 bits integer)
//  TH3F a 3-D histogram with four bytes per cell (float)
//  TH3D a 3-D histogram with eight bytes per cell (double)
//
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

//______________________________________________________________________________
TH3::TH3()
{
   // Default constructor.
   fDimension   = 3;
   fTsumwy      = fTsumwy2 = fTsumwxy = 0;
   fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
}

//______________________________________________________________________________
TH3::TH3(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
                                     ,Int_t nbinsy,Double_t ylow,Double_t yup
                                     ,Int_t nbinsz,Double_t zlow,Double_t zup)
     :TH1(name,title,nbinsx,xlow,xup),
      TAtt3D()
{
//*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
//*-*              ==================================================

   fDimension   = 3;
   if (nbinsy <= 0) nbinsy = 1;
   if (nbinsz <= 0) nbinsz = 1;
   fYaxis.Set(nbinsy,ylow,yup);
   fZaxis.Set(nbinsz,zlow,zup);
   fNcells      = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
   fTsumwy      = fTsumwy2 = fTsumwxy = 0;
   fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
}

//______________________________________________________________________________
TH3::TH3(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
                                           ,Int_t nbinsy,const Float_t *ybins
                                           ,Int_t nbinsz,const Float_t *zbins)
     :TH1(name,title,nbinsx,xbins),
      TAtt3D()
{
//*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
//*-*            =======================================================
   fDimension   = 3;
   if (nbinsy <= 0) nbinsy = 1;
   if (nbinsz <= 0) nbinsz = 1;
   if (ybins) fYaxis.Set(nbinsy,ybins);
   else       fYaxis.Set(nbinsy,0,1);
   if (zbins) fZaxis.Set(nbinsz,zbins);
   else       fZaxis.Set(nbinsz,0,1);
   fNcells      = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
   fTsumwy      = fTsumwy2 = fTsumwxy = 0;
   fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
}

//______________________________________________________________________________
TH3::TH3(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
                                           ,Int_t nbinsy,const Double_t *ybins
                                           ,Int_t nbinsz,const Double_t *zbins)
     :TH1(name,title,nbinsx,xbins),
      TAtt3D()
{
//*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
//*-*            =======================================================
   fDimension   = 3;
   if (nbinsy <= 0) nbinsy = 1;
   if (nbinsz <= 0) nbinsz = 1;
   if (ybins) fYaxis.Set(nbinsy,ybins);
   else       fYaxis.Set(nbinsy,0,1);
   if (zbins) fZaxis.Set(nbinsz,zbins);
   else       fZaxis.Set(nbinsz,0,1);
   fNcells      = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
   fTsumwy      = fTsumwy2 = fTsumwxy = 0;
   fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
}

//______________________________________________________________________________
TH3::TH3(const TH3 &h) : TH1(), TAtt3D()
{
   // Copy constructor.
   // The list of functions is not copied. (Use Clone if needed)

   ((TH3&)h).Copy(*this);
}

//______________________________________________________________________________
TH3::~TH3()
{
   // Destructor.
}

//______________________________________________________________________________
void TH3::Copy(TObject &obj) const
{
   // Copy.

   TH1::Copy(obj);
   ((TH3&)obj).fTsumwy      = fTsumwy;
   ((TH3&)obj).fTsumwy2     = fTsumwy2;
   ((TH3&)obj).fTsumwxy     = fTsumwxy;
   ((TH3&)obj).fTsumwz      = fTsumwz;
   ((TH3&)obj).fTsumwz2     = fTsumwz2;
   ((TH3&)obj).fTsumwxz     = fTsumwxz;
   ((TH3&)obj).fTsumwyz     = fTsumwyz;
}

//______________________________________________________________________________
Int_t TH3::BufferEmpty(Int_t action)
{
   // Fill histogram with all entries in the buffer.
   // action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
   // action =  0 histogram is filled from the buffer
   // action =  1 histogram is filled and buffer is deleted
   //             The buffer is automatically deleted when the number of entries
   //             in the buffer is greater than the number of entries in the histogram

   // do we need to compute the bin size?
   if (!fBuffer) return 0;
   Int_t nbentries = (Int_t)fBuffer[0];
   if (!nbentries) return 0;
   Double_t *buffer = fBuffer;
   if (nbentries < 0) {
      if (action == 0) return 0;
      nbentries  = -nbentries;
      fBuffer=0;
      Reset();
      fBuffer = buffer;
   }
   if (TestBit(kCanRebin) || fXaxis.GetXmax() <= fXaxis.GetXmin() ||
      fYaxis.GetXmax() <= fYaxis.GetXmin() ||
      fZaxis.GetXmax() <= fZaxis.GetXmin()) {
         //find min, max of entries in buffer
         Double_t xmin = fBuffer[2];
         Double_t xmax = xmin;
         Double_t ymin = fBuffer[3];
         Double_t ymax = ymin;
         Double_t zmin = fBuffer[4];
         Double_t zmax = zmin;
         for (Int_t i=1;i<nbentries;i++) {
            Double_t x = fBuffer[4*i+2];
            if (x < xmin) xmin = x;
            if (x > xmax) xmax = x;
            Double_t y = fBuffer[4*i+3];
            if (y < ymin) ymin = y;
            if (y > ymax) ymax = y;
            Double_t z = fBuffer[4*i+4];
            if (z < zmin) zmin = z;
            if (z > zmax) zmax = z;
         }
         if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin() || fZaxis.GetXmax() <= fZaxis.GetXmin()) {
            THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax,zmin,zmax);
         } else {
            fBuffer = 0;
            Int_t keep = fBufferSize; fBufferSize = 0;
            if (xmin <  fXaxis.GetXmin()) RebinAxis(xmin,&fXaxis);
            if (xmax >= fXaxis.GetXmax()) RebinAxis(xmax,&fXaxis);
            if (ymin <  fYaxis.GetXmin()) RebinAxis(ymin,&fYaxis);
            if (ymax >= fYaxis.GetXmax()) RebinAxis(ymax,&fYaxis);
            if (zmin <  fZaxis.GetXmin()) RebinAxis(zmin,&fZaxis);
            if (zmax >= fZaxis.GetXmax()) RebinAxis(zmax,&fZaxis);
            fBuffer = buffer;
            fBufferSize = keep;
         }
   }
   fBuffer = 0;

   for (Int_t i=0;i<nbentries;i++) {
      Fill(buffer[4*i+2],buffer[4*i+3],buffer[4*i+4],buffer[4*i+1]);
   }
   fBuffer = buffer;

   if (action > 0) { delete [] fBuffer; fBuffer = 0; fBufferSize = 0;}
   else {
      if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
      else                              fBuffer[0] = 0;
   }
   return nbentries;
}

//______________________________________________________________________________
Int_t TH3::BufferFill(Double_t x, Double_t y, Double_t z, Double_t w)
{
   // accumulate arguments in buffer. When buffer is full, empty the buffer
   // fBuffer[0] = number of entries in buffer
   // fBuffer[1] = w of first entry
   // fBuffer[2] = x of first entry
   // fBuffer[3] = y of first entry
   // fBuffer[4] = z of first entry

   if (!fBuffer) return -3;
   Int_t nbentries = (Int_t)fBuffer[0];
   if (nbentries < 0) {
      nbentries  = -nbentries;
      fBuffer[0] =  nbentries;
      if (fEntries > 0) {
         Double_t *buffer = fBuffer; fBuffer=0;
         Reset();
         fBuffer = buffer;
      }
   }
   if (4*nbentries+4 >= fBufferSize) {
      BufferEmpty(1);
      return Fill(x,y,z,w);
   }
   fBuffer[4*nbentries+1] = w;
   fBuffer[4*nbentries+2] = x;
   fBuffer[4*nbentries+3] = y;
   fBuffer[4*nbentries+4] = z;
   fBuffer[0] += 1;
   return -3;
}

//______________________________________________________________________________
Int_t TH3::Fill(Double_t x, Double_t y, Double_t z)
{
   //*-*-*-*-*-*-*-*-*-*-*Increment cell defined by x,y,z by 1 *-*-*-*-*
   //*-*                  ====================================
   //*-*
   //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

   if (fBuffer) return BufferFill(x,y,z,1);

   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(x);
   biny = fYaxis.FindBin(y);
   binz = fZaxis.FindBin(z);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin);
   if (fSumw2.fN) ++fSumw2.fArray[bin];
   if (binx == 0 || binx > fXaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }

   if (biny == 0 || biny > fYaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (binz == 0 || binz > fZaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   ++fTsumw;
   ++fTsumw2;
   fTsumwx  += x;
   fTsumwx2 += x*x;
   fTsumwy  += y;
   fTsumwy2 += y*y;
   fTsumwxy += x*y;
   fTsumwz  += z;
   fTsumwz2 += z*z;
   fTsumwxz += x*z;
   fTsumwyz += y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(Double_t x, Double_t y, Double_t z, Double_t w)
{
   //*-*-*-*-*-*-*-*-*-*-*Increment cell defined by x,y,z by a weight w*-*-*-*-*
   //*-*                  =============================================
   //*-*
   //*-* If the storage of the sum of squares of weights has been triggered,
   //*-* via the function Sumw2, then the sum of the squares of weights is incremented
   //*-* by w^2 in the cell corresponding to x,y,z.
   //*-*
   //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

   if (fBuffer) return BufferFill(x,y,z,w);

   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(x);
   biny = fYaxis.FindBin(y);
   binz = fZaxis.FindBin(z);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (biny == 0 || biny > fYaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (binz == 0 || binz > fZaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   fTsumw   += w;
   fTsumw2  += w*w;
   fTsumwx  += w*x;
   fTsumwx2 += w*x*x;
   fTsumwy  += w*y;
   fTsumwy2 += w*y*y;
   fTsumwxy += w*x*y;
   fTsumwz  += w*z;
   fTsumwz2 += w*z*z;
   fTsumwxz += w*x*z;
   fTsumwyz += w*y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(const char *namex, const char *namey, const char *namez, Double_t w)
{
   // Increment cell defined by namex,namey,namez by a weight w
   //
   // If the storage of the sum of squares of weights has been triggered,
   // via the function Sumw2, then the sum of the squares of weights is incremented
   // by w^2 in the cell corresponding to x,y,z.
   //
   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(namex);
   biny = fYaxis.FindBin(namey);
   binz = fZaxis.FindBin(namez);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
   if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
   if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
   Double_t x = fXaxis.GetBinCenter(binx);
   Double_t y = fYaxis.GetBinCenter(biny);
   Double_t z = fZaxis.GetBinCenter(binz);
   Double_t v = (w > 0 ? w : -w);
   fTsumw   += v;
   fTsumw2  += v*v;
   fTsumwx  += v*x;
   fTsumwx2 += v*x*x;
   fTsumwy  += v*y;
   fTsumwy2 += v*y*y;
   fTsumwxy += v*x*y;
   fTsumwz  += v*z;
   fTsumwz2 += v*z*z;
   fTsumwxz += v*x*z;
   fTsumwyz += v*y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(const char *namex, Double_t y, const char *namez, Double_t w)
{
   // Increment cell defined by namex,y,namez by a weight w
   //
   // If the storage of the sum of squares of weights has been triggered,
   // via the function Sumw2, then the sum of the squares of weights is incremented
   // by w^2 in the cell corresponding to x,y,z.
   //
   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(namex);
   biny = fYaxis.FindBin(y);
   binz = fZaxis.FindBin(namez);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
   if (biny == 0 || biny > fYaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
   Double_t x = fXaxis.GetBinCenter(binx);
   Double_t z = fZaxis.GetBinCenter(binz);
   Double_t v = (w > 0 ? w : -w);
   fTsumw   += v;
   fTsumw2  += v*v;
   fTsumwx  += v*x;
   fTsumwx2 += v*x*x;
   fTsumwy  += v*y;
   fTsumwy2 += v*y*y;
   fTsumwxy += v*x*y;
   fTsumwz  += v*z;
   fTsumwz2 += v*z*z;
   fTsumwxz += v*x*z;
   fTsumwyz += v*y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(const char *namex, const char *namey, Double_t z, Double_t w)
{
   // Increment cell defined by namex,namey,z by a weight w
   //
   // If the storage of the sum of squares of weights has been triggered,
   // via the function Sumw2, then the sum of the squares of weights is incremented
   // by w^2 in the cell corresponding to x,y,z.
   //
   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(namex);
   biny = fYaxis.FindBin(namey);
   binz = fZaxis.FindBin(z);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
   if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
   if (binz == 0 || binz > fZaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   Double_t x = fXaxis.GetBinCenter(binx);
   Double_t y = fYaxis.GetBinCenter(biny);
   Double_t v = (w > 0 ? w : -w);
   fTsumw   += v;
   fTsumw2  += v*v;
   fTsumwx  += v*x;
   fTsumwx2 += v*x*x;
   fTsumwy  += v*y;
   fTsumwy2 += v*y*y;
   fTsumwxy += v*x*y;
   fTsumwz  += v*z;
   fTsumwz2 += v*z*z;
   fTsumwxz += v*x*z;
   fTsumwyz += v*y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(Double_t x, const char *namey, const char *namez, Double_t w)
{
   // Increment cell defined by x,namey,namezz by a weight w
   //
   // If the storage of the sum of squares of weights has been triggered,
   // via the function Sumw2, then the sum of the squares of weights is incremented
   // by w^2 in the cell corresponding to x,y,z.
   //
   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(x);
   biny = fYaxis.FindBin(namey);
   binz = fZaxis.FindBin(namez);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
   if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
   Double_t y = fYaxis.GetBinCenter(biny);
   Double_t z = fZaxis.GetBinCenter(binz);
   Double_t v = (w > 0 ? w : -w);
   fTsumw   += v;
   fTsumw2  += v*v;
   fTsumwx  += v*x;
   fTsumwx2 += v*x*x;
   fTsumwy  += v*y;
   fTsumwy2 += v*y*y;
   fTsumwxy += v*x*y;
   fTsumwz  += v*z;
   fTsumwz2 += v*z*z;
   fTsumwxz += v*x*z;
   fTsumwyz += v*y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(Double_t x, const char *namey, Double_t z, Double_t w)
{
   // Increment cell defined by x,namey,z by a weight w
   //
   // If the storage of the sum of squares of weights has been triggered,
   // via the function Sumw2, then the sum of the squares of weights is incremented
   // by w^2 in the cell corresponding to x,y,z.
   //
   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(x);
   biny = fYaxis.FindBin(namey);
   binz = fZaxis.FindBin(z);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
   if (binz == 0 || binz > fZaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   Double_t y = fYaxis.GetBinCenter(biny);
   Double_t v = (w > 0 ? w : -w);
   fTsumw   += v;
   fTsumw2  += v*v;
   fTsumwx  += v*x;
   fTsumwx2 += v*x*x;
   fTsumwy  += v*y;
   fTsumwy2 += v*y*y;
   fTsumwxy += v*x*y;
   fTsumwz  += v*z;
   fTsumwz2 += v*z*z;
   fTsumwxz += v*x*z;
   fTsumwyz += v*y*z;
   return bin;
}

//______________________________________________________________________________
Int_t TH3::Fill(Double_t x, Double_t y, const char *namez, Double_t w)
{
   // Increment cell defined by x,y,namez by a weight w
   //
   // If the storage of the sum of squares of weights has been triggered,
   // via the function Sumw2, then the sum of the squares of weights is incremented
   // by w^2 in the cell corresponding to x,y,z.
   //
   Int_t binx, biny, binz, bin;
   fEntries++;
   binx = fXaxis.FindBin(x);
   biny = fYaxis.FindBin(y);
   binz = fZaxis.FindBin(namez);
   bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
   AddBinContent(bin,w);
   if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
   if (binx == 0 || binx > fXaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (biny == 0 || biny > fYaxis.GetNbins()) {
      if (!fgStatOverflows) return -1;
   }
   if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
   Double_t z = fZaxis.GetBinCenter(binz);
   Double_t v = (w > 0 ? w : -w);
   fTsumw   += v;
   fTsumw2  += v*v;
   fTsumwx  += v*x;
   fTsumwx2 += v*x*x;
   fTsumwy  += v*y;
   fTsumwy2 += v*y*y;
   fTsumwxy += v*x*y;
   fTsumwz  += v*z;
   fTsumwz2 += v*z*z;
   fTsumwxz += v*x*z;
   fTsumwyz += v*y*z;
   return bin;
}

//______________________________________________________________________________
void TH3::FillRandom(const char *fname, Int_t ntimes)
{
   //*-*-*-*-*-*-*Fill histogram following distribution in function fname*-*-*-*
   //*-*          =======================================================
   //*-*
   //*-*   The distribution contained in the function fname (TF1) is integrated
   //*-*   over the channel contents.
   //*-*   It is normalized to 1.
   //*-*   Getting one random number implies:
   //*-*     - Generating a random number between 0 and 1 (say r1)
   //*-*     - Look in which bin in the normalized integral r1 corresponds to
   //*-*     - Fill histogram channel
   //*-*   ntimes random numbers are generated
   //*-*
   //*-*  One can also call TF1::GetRandom to get a random variate from a function.
   //*-*
   //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*

   Int_t bin, binx, biny, binz, ibin, loop;
   Double_t r1, x, y,z, xv[3];
   //*-*- Search for fname in the list of ROOT defined functions
   TF1 *f1 = (TF1*)gROOT->GetFunction(fname);
   if (!f1) { Error("FillRandom", "Unknown function: %s",fname); return; }

   //*-*- Allocate temporary space to store the integral and compute integral
   Int_t nbinsx = GetNbinsX();
   Int_t nbinsy = GetNbinsY();
   Int_t nbinsz = GetNbinsZ();
   Int_t nxy    = nbinsx*nbinsy;
   Int_t nbins  = nxy*nbinsz;

   Double_t *integral = new Double_t[nbins+1];
   ibin = 0;
   integral[ibin] = 0;
   for (binz=1;binz<=nbinsz;binz++) {
      xv[2] = fZaxis.GetBinCenter(binz);
      for (biny=1;biny<=nbinsy;biny++) {
         xv[1] = fYaxis.GetBinCenter(biny);
         for (binx=1;binx<=nbinsx;binx++) {
            xv[0] = fXaxis.GetBinCenter(binx);
            ibin++;
            integral[ibin] = integral[ibin-1] + f1->Eval(xv[0],xv[1],xv[2]);
         }
      }
   }

   //*-*- Normalize integral to 1
   if (integral[nbins] == 0 ) {
      Error("FillRandom", "Integral = zero"); return;
   }
   for (bin=1;bin<=nbins;bin++)  integral[bin] /= integral[nbins];

   //*-*--------------Start main loop ntimes
   if (fDimension < 2) nbinsy = -1;
   if (fDimension < 3) nbinsz = -1;
   for (loop=0;loop<ntimes;loop++) {
      r1 = gRandom->Rndm(loop);
      ibin = TMath::BinarySearch(nbins,&integral[0],r1);
      binz = ibin/nxy;
      biny = (ibin - nxy*binz)/nbinsx;
      binx = 1 + ibin - nbinsx*(biny + nbinsy*binz);
      if (nbinsz) binz++;
      if (nbinsy) biny++;
      x    = fXaxis.GetBinCenter(binx);
      y    = fYaxis.GetBinCenter(biny);
      z    = fZaxis.GetBinCenter(binz);
      Fill(x,y,z, 1.);
   }
   delete [] integral;
}

//______________________________________________________________________________
void TH3::FillRandom(TH1 *h, Int_t ntimes)
{
   //*-*-*-*-*-*-*Fill histogram following distribution in histogram h*-*-*-*
   //*-*          ====================================================
   //*-*
   //*-*   The distribution contained in the histogram h (TH3) is integrated
   //*-*   over the channel contents.
   //*-*   It is normalized to 1.
   //*-*   Getting one random number implies:
   //*-*     - Generating a random number between 0 and 1 (say r1)
   //*-*     - Look in which bin in the normalized integral r1 corresponds to
   //*-*     - Fill histogram channel
   //*-*   ntimes random numbers are generated
   //*-*
   //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*

   if (!h) { Error("FillRandom", "Null histogram"); return; }
   if (fDimension != h->GetDimension()) {
      Error("FillRandom", "Histograms with different dimensions"); return;
   }

   if (h->ComputeIntegral() == 0) return;

   TH3 *h3 = (TH3*)h;
   Int_t loop;
   Double_t x,y,z;
   for (loop=0;loop<ntimes;loop++) {
      h3->GetRandom3(x,y,z);
      Fill(x,y,z,1.);
   }
}


//______________________________________________________________________________
Int_t TH3::FindFirstBinAbove(Double_t threshold, Int_t axis) const
{
   //find first bin with content > threshold for axis (1=x, 2=y, 3=z)
   //if no bins with content > threshold is found the function returns -1.
   
   if (axis < 1 || axis > 3) {
      Warning("FindFirstBinAbove","Invalid axis number : %d, axis x assumed\n",axis);
      axis = 1;
   }
   Int_t nbinsx = fXaxis.GetNbins();
   Int_t nbinsy = fYaxis.GetNbins();
   Int_t nbinsz = fZaxis.GetNbins();
   Int_t binx, biny, binz;
   if (axis == 1) {
      for (binx=1;binx<=nbinsx;binx++) {
         for (biny=1;biny<=nbinsy;biny++) {
            for (binz=1;binz<=nbinsz;binz++) {
               if (GetBinContent(binx,biny,binz) > threshold) return binx;
            }
         }
      }
   } else if (axis == 2) {
      for (biny=1;biny<=nbinsy;biny++) {
         for (binx=1;binx<=nbinsx;binx++) {
            for (binz=1;binz<=nbinsz;binz++) {
               if (GetBinContent(binx,biny,binz) > threshold) return biny;
            }
         }
      }
   } else {
      for (binz=1;binz<=nbinsz;binz++) {
         for (binx=1;binx<=nbinsx;binx++) {
            for (biny=1;biny<=nbinsy;biny++) {
               if (GetBinContent(binx,biny,binz) > threshold) return binz;
            }
         }
      }
   }
   return -1;
}


//______________________________________________________________________________
Int_t TH3::FindLastBinAbove(Double_t threshold, Int_t axis) const
{
   //find last bin with content > threshold for axis (1=x, 2=y, 3=z)
   //if no bins with content > threshold is found the function returns -1.
   
   if (axis < 1 || axis > 3) {
      Warning("FindLastBinAbove","Invalid axis number : %d, axis x assumed\n",axis);
      axis = 1;
   }
   Int_t nbinsx = fXaxis.GetNbins();
   Int_t nbinsy = fYaxis.GetNbins();
   Int_t nbinsz = fZaxis.GetNbins();
   Int_t binx, biny, binz;
   if (axis == 1) {
      for (binx=nbinsx;binx>=1;binx--) {
         for (biny=1;biny<=nbinsy;biny++) {
            for (binz=1;binz<=nbinsz;binz++) {
               if (GetBinContent(binx,biny,binz) > threshold) return binx;
            }
         }
      }
   } else if (axis == 2) {
      for (biny=nbinsy;biny>=1;biny--) {
         for (binx=1;binx<=nbinsx;binx++) {
            for (binz=1;binz<=nbinsz;binz++) {
               if (GetBinContent(binx,biny,binz) > threshold) return biny;
            }
         }
      }
   } else {
      for (binz=nbinsz;binz>=1;binz--) {
         for (binx=1;binx<=nbinsx;binx++) {
            for (biny=1;biny<=nbinsy;biny++) {
               if (GetBinContent(binx,biny,binz) > threshold) return binz;
            }
         }
      }
   }
   return -1;
}


//______________________________________________________________________________
void TH3::FitSlicesZ(TF1 *f1, Int_t binminx, Int_t binmaxx, Int_t binminy, Int_t binmaxy, Int_t cut, Option_t *option)
{
   // Project slices along Z in case of a 3-D histogram, then fit each slice
   // with function f1 and make a 2-d histogram for each fit parameter
   // Only cells in the bin range [binminx,binmaxx] and [binminy,binmaxy] are considered.
   // if f1=0, a gaussian is assumed
   // Before invoking this function, one can set a subrange to be fitted along Z
   // via f1->SetRange(zmin,zmax)
   // The argument option (default="QNR") can be used to change the fit options.
   //     "Q" means Quiet mode
   //     "N" means do not show the result of the fit
   //     "R" means fit the function in the specified function range
   //
   // Note that the generated histograms are added to the list of objects
   // in the current directory. It is the user's responsability to delete
   // these histograms.
   //
   //  Example: Assume a 3-d histogram h3
   //   Root > h3->FitSlicesZ(); produces 4 TH2D histograms
   //          with h3_0 containing parameter 0(Constant) for a Gaus fit
   //                    of each cell in X,Y projected along Z
   //          with h3_1 containing parameter 1(Mean) for a gaus fit
   //          with h3_2 containing parameter 2(RMS)  for a gaus fit
   //          with h3_chi2 containing the chisquare/number of degrees of freedom for a gaus fit
   //
   //   Root > h3->Fit(0,15,22,0,0,10);
   //          same as above, but only for bins 15 to 22 along X
   //          and only for cells in X,Y for which the corresponding projection
   //          along Z has more than cut bins filled.
   //
   //  NOTE: To access the generated histograms in the current directory, do eg:
   //     TH2D *h3_1 = (TH2D*)gDirectory->Get("h3_1");

   Int_t nbinsx  = fXaxis.GetNbins();
   Int_t nbinsy  = fYaxis.GetNbins();
   Int_t nbinsz  = fZaxis.GetNbins();
   if (binminx < 1) binminx = 1;
   if (binmaxx > nbinsx) binmaxx = nbinsx;
   if (binmaxx < binminx) {binminx = 1; binmaxx = nbinsx;}
   if (binminy < 1) binminy = 1;
   if (binmaxy > nbinsy) binmaxy = nbinsy;
   if (binmaxy < binminy) {binminy = 1; binmaxy = nbinsy;}

   //default is to fit with a gaussian
   if (f1 == 0) {
      f1 = (TF1*)gROOT->GetFunction("gaus");
      if (f1 == 0) f1 = new TF1("gaus","gaus",fZaxis.GetXmin(),fZaxis.GetXmax());
      else         f1->SetRange(fZaxis.GetXmin(),fZaxis.GetXmax());
   }
   const char *fname = f1->GetName();
   Int_t npar = f1->GetNpar();
   Double_t *parsave = new Double_t[npar];
   f1->GetParameters(parsave);

   //Create one 2-d histogram for each function parameter
   Int_t ipar;
   char name[80], title[80];
   TH2D *hlist[25];
   const TArrayD *xbins = fXaxis.GetXbins();
   const TArrayD *ybins = fYaxis.GetXbins();
   for (ipar=0;ipar<npar;ipar++) {
      sprintf(name,"%s_%d",GetName(),ipar);
      sprintf(title,"Fitted value of par[%d]=%s",ipar,f1->GetParName(ipar));
      if (xbins->fN == 0) {
         hlist[ipar] = new TH2D(name, title,
                                nbinsx, fXaxis.GetXmin(), fXaxis.GetXmax(),
                                nbinsy, fYaxis.GetXmin(), fYaxis.GetXmax());
      } else {
         hlist[ipar] = new TH2D(name, title,
                                nbinsx, xbins->fArray,
                                nbinsy, ybins->fArray);
      }
      hlist[ipar]->GetXaxis()->SetTitle(fXaxis.GetTitle());
      hlist[ipar]->GetYaxis()->SetTitle(fYaxis.GetTitle());
   }
   sprintf(name,"%s_chi2",GetName());
   TH2D *hchi2 = new TH2D(name,"chisquare", nbinsx, fXaxis.GetXmin(), fXaxis.GetXmax()
      , nbinsy, fYaxis.GetXmin(), fYaxis.GetXmax());

   //Loop on all cells in X,Y generate a projection along Z
   TH1D *hpz = new TH1D("R_temp","_temp",nbinsz, fZaxis.GetXmin(), fZaxis.GetXmax());
   Int_t bin,binx,biny,binz;
   for (biny=binminy;biny<=binmaxy;biny++) {
      Float_t y = fYaxis.GetBinCenter(biny);
      for (binx=binminx;binx<=binmaxx;binx++) {
         Float_t x = fXaxis.GetBinCenter(binx);
         hpz->Reset();
         Int_t nfill = 0;
         for (binz=1;binz<=nbinsz;binz++) {
            bin = GetBin(binx,biny,binz);
            Float_t w = GetBinContent(bin);
            if (w == 0) continue;
            hpz->Fill(fZaxis.GetBinCenter(binz),w);
            hpz->SetBinError(binz,GetBinError(bin));
            nfill++;
         }
         if (nfill < cut) continue;
         f1->SetParameters(parsave);
         hpz->Fit(fname,option);
         Int_t npfits = f1->GetNumberFitPoints();
         if (npfits > npar && npfits >= cut) {
            for (ipar=0;ipar<npar;ipar++) {
               hlist[ipar]->Fill(x,y,f1->GetParameter(ipar));
               hlist[ipar]->SetCellError(binx,biny,f1->GetParError(ipar));
            }
            hchi2->Fill(x,y,f1->GetChisquare()/(npfits-npar));
         }
      }
   }
   delete [] parsave;
   delete hpz;
}

//______________________________________________________________________________
Double_t TH3::GetBinWithContent3(Double_t c, Int_t &binx, Int_t &biny, Int_t &binz, Int_t firstx, Int_t lastx, Int_t firsty, Int_t lasty, Int_t firstz, Int_t lastz, Double_t maxdiff) const
{
   // compute first cell (binx,biny,binz) in the range [firstx,lastx](firsty,lasty][firstz,lastz] for which
   // diff = abs(cell_content-c) <= maxdiff
   // In case several cells in the specified range with diff=0 are found
   // the first cell found is returned in binx,biny,binz.
   // In case several cells in the specified range satisfy diff <=maxdiff
   // the cell with the smallest difference is returned in binx,biny,binz.
   // In all cases the function returns the smallest difference.
   //
   // NOTE1: if firstx <= 0, firstx is set to bin 1
   //        if (lastx < firstx then firstx is set to the number of bins in X
   //        ie if firstx=0 and lastx=0 (default) the search is on all bins in X.
   //        if firsty <= 0, firsty is set to bin 1
   //        if (lasty < firsty then firsty is set to the number of bins in Y
   //        ie if firsty=0 and lasty=0 (default) the search is on all bins in Y.
   //        if firstz <= 0, firstz is set to bin 1
   //        if (lastz < firstz then firstz is set to the number of bins in Z
   //        ie if firstz=0 and lastz=0 (default) the search is on all bins in Z.
   // NOTE2: if maxdiff=0 (default), the first cell with content=c is returned.

   if (fDimension != 3) {
      binx = 0;
      biny = 0;
      binz = 0;
      Error("GetBinWithContent3","function is only valid for 3-D histograms");
      return 0;
   }
   if (firstx <= 0) firstx = 1;
   if (lastx < firstx) lastx = fXaxis.GetNbins();
   if (firsty <= 0) firsty = 1;
   if (lasty < firsty) lasty = fYaxis.GetNbins();
   if (firstz <= 0) firstz = 1;
   if (lastz < firstz) lastz = fZaxis.GetNbins();
   Int_t binminx = 0, binminy=0, binminz=0;
   Double_t diff, curmax = 1.e240;
   for (Int_t k=firstz;k<=lastz;k++) {
      for (Int_t j=firsty;j<=lasty;j++) {
         for (Int_t i=firstx;i<=lastx;i++) {
            diff = TMath::Abs(GetBinContent(i,j,k)-c);
            if (diff <= 0) {binx = i; biny=j; binz=k; return diff;}
            if (diff < curmax && diff <= maxdiff) {curmax = diff, binminx=i; binminy=j;binminz=k;}
         }
      }
   }
   binx = binminx;
   biny = binminy;
   binz = binminz;
   return curmax;
}

//______________________________________________________________________________
Double_t TH3::GetCorrelationFactor(Int_t axis1, Int_t axis2) const
{
   //*-*-*-*-*-*-*-*Return correlation factor between axis1 and axis2*-*-*-*-*
   //*-*            ====================================================
   if (axis1 < 1 || axis2 < 1 || axis1 > 3 || axis2 > 3) {
      Error("GetCorrelationFactor","Wrong parameters");
      return 0;
   }
   if (axis1 == axis2) return 1;
   Double_t rms1 = GetRMS(axis1);
   if (rms1 == 0) return 0;
   Double_t rms2 = GetRMS(axis2);
   if (rms2 == 0) return 0;
   return GetCovariance(axis1,axis2)/rms1/rms2;
}

//______________________________________________________________________________
Double_t TH3::GetCovariance(Int_t axis1, Int_t axis2) const
{
   //*-*-*-*-*-*-*-*Return covariance between axis1 and axis2*-*-*-*-*
   //*-*            ====================================================

   if (axis1 < 1 || axis2 < 1 || axis1 > 3 || axis2 > 3) {
      Error("GetCovariance","Wrong parameters");
      return 0;
   }
   Double_t stats[11];
   GetStats(stats);
   Double_t sumw   = stats[0];
   Double_t sumw2  = stats[1];
   Double_t sumwx  = stats[2];
   Double_t sumwx2 = stats[3];
   Double_t sumwy  = stats[4];
   Double_t sumwy2 = stats[5];
   Double_t sumwxy = stats[6];
   Double_t sumwz  = stats[7];
   Double_t sumwz2 = stats[8];
   Double_t sumwxz = stats[9];
   Double_t sumwyz = stats[10];

   if (sumw == 0) return 0;
   if (axis1 == 1 && axis2 == 1) {
      return TMath::Abs(sumwx2/sumw - sumwx*sumwx/sumw2);
   }
   if (axis1 == 2 && axis2 == 2) {
      return TMath::Abs(sumwy2/sumw - sumwy*sumwy/sumw2);
   }
   if (axis1 == 3 && axis2 == 3) {
      return TMath::Abs(sumwz2/sumw - sumwz*sumwz/sumw2);
   }
   if ((axis1 == 1 && axis2 == 2) || (axis1 == 2 && axis1 == 1)) {
      return sumwxy/sumw - sumwx/sumw*sumwy/sumw;
   }
   if ((axis1 == 1 && axis2 == 3) || (axis1 == 3 && axis2 == 1)) {
      return sumwxz/sumw - sumwx/sumw*sumwz/sumw;
   }
   if ((axis1 == 2 && axis2 == 3) || (axis1 == 3 && axis2 == 2)) {
      return sumwyz/sumw - sumwy/sumw*sumwz/sumw;
   }
   return 0;
}


//______________________________________________________________________________
void TH3::GetRandom3(Double_t &x, Double_t &y, Double_t &z)
{
   // return 3 random numbers along axis x , y and z distributed according
   // the cellcontents of a 3-dim histogram

   Int_t nbinsx = GetNbinsX();
   Int_t nbinsy = GetNbinsY();
   Int_t nbinsz = GetNbinsZ();
   Int_t nxy    = nbinsx*nbinsy;
   Int_t nbins  = nxy*nbinsz;
   Double_t integral;
   if (fIntegral) {
      if (fIntegral[nbins+1] != fEntries) integral = ComputeIntegral();
   } else {
      integral = ComputeIntegral();
      if (integral == 0 || fIntegral == 0) return;
   }
   Double_t r1 = gRandom->Rndm();
   Int_t ibin = TMath::BinarySearch(nbins,fIntegral,(Double_t) r1);
   Int_t binz = ibin/nxy;
   Int_t biny = (ibin - nxy*binz)/nbinsx;
   Int_t binx = ibin - nbinsx*(biny + nbinsy*binz);
   x = fXaxis.GetBinLowEdge(binx+1);
   if (r1 > fIntegral[ibin]) x +=
      fXaxis.GetBinWidth(binx+1)*(r1-fIntegral[ibin])/(fIntegral[ibin+1] - fIntegral[ibin]);
   y = fYaxis.GetBinLowEdge(biny+1) + fYaxis.GetBinWidth(biny+1)*gRandom->Rndm();
   z = fZaxis.GetBinLowEdge(binz+1) + fZaxis.GetBinWidth(binz+1)*gRandom->Rndm();
}

//______________________________________________________________________________
void TH3::GetStats(Double_t *stats) const
{
   // fill the array stats from the contents of this histogram
   // The array stats must be correctly dimensionned in the calling program.
   // stats[0] = sumw
   // stats[1] = sumw2
   // stats[2] = sumwx
   // stats[3] = sumwx2
   // stats[4] = sumwy
   // stats[5] = sumwy2
   // stats[6] = sumwxy
   // stats[7] = sumwz
   // stats[8] = sumwz2
   // stats[9] = sumwxz
   // stats[10]= sumwyz

   if (fBuffer) ((TH3*)this)->BufferEmpty();

   Int_t bin, binx, biny, binz;
   Double_t w,err;
   Double_t x,y,z;
   if ((fTsumw == 0 && fEntries > 0) || fXaxis.TestBit(TAxis::kAxisRange) || fYaxis.TestBit(TAxis::kAxisRange) || fZaxis.TestBit(TAxis::kAxisRange)) {
      for (bin=0;bin<9;bin++) stats[bin] = 0;

      Int_t firstBinX = fXaxis.GetFirst();
      Int_t lastBinX  = fXaxis.GetLast();
      Int_t firstBinY = fYaxis.GetFirst();
      Int_t lastBinY  = fYaxis.GetLast();
      Int_t firstBinZ = fZaxis.GetFirst();
      Int_t lastBinZ  = fZaxis.GetLast();
      // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
      if (fgStatOverflows) {
         if ( !fXaxis.TestBit(TAxis::kAxisRange) ) {
            if (firstBinX == 1) firstBinX = 0;
            if (lastBinX ==  fXaxis.GetNbins() ) lastBinX += 1;
         }
         if ( !fYaxis.TestBit(TAxis::kAxisRange) ) {
            if (firstBinY == 1) firstBinY = 0;
            if (lastBinY ==  fYaxis.GetNbins() ) lastBinY += 1;
         }
         if ( !fZaxis.TestBit(TAxis::kAxisRange) ) {
            if (firstBinZ == 1) firstBinZ = 0;
            if (lastBinZ ==  fZaxis.GetNbins() ) lastBinZ += 1;
         }
      }
      for (binz = firstBinZ; binz <= lastBinZ; binz++) {
         z = fZaxis.GetBinCenter(binz);
         for (biny = firstBinY; biny <= lastBinY; biny++) {
            y = fYaxis.GetBinCenter(biny);
            for (binx = firstBinX; binx <= lastBinX; binx++) {
               bin = GetBin(binx,biny,binz);
               x   = fXaxis.GetBinCenter(binx);
               w   = TMath::Abs(GetBinContent(bin));
               err = TMath::Abs(GetBinError(bin));
               stats[0] += w;
               stats[1] += err*err;
               stats[2] += w*x;
               stats[3] += w*x*x;
               stats[4] += w*y;
               stats[5] += w*y*y;
               stats[6] += w*x*y;
               stats[7] += w*z;
               stats[8] += w*z*z;
               stats[9] += w*x*z;
               stats[10]+= w*y*z;
            }
         }
      }
   } else {
      stats[0] = fTsumw;
      stats[1] = fTsumw2;
      stats[2] = fTsumwx;
      stats[3] = fTsumwx2;
      stats[4] = fTsumwy;
      stats[5] = fTsumwy2;
      stats[6] = fTsumwxy;
      stats[7] = fTsumwz;
      stats[8] = fTsumwz2;
      stats[9] = fTsumwxz;
      stats[10]= fTsumwyz;
   }
}

//______________________________________________________________________________
Double_t TH3::Integral(Option_t *option) const
{
   //Return integral of bin contents. Only bins in the bins range are considered.
   // By default the integral is computed as the sum of bin contents in the range.
   // if option "width" is specified, the integral is the sum of
   // the bin contents multiplied by the bin width in x, y and in z.

   return Integral(fXaxis.GetFirst(),fXaxis.GetLast(),
      fYaxis.GetFirst(),fYaxis.GetLast(),
      fZaxis.GetFirst(),fZaxis.GetLast(),option);
}

//______________________________________________________________________________
Double_t TH3::Integral(Int_t binx1, Int_t binx2, Int_t biny1, Int_t biny2, Int_t binz1, Int_t binz2, Option_t *option) const
{
   //Return integral of bin contents in range [binx1,binx2],[biny1,biny2],[binz1,binz2]
   // for a 3-D histogram
   // By default the integral is computed as the sum of bin contents in the range.
   // if option "width" is specified, the integral is the sum of
   // the bin contents multiplied by the bin width in x, y and in z.

   Double_t err = 0; 
   return DoIntegral(binx1,binx2,biny1,biny2,binz1,binz2,err,option);
}
//______________________________________________________________________________
Double_t TH3::IntegralAndError(Int_t binx1, Int_t binx2, Int_t biny1, Int_t biny2, Int_t binz1, Int_t binz2, Double_t & error, Option_t *option) const
{
   //Return integral of bin contents in range [binx1,binx2],[biny1,biny2],[binz1,binz2]
   // for a 3-D histogram. Calculates also the integral error using error propagation 
   // from the bin errors assumming that all the bins are uncorrelated. 
   // By default the integral is computed as the sum of bin contents in the range.
   // if option "width" is specified, the integral is the sum of
   // the bin contents multiplied by the bin width in x, y and in z.
   return DoIntegral(binx1,binx2,biny1,biny2,binz1,binz2,error,option,kTRUE);
}

//______________________________________________________________________________
Double_t TH3::Interpolate(Double_t)
{
   
   //Not yet implemented
   Error("Interpolate","This function must be called with 3 arguments for a TH3");
   return 0;
}

//______________________________________________________________________________
Double_t TH3::Interpolate(Double_t, Double_t)
{
   
   //Not yet implemented
   Error("Interpolate","This function must be called with 3 arguments for a TH3");
   return 0;
}

//______________________________________________________________________________
Double_t TH3::Interpolate(Double_t x, Double_t y, Double_t z)
{
   // Given a point P(x,y,z), Interpolate approximates the value via trilinear interpolation
   // based on the 8 nearest bin center points ( corner of the cube surronding the points) 
   // The Algorithm is described in http://en.wikipedia.org/wiki/Trilinear_interpolation
   // The given values (x,y,z) must be between first bin center and  last bin center for each coordinate: 
   //
   //   fXAxis.GetBinCenter(1) < x  < fXaxis.GetBinCenter(nbinX)     AND
   //   fYAxis.GetBinCenter(1) < y  < fYaxis.GetBinCenter(nbinY)     AND
   //   fZAxis.GetBinCenter(1) < z  < fZaxis.GetBinCenter(nbinZ) 

   Int_t ubx = fXaxis.FindBin(x);
   if ( x < fXaxis.GetBinCenter(ubx) ) ubx -= 1;
   Int_t obx = ubx + 1;

   Int_t uby = fYaxis.FindBin(y);
   if ( y < fYaxis.GetBinCenter(uby) ) uby -= 1;
   Int_t oby = uby + 1;

   Int_t ubz = fZaxis.FindBin(z);
   if ( z < fZaxis.GetBinCenter(ubz) ) ubz -= 1;
   Int_t obz = ubz + 1;


//    if ( IsBinUnderflow(GetBin(ubx, uby, ubz)) ||
//         IsBinOverflow (GetBin(obx, oby, obz)) ) {
   if (ubx <=0 || uby <=0 || ubz <= 0 ||
       obx > fXaxis.GetNbins() || oby > fYaxis.GetNbins() || obz > fZaxis.GetNbins() ) {
      Error("Interpolate","Cannot interpolate outside histogram domain.");
      return 0;
   }

   Double_t xw = fXaxis.GetBinCenter(obx) - fXaxis.GetBinCenter(ubx);
   Double_t yw = fYaxis.GetBinCenter(oby) - fYaxis.GetBinCenter(uby);
   Double_t zw = fZaxis.GetBinCenter(obz) - fZaxis.GetBinCenter(ubz);

   Double_t xd = (x - fXaxis.GetBinCenter(ubx)) / xw;
   Double_t yd = (y - fYaxis.GetBinCenter(uby)) / yw;
   Double_t zd = (z - fZaxis.GetBinCenter(ubz)) / zw;


   Double_t v[] = { GetBinContent( ubx, uby, ubz ), GetBinContent( ubx, uby, obz ),
                    GetBinContent( ubx, oby, ubz ), GetBinContent( ubx, oby, obz ),
                    GetBinContent( obx, uby, ubz ), GetBinContent( obx, uby, obz ),
                    GetBinContent( obx, oby, ubz ), GetBinContent( obx, oby, obz ) };


   Double_t i1 = v[0] * (1 - zd) + v[1] * zd;
   Double_t i2 = v[2] * (1 - zd) + v[3] * zd;
   Double_t j1 = v[4] * (1 - zd) + v[5] * zd;
   Double_t j2 = v[6] * (1 - zd) + v[7] * zd;


   Double_t w1 = i1 * (1 - yd) + i2 * yd;
   Double_t w2 = j1 * (1 - yd) + j2 * yd;


   Double_t result = w1 * (1 - xd) + w2 * xd;

   return result;
}

//______________________________________________________________________________
Double_t TH3::KolmogorovTest(const TH1 *h2, Option_t *option) const
{
   //  Statistical test of compatibility in shape between
   //  THIS histogram and h2, using Kolmogorov test.
   //     Default: Ignore under- and overflow bins in comparison
   //
   //     option is a character string to specify options
   //         "U" include Underflows in test
   //         "O" include Overflows
   //         "N" include comparison of normalizations
   //         "D" Put out a line of "Debug" printout
   //         "M" Return the Maximum Kolmogorov distance instead of prob
   //
   //   The returned function value is the probability of test
   //       (much less than one means NOT compatible)
   //
   //   The KS test uses the distance between the pseudo-CDF's obtained 
   //   from the histogram. Since in more than 1D the order for generating the pseudo-CDF is 
   //   arbitrary, we use the pseudo-CDF's obtained from all the possible 6 combinatons of the 3 axis. 
   //   The average of all the maximum  distances obtained is used in the tests.  

   TString opt = option;
   opt.ToUpper();

   Double_t prb = 0;
   TH1 *h1 = (TH1*)this;
   if (h2 == 0) return 0;
   TAxis *xaxis1 = h1->GetXaxis();
   TAxis *xaxis2 = h2->GetXaxis();
   TAxis *yaxis1 = h1->GetYaxis();
   TAxis *yaxis2 = h2->GetYaxis();
   TAxis *zaxis1 = h1->GetZaxis();
   TAxis *zaxis2 = h2->GetZaxis();
   Int_t ncx1   = xaxis1->GetNbins();
   Int_t ncx2   = xaxis2->GetNbins();
   Int_t ncy1   = yaxis1->GetNbins();
   Int_t ncy2   = yaxis2->GetNbins();
   Int_t ncz1   = zaxis1->GetNbins();
   Int_t ncz2   = zaxis2->GetNbins();

   // Check consistency of dimensions
   if (h1->GetDimension() != 3 || h2->GetDimension() != 3) {
      Error("KolmogorovTest","Histograms must be 3-D\n");
      return 0;
   }

   // Check consistency in number of channels
   if (ncx1 != ncx2) {
      Error("KolmogorovTest","Number of channels in X is different, %d and %d\n",ncx1,ncx2);
      return 0;
   }
   if (ncy1 != ncy2) {
      Error("KolmogorovTest","Number of channels in Y is different, %d and %d\n",ncy1,ncy2);
      return 0;
   }
   if (ncz1 != ncz2) {
      Error("KolmogorovTest","Number of channels in Z is different, %d and %d\n",ncz1,ncz2);
      return 0;
   }

   // Check consistency in channel edges
   Bool_t afunc1 = kFALSE;
   Bool_t afunc2 = kFALSE;
   Double_t difprec = 1e-5;
   Double_t diff1 = TMath::Abs(xaxis1->GetXmin() - xaxis2->GetXmin());
   Double_t diff2 = TMath::Abs(xaxis1->GetXmax() - xaxis2->GetXmax());
   if (diff1 > difprec || diff2 > difprec) {
      Error("KolmogorovTest","histograms with different binning along X");
      return 0;
   }
   diff1 = TMath::Abs(yaxis1->GetXmin() - yaxis2->GetXmin());
   diff2 = TMath::Abs(yaxis1->GetXmax() - yaxis2->GetXmax());
   if (diff1 > difprec || diff2 > difprec) {
      Error("KolmogorovTest","histograms with different binning along Y");
      return 0;
   }
   diff1 = TMath::Abs(zaxis1->GetXmin() - zaxis2->GetXmin());
   diff2 = TMath::Abs(zaxis1->GetXmax() - zaxis2->GetXmax());
   if (diff1 > difprec || diff2 > difprec) {
      Error("KolmogorovTest","histograms with different binning along Z");
      return 0;
   }

   //   Should we include Uflows, Oflows?
   Int_t ibeg = 1, jbeg = 1, kbeg = 1;
   Int_t iend = ncx1, jend = ncy1, kend = ncz1;
   if (opt.Contains("U")) {ibeg = 0; jbeg = 0; kbeg = 0;}
   if (opt.Contains("O")) {iend = ncx1+1; jend = ncy1+1; kend = ncz1+1;}

   Int_t i,j,k,bin;
   Double_t sum1  = 0;
   Double_t sum2  = 0;
   Double_t w1    = 0;
   Double_t w2    = 0;
   for (i = ibeg; i <= iend; i++) {
      for (j = jbeg; j <= jend; j++) {
         for (k = kbeg; k <= kend; k++) {
            bin = h1->GetBin(i,j,k);
            sum1 += h1->GetBinContent(bin);
            sum2 += h2->GetBinContent(bin);
            Double_t ew1   = h1->GetBinError(bin);
            Double_t ew2   = h2->GetBinError(bin);
            w1   += ew1*ew1;
            w2   += ew2*ew2;
         }
      }
   }


   //    Check that both scatterplots contain events
   if (sum1 == 0) {
      Error("KolmogorovTest","Integral is zero for h1=%s\n",h1->GetName());
      return 0;
   }
   if (sum2 == 0) {
      Error("KolmogorovTest","Integral is zero for h2=%s\n",h2->GetName());
      return 0;
   }
   // calculate the effective entries.  
   // the case when errors are zero (w1 == 0 or w2 ==0) are equivalent to 
   // compare to a function. In that case the rescaling is done only on sqrt(esum2) or sqrt(esum1) 
   Double_t esum1 = 0, esum2 = 0; 
   if (w1 > 0) 
      esum1 = sum1 * sum1 / w1; 
   else 
      afunc1 = kTRUE;    // use later for calculating z
   
   if (w2 > 0) 
      esum2 = sum2 * sum2 / w2; 
   else 
      afunc2 = kTRUE;    // use later for calculating z
   
   if (afunc2 && afunc1) { 
      Error("KolmogorovTest","Errors are zero for both histograms\n");
      return 0;
   }

   //   Find Kolmogorov distance
   //   order is arbitrary take average of all possible 6 starting orders x,y,z 
   int order[3] = {0,1,2};
   int binbeg[3]; 
   int binend[3]; 
   int ibin[3];
   binbeg[0] = ibeg; binbeg[1] = jbeg; binbeg[2] = kbeg; 
   binend[0] = iend; binend[1] = jend; binend[2] = kend; 
   Double_t vdfmax[6]; // there are in total 6 combinations 
   int icomb = 0; 
   Double_t s1 = 1./(6.*sum1);
   Double_t s2 = 1./(6.*sum2);
   Double_t rsum1=0, rsum2=0;
   do { 
      // loop on bins
      Double_t dmax = 0;
      for (i = binbeg[order[0] ]; i <= binend[order[0] ]; i++) {
         for ( j = binbeg[order[1] ]; j <= binend[order[1] ]; j++) {
            for ( k = binbeg[order[2] ]; k <= binend[order[2] ]; k++) {
                  ibin[ order[0] ] = i;
                  ibin[ order[1] ] = j;
                  ibin[ order[2] ] = k;
                  bin = h1->GetBin(ibin[0],ibin[1],ibin[2]);
                  rsum1 += s1*h1->GetBinContent(bin);
                  rsum2 += s2*h2->GetBinContent(bin);
                  dmax   = TMath::Max(dmax, TMath::Abs(rsum1-rsum2));
            }
         }
      }
      vdfmax[icomb] = dmax; 
      icomb++;
   } while (TMath::Permute(3,order)  );


   // get average of distances 
   Double_t dfmax = TMath::Mean(6,vdfmax);
   
   //    Get Kolmogorov probability
   Double_t factnm;
   if (afunc1)      factnm = TMath::Sqrt(sum2);
   else if (afunc2) factnm = TMath::Sqrt(sum1);
   else             factnm = TMath::Sqrt(sum1*sum2/(sum1+sum2));
   Double_t z  = dfmax*factnm;

   prb = TMath::KolmogorovProb(z); 

   Double_t prb1 = 0, prb2 = 0; 
   // option N to combine normalization makes sense if both afunc1 and afunc2 are false
   if (opt.Contains("N")  && !(afunc1 || afunc2 ) ) { 
      // Combine probabilities for shape and normalization
      prb1   = prb;
      Double_t d12    = esum1-esum2;
      Double_t chi2   = d12*d12/(esum1+esum2);
      prb2   = TMath::Prob(chi2,1);
      //     see Eadie et al., section 11.6.2
      if (prb > 0 && prb2 > 0) prb = prb*prb2*(1-TMath::Log(prb*prb2));
      else                     prb = 0;
   }

   //    debug printout
   if (opt.Contains("D")) {
      printf(" Kolmo Prob  h1 = %s, sum1=%g\n",h1->GetName(),sum1);
      printf(" Kolmo Prob  h2 = %s, sum2=%g\n",h2->GetName(),sum2);
      printf(" Kolmo Probabil = %f, Max Dist = %g\n",prb,dfmax);
      if (opt.Contains("N"))
         printf(" Kolmo Probabil = %f for shape alone, =%f for normalisation alone\n",prb1,prb2);
   }
   // This numerical error condition should never occur:
   if (TMath::Abs(rsum1-1) > 0.002) Warning("KolmogorovTest","Numerical problems with h1=%s\n",h1->GetName());
   if (TMath::Abs(rsum2-1) > 0.002) Warning("KolmogorovTest","Numerical problems with h2=%s\n",h2->GetName());

   if(opt.Contains("M"))      return dfmax;  // return avergae of max distance

   return prb;
}


//______________________________________________________________________________
Long64_t TH3::Merge(TCollection *list)
{
   //Add all histograms in the collection to this histogram.
   //This function computes the min/max for the axes,
   //compute a new number of bins, if necessary,
   //add bin contents, errors and statistics.
   //If overflows are present and limits are different the function will fail.
   //The function returns the total number of entries in the result histogram
   //if the merge is successfull, -1 otherwise.
   //
   //IMPORTANT remark. The 2 axis x and y may have different number
   //of bins and different limits, BUT the largest bin width must be
   //a multiple of the smallest bin width and the upper limit must also
   //be a multiple of the bin width.

   if (!list) return 0;
   if (list->IsEmpty()) return (Int_t) GetEntries();

   TList inlist;
   TH1* hclone = (TH1*)Clone("FirstClone");
   R__ASSERT(hclone);
   BufferEmpty(1);         // To remove buffer.
   Reset();                // BufferEmpty sets limits so we can't use it later.
   SetEntries(0);
   inlist.Add(hclone);
   inlist.AddAll(list);

   TAxis newXAxis;
   TAxis newYAxis;
   TAxis newZAxis;
   Bool_t initialLimitsFound = kFALSE;
   Bool_t same = kTRUE;
   Bool_t allHaveLimits = kTRUE;

   TIter next(&inlist);
   while (TObject *o = next()) {
      TH3* h = dynamic_cast<TH3*> (o);
      if (!h) {
         Error("Add","Attempt to add object of class: %s to a %s",
            o->ClassName(),this->ClassName());
         return -1;
      }
      Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
      allHaveLimits = allHaveLimits && hasLimits;

      if (hasLimits) {
         h->BufferEmpty();
         if (!initialLimitsFound) {
            initialLimitsFound = kTRUE;
            newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
               h->GetXaxis()->GetXmax());
            newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
               h->GetYaxis()->GetXmax());
            newZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
               h->GetZaxis()->GetXmax());
         }
         else {
            if (!RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
               Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
                  "first: (%d, %f, %f), second: (%d, %f, %f)",
                  newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
                  h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
                  h->GetXaxis()->GetXmax());
            }
            if (!RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
               Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
                  "first: (%d, %f, %f), second: (%d, %f, %f)",
                  newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
                  h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
                  h->GetYaxis()->GetXmax());
            }
            if (!RecomputeAxisLimits(newZAxis, *(h->GetZaxis()))) {
               Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
                  "first: (%d, %f, %f), second: (%d, %f, %f)",
                  newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax(),
                  h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
                  h->GetZaxis()->GetXmax());
            }
         }
      }
   }
   next.Reset();

   same = same && SameLimitsAndNBins(newXAxis, *GetXaxis())
      && SameLimitsAndNBins(newYAxis, *GetYaxis());
   if (!same && initialLimitsFound)
      SetBins(newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
      newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
      newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax());

   if (!allHaveLimits) {
      // fill this histogram with all the data from buffers of histograms without limits
      while (TH3* h = dynamic_cast<TH3*> (next())) {
         if (h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && h->fBuffer) {
            // no limits
            Int_t nbentries = (Int_t)h->fBuffer[0];
            for (Int_t i = 0; i < nbentries; i++)
               Fill(h->fBuffer[4*i + 2], h->fBuffer[4*i + 3],
               h->fBuffer[4*i + 4], h->fBuffer[4*i + 1]);
            // Entries from buffers have to be filled one by one
            // because FillN doesn't resize histograms.
         }
      }
      if (!initialLimitsFound)
         return (Int_t) GetEntries();  // all histograms have been processed
      next.Reset();
   }

   //merge bin contents and errors
   Double_t stats[kNstat], totstats[kNstat];
   for (Int_t i=0;i<kNstat;i++) {totstats[i] = stats[i] = 0;}
   GetStats(totstats);
   Double_t nentries = GetEntries();
   Int_t binx, biny, binz, ix, iy, iz, nx, ny, nz, bin, ibin;
   Double_t cu;
   Int_t nbix = fXaxis.GetNbins();
   Int_t nbiy = fYaxis.GetNbins();
   Bool_t canRebin=TestBit(kCanRebin);
   ResetBit(kCanRebin); // reset, otherwise setting the under/overflow will rebin

   while (TH1* h=(TH1*)next()) {
      // process only if the histogram has limits; otherwise it was processed before
      if (h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
         // import statistics
         h->GetStats(stats);
         for (Int_t i = 0; i < kNstat; i++)
            totstats[i] += stats[i];
         nentries += h->GetEntries();

         nx = h->GetXaxis()->GetNbins();
         ny = h->GetYaxis()->GetNbins();
         nz = h->GetZaxis()->GetNbins();

         for (binz = 0; binz <= nz + 1; binz++) {
            iz = fZaxis.FindBin(h->GetZaxis()->GetBinCenter(binz));
            for (biny = 0; biny <= ny + 1; biny++) {
               iy = fYaxis.FindBin(h->GetYaxis()->GetBinCenter(biny));
               for (binx = 0; binx <= nx + 1; binx++) {
                  ix = fXaxis.FindBin(h->GetXaxis()->GetBinCenter(binx));
                  bin = binx +(nx+2)*(biny + (ny+2)*binz);
                  ibin = ix +(nbix+2)*(iy + (nbiy+2)*iz);
                  cu  = h->GetBinContent(bin);
                  if ((!same) && (binx == 0 || binx == nx + 1
                     || biny == 0 || biny == ny + 1
                     || binz == 0 || binz == nz + 1)) {
                        if (cu != 0) {
                           Error("Merge", "Cannot merge histograms - the histograms have"
                              " different limits and undeflows/overflows are present."
                              " The initial histogram is now broken!");
                           return -1;
                        }
                  }
                  AddBinContent(ibin,cu);
                  if (fSumw2.fN) {
                     Double_t error1 = h->GetBinError(bin);
                     fSumw2.fArray[ibin] += error1*error1;
                  }
               }
            }
         }
      }
   }
   if (canRebin) SetBit(kCanRebin);

   //copy merged stats
   PutStats(totstats);
   SetEntries(nentries);
   inlist.Remove(hclone);
   delete hclone;
   return (Long64_t)nentries;
}

//______________________________________________________________________________
TH1D *TH3::ProjectionX(const char *name, Int_t iymin, Int_t iymax, Int_t izmin, Int_t izmax, Option_t *option) const
{
   //*-*-*-*-*Project a 3-D histogram into a 1-D histogram along X*-*-*-*-*-*-*
   //*-*      ====================================================
   //
   //   The projection is always of the type TH1D.
   //   The projection is made from the cells along the X axis
   //   ranging from iymin to iymax and izmin to izmax included.
   //   By default, underflow and overflows are included
   //   By Setting iymin=1 and iymax=NbinsY the underflow and/or overflow will be excluded
   //
   //   if option "e" is specified, the errors are computed.
   //   if option "d" is specified, the projection is drawn in the current pad.
   //   if option "o" original axis range of the taget axes will be
   //   kept, but only bins inside the selected range will be filled.
   //
   //   NOTE that if a TH1D named "name" exists in the current directory or pad and having   
   //   a compatible axis, the histogram is reset and filled again with the projected contents of the TH3.
   //   In the case of axis incompatibility, an error is reported and a NULL pointer is returned.
   //
   //  implemented using Project3D


   TString opt = option;
   opt.ToLower();

   Int_t piymin = GetYaxis()->GetFirst();
   Int_t piymax = GetYaxis()->GetLast();
   Int_t pizmin = GetZaxis()->GetFirst();
   Int_t pizmax = GetZaxis()->GetLast();   

   GetYaxis()->SetRange(iymin,iymax);
   GetZaxis()->SetRange(izmin,izmax);

   // exclude underflow/overflow by forcing the axis range bit
   // due to limitation of TAxis::SetRange cannot select only underflow or overflow cannot have underflow or overflow only   
   if (iymin == 1 && iymax ==  GetNbinsY() ) GetYaxis()->SetBit(TAxis::kAxisRange); 
   if (izmin == 1 && izmax ==  GetNbinsZ() ) GetZaxis()->SetBit(TAxis::kAxisRange); 
   // I can use the useUF or useOF flag for exclude/include the underflow/overflow separtly
   // (-1 in the imax is considered as an overflow)
   Bool_t useUF = (iymin == 0 || izmin == 0); 
   Bool_t useOF = ( (iymax < 0 ) || (iymax > GetNbinsY() ) || (izmax < 0) || (izmax > GetNbinsZ() ) ); 

   Bool_t computeErrors = GetSumw2N();
   if (opt.Contains("e") ) { 
      computeErrors = kTRUE;
      opt.Remove(opt.First("e"),1);
   }
   Bool_t originalRange = kFALSE;
   if (opt.Contains('o') ) { 
      originalRange = kTRUE; 
      opt.Remove(opt.First("o"),1);
   }
  
   TH1D * h1 = DoProject1D(name, GetTitle(), this->GetXaxis(), computeErrors, originalRange, useUF, useOF);

   // restore original range
   GetYaxis()->SetRange(piymin,piymax);
   GetZaxis()->SetRange(pizmin,pizmax);

   // draw in current pad 
   if (h1 && opt.Contains("d")) {
      opt.Remove(opt.First("d"),1);
      TVirtualPad *padsav = gPad;
      TVirtualPad *pad = gROOT->GetSelectedPad();
      if (pad) pad->cd();
      if (!gPad->FindObject(h1)) {
         h1->Draw(opt);
      } else {
         h1->Paint(opt);
      }
      if (padsav) padsav->cd();
   }

   return h1;
}

//______________________________________________________________________________
TH1D *TH3::ProjectionY(const char *name, Int_t ixmin, Int_t ixmax, Int_t izmin, Int_t izmax, Option_t *option) const
{
   //*-*-*-*-*Project a 3-D histogram into a 1-D histogram along Y*-*-*-*-*-*-*
   //*-*      ====================================================
   //
   //   The projection is always of the type TH1D.
   //   The projection is made from the cells along the Y axis
   //   ranging from ixmin to ixmax and izmin to izmax included.
   //   By default, underflow and overflow are included. 
   //   By Setting ixmin=1 and ixmax=NbinsX the underflow and/or overflow will be excluded
   //
   //   if option "e" is specified, the errors are computed.
   //   if option "d" is specified, the projection is drawn in the current pad.
   //   if option "o" original axis range of the taget axes will be
   //   kept, but only bins inside the selected range will be filled.
   //
   //   NOTE that if a TH1D named "name" exists in the current directory or pad and having   
   //   a compatible axis, the histogram is reset and filled again with the projected contents of the TH3.
   //   In the case of axis incompatibility, an error is reported and a NULL pointer is returned.
   //
   //  implemented using Project3D


   TString opt = option;
   opt.ToLower();

   Int_t pixmin = GetXaxis()->GetFirst();
   Int_t pixmax = GetXaxis()->GetLast();
   Int_t pizmin = GetZaxis()->GetFirst();
   Int_t pizmax = GetZaxis()->GetLast();   

   GetXaxis()->SetRange(ixmin,ixmax);
   GetZaxis()->SetRange(izmin,izmax);

   // exclude underflow/overflow by forcing the axis range bit
   // due to limitation of TAxis::SetRange cannot select only underflow or overflow cannot have underflow or overflow only   
   if (ixmin == 1 && ixmax ==  GetNbinsX() ) GetXaxis()->SetBit(TAxis::kAxisRange); 
   if (izmin == 1 && izmax ==  GetNbinsZ() ) GetZaxis()->SetBit(TAxis::kAxisRange); 
   // I can use the useUF or useOF flag for exclude/include the underflow/overflow separtly
   // (-1 in the imax is considered as an overflow)
   Bool_t useUF = (ixmin == 0 || izmin == 0); 
   Bool_t useOF = ( (ixmax < 0 ) || (ixmax > GetNbinsX() ) || (izmax < 0) || (izmax > GetNbinsZ() ) ); 

   Bool_t computeErrors = GetSumw2N();
   if (opt.Contains("e") ) { 
      computeErrors = kTRUE;
      opt.Remove(opt.First("e"),1);
   }
   Bool_t originalRange = kFALSE;
   if (opt.Contains('o') ) { 
      originalRange = kTRUE; 
      opt.Remove(opt.First("o"),1);
   }
  
   TH1D * h1 = DoProject1D(name, GetTitle(), this->GetYaxis(), computeErrors, originalRange, useUF, useOF);

   // restore axis range
   GetXaxis()->SetRange(pixmin,pixmax);
   GetZaxis()->SetRange(pizmin,pizmax);

   // draw in current pad 
   if (h1 && opt.Contains("d")) {
      opt.Remove(opt.First("d"),1);
      TVirtualPad *padsav = gPad;
      TVirtualPad *pad = gROOT->GetSelectedPad();
      if (pad) pad->cd();
      if (!gPad->FindObject(h1)) {
         h1->Draw(opt);
      } else {
         h1->Paint(opt);
      }
      if (padsav) padsav->cd();
   }
   
   return h1;
}

//______________________________________________________________________________
TH1D *TH3::ProjectionZ(const char *name, Int_t ixmin, Int_t ixmax, Int_t iymin, Int_t iymax, Option_t *option) const
{
   //*-*-*-*-*Project a 3-D histogram into a 1-D histogram along Z*-*-*-*-*-*-*
   //*-*      ====================================================
   //
   //   The projection is always of the type TH1D.
   //   The projection is made from the cells along the X axis
   //   ranging from ixmin to ixmax and iymin to iymax included.
   //   By default, bins 1 to nx and 1 to ny  are included
   //   By setting ixmin=1 and/or ixmax=NbinsX the underflow and/or overflow in X will be excluded
   //   By setting iymin=1 and/or iymax=NbinsY the underflow and/or overflow in Y will be excluded
   //
   //   if option "e" is specified, the errors are computed.
   //   if option "d" is specified, the projection is drawn in the current pad.
   //   if option "o" original axis range of the taget axes will be
   //   kept, but only bins inside the selected range will be filled.
   //
   //   NOTE that if a TH1D named "name" exists in the current directory or pad and having   
   //   a compatible axis, the histogram is reset and filled again with the projected contents of the TH3.
   //   In the case of axis incompatibility, an error is reported and a NULL pointer is returned.
   //
   //  implemented using Project3D


   TString opt = option;
   opt.ToLower();

   Int_t pixmin = GetXaxis()->GetFirst();
   Int_t pixmax = GetXaxis()->GetLast();
   Int_t piymin = GetYaxis()->GetFirst();
   Int_t piymax = GetYaxis()->GetLast();  

   GetXaxis()->SetRange(ixmin,ixmax);
   GetYaxis()->SetRange(iymin,iymax);

   // exclude underflow/overflow by forcing the axis range bit
   // due to limitation of TAxis::SetRange cannot select only underflow or overflow cannot have underflow or overflow only   
   if (ixmin == 1 && ixmax ==  GetNbinsX() ) GetXaxis()->SetBit(TAxis::kAxisRange); 
   if (iymin == 1 && iymax ==  GetNbinsY() ) GetYaxis()->SetBit(TAxis::kAxisRange); 
   // I can use the useUF or useOF flag for exclude/include the underflow/overflow separtly
   // (-1 in the imax is considered as an overflow)
   Bool_t useUF = (ixmin == 0 || iymin == 0); 
   Bool_t useOF = ( (ixmax < 0 ) || (ixmax > GetNbinsX() ) || (iymax < 0) || (iymax > GetNbinsY() ) ); 

   Bool_t computeErrors = GetSumw2N();
   if (opt.Contains("e") ) { 
      computeErrors = kTRUE;
      opt.Remove(opt.First("e"),1);
   }
   Bool_t originalRange = kFALSE;
   if (opt.Contains('o') ) { 
      originalRange = kTRUE; 
      opt.Remove(opt.First("o"),1);
   }

   TH1D * h1 =  DoProject1D(name, GetTitle(), this->GetZaxis(), computeErrors, originalRange, useUF, useOF);

   // restore the range
   GetXaxis()->SetRange(pixmin,pixmax);
   GetYaxis()->SetRange(piymin,piymax);

   // draw in current pad 
   if (h1 && opt.Contains("d")) {
      opt.Remove(opt.First("d"),1);
      TVirtualPad *padsav = gPad;
      TVirtualPad *pad = gROOT->GetSelectedPad();
      if (pad) pad->cd();
      if (!gPad->FindObject(h1)) {
         h1->Draw(opt);
      } else {
         h1->Paint(opt);
      }
      if (padsav) padsav->cd();
   }

   return h1;
}

//______________________________________________________________________________
TH1D *TH3::DoProject1D(const char* name, const char* title, TAxis* projX, 
                    bool computeErrors, bool originalRange, 
                    bool useUF, bool useOF) const
{
   // internal methdod performing the projection to 1D histogram
   // called from TH3::Project3D

   // Create the projection histogram
   TH1D *h1 = 0;

   // Get range to use as well as bin limits
   Int_t ixmin = projX->GetFirst();
   Int_t ixmax = projX->GetLast();
   if (ixmin == 0 && ixmax == 0) { ixmin = 1; ixmax = projX->GetNbins(); }
   Int_t nx = ixmax-ixmin+1;

   // Create the histogram, either reseting a preexisting one 
   // in case they have a compatible axis
   TObject *h1obj = gROOT->FindObject(name);
   if (h1obj && h1obj->InheritsFrom("TH1")) {
      if (h1obj->IsA() != TH1D::Class() ) { 
         Error("DoProject1D","Histogram with name %s must be a TH1D and is a %s",name,h1obj->ClassName());
         return 0; 
      }
      h1 = (TH1D*)h1obj;
      // check histogram compatibility (not perfect for variable bins histograms)
      if ( h1->GetNbinsX() ==  projX->GetNbins() && 
           h1->GetXaxis()->GetXmin() == projX->GetXmin() &&
           h1->GetXaxis()->GetXmax() == projX->GetXmax() ) { 
         // enable originalRange option in case a range is set in the outer axis
         originalRange = kTRUE; 
         h1->Reset();
      }
      else if ( h1->GetNbinsX() ==  nx && 
                h1->GetXaxis()->GetXmin() == projX->GetBinLowEdge(ixmin) &&
                h1->GetXaxis()->GetXmax() == projX->GetBinUpEdge(ixmax) ) { 
         // reset also in case an histogram exists with compatible axis with the zoomed original axis
         h1->Reset();   
      }      
      else {  
         Error("DoProject1D","Histogram with name %s alread exists and it is not compatible",name);
         return 0; 
      }
   }

   if (!h1) { 
      const TArrayD *bins = projX->GetXbins();
      if ( originalRange )
      {
         if (bins->fN == 0) {
            h1 = new TH1D(name,title,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
         } else {
            h1 = new TH1D(name,title,projX->GetNbins(),bins->fArray);
         }
      } else {
         if (bins->fN == 0) {
            h1 = new TH1D(name,title,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
         } else {
            h1 = new TH1D(name,title,nx,&bins->fArray[ixmin-1]);
         }
      }
   }

   // Copy the axis attributes and the axis labels if needed.
   h1->GetXaxis()->ImportAttributes(projX);
   THashList* labels = projX->GetLabels();
   if (labels) {
      TIter iL(labels);
      TObjString* lb;
      Int_t i = 1;
      while ((lb=(TObjString*)iL())) {
         h1->GetXaxis()->SetBinLabel(i,lb->String().Data());
         i++;
      }
   }
   h1->SetLineColor(this->GetLineColor());
   h1->SetFillColor(this->GetFillColor());
   h1->SetMarkerColor(this->GetMarkerColor());
   h1->SetMarkerStyle(this->GetMarkerStyle());

   // Activate errors
   if ( computeErrors ) h1->Sumw2();

   // Set references to the axis, so that the bucle has no branches.
   TAxis* out1 = 0;
   TAxis* out2 = 0;
   if ( projX == GetXaxis() ) {
      out1 = GetYaxis();
      out2 = GetZaxis();
   } else if ( projX == GetYaxis() ) {
      out1 = GetZaxis();
      out2 = GetXaxis();
   } else {
      out1 = GetYaxis();
      out2 = GetXaxis();
   }

   Int_t *refX = 0, *refY = 0, *refZ = 0;
   Int_t ixbin, out1bin, out2bin;
   if ( projX == GetXaxis() ) { refX = &ixbin;   refY = &out1bin; refZ = &out2bin; }
   if ( projX == GetYaxis() ) { refX = &out2bin; refY = &ixbin;   refZ = &out1bin; }
   if ( projX == GetZaxis() ) { refX = &out2bin; refY = &out1bin; refZ = &ixbin;   }

   // Fill the projected histogram excluding underflow/overflows if considered in the option
   // if specified in the option (by default they considered)
   Double_t totcont  = 0;

   Int_t out1min = out1->GetFirst(); 
   Int_t out1max = out1->GetLast(); 
   // GetFirst(), GetLast() can return (0,0) when the range bit is set artifically (see TAxis::SetRange)
   if (out1min == 0 && out1max == 0) { out1min = 1; out1max = out1->GetNbins(); }
   // correct for underflow/overflows
   if (useUF && !out1->TestBit(TAxis::kAxisRange) )  out1min -= 1; 
   if (useOF && !out1->TestBit(TAxis::kAxisRange) )  out1max += 1; 
   Int_t out2min = out2->GetFirst(); 
   Int_t out2max = out2->GetLast(); 
   if (out2min == 0 && out2max == 0) { out2min = 1; out2max = out2->GetNbins(); }
   if (useUF && !out2->TestBit(TAxis::kAxisRange) )  out2min -= 1; 
   if (useOF && !out2->TestBit(TAxis::kAxisRange) )  out2max += 1; 

   for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++){
      if ( projX->TestBit(TAxis::kAxisRange) && ( ixbin < ixmin || ixbin > ixmax )) continue;

      Double_t cont = 0; 
      Double_t err2 = 0; 

      // loop on the bins to be integrated (outbin should be called inbin)
      for (out1bin = out1min; out1bin <= out1max; out1bin++){
         for (out2bin = out2min; out2bin <= out2max; out2bin++){

            Int_t bin = GetBin(*refX, *refY, *refZ);

            // sum the bin contents and errors if needed
            cont += GetBinContent(bin);
            if (computeErrors) { 
               Double_t exyz = GetBinError(bin);
               err2 += exyz*exyz;
            }
         }
      }
      Int_t ix    = h1->FindBin( projX->GetBinCenter(ixbin) );
      h1->SetBinContent(ix ,cont);
      if (computeErrors) h1->SetBinError(ix, TMath::Sqrt(err2) ); 
      // sum all content
      totcont += cont;
      
   }

   // since we use a combination of fill and SetBinError we need to reset and recalculate the statistics
   // for weighted histograms otherwise sumw2 will be wrong. 
   // We  can keep the original statistics from the TH3 if the projected sumw is consistent with original one
   // i.e. when no events are thrown away  
   bool resetStats = true; 
   double eps = 1.E-12;
   if (IsA() == TH3F::Class() ) eps = 1.E-6;
   if (fTsumw != 0 && TMath::Abs( fTsumw - totcont) <  TMath::Abs(fTsumw) * eps) resetStats = false; 

   bool resetEntries = resetStats; 
   // entries are calculated using underflow/overflow. If excluded entries must be reset
   resetEntries |= !useUF || !useOF; 
   

   if (!resetStats) {
      Double_t stats[kNstat];
      GetStats(stats); 
      if ( projX == GetYaxis() ) {
         stats[2] = stats[4];
         stats[3] = stats[5]; 
      }
      else if  ( projX == GetZaxis() ) {
         stats[2] = stats[7];
         stats[3] = stats[8]; 
      }
      h1->PutStats(stats);
   }
   else {
      // reset statistics 
      h1->ResetStats();
   }
   if (resetEntries) { 
      // in case of error calculation (i.e. when Sumw2() is set) 
      // use the effective entries for the entries
      // since this  is the only way to estimate them
      Double_t entries =  TMath::Floor( totcont + 0.5); // to avoid numerical rounding         
      if (computeErrors) entries = h1->GetEffectiveEntries();
      h1->SetEntries( entries );  
   }
   else { 
      h1->SetEntries( fEntries );  
   }

   return h1;
}

//______________________________________________________________________________
TH2D *TH3::DoProject2D(const char* name, const char * title, TAxis* projX, TAxis* projY,  
                    bool computeErrors, bool originalRange,
                    bool useUF, bool useOF) const
{
   // internal method performing the projection to a 2D histogram
   // called from TH3::Project3D 

   TH2D *h2 = 0;

   // Get range to use as well as bin limits
   Int_t ixmin = projX->GetFirst();
   Int_t ixmax = projX->GetLast();
   Int_t iymin = projY->GetFirst();
   Int_t iymax = projY->GetLast();
   if (ixmin == 0 && ixmax == 0) { ixmin = 1; ixmax = projX->GetNbins(); }
   if (iymin == 0 && iymax == 0) { iymin = 1; iymax = projY->GetNbins(); }
   Int_t nx = ixmax-ixmin+1;
   Int_t ny = iymax-iymin+1;

   // Create the histogram, either reseting a preexisting one 
   // if compatible or creating one from scratch.
   // Does an object with the same name exists?
   TObject *h2obj = gROOT->FindObject(name);
   if (h2obj && h2obj->InheritsFrom("TH1")) {
      if ( h2obj->IsA() != TH2D::Class() ) { 
         Error("DoProject2D","Histogram with name %s must be a TH2D and is a %s",name,h2obj->ClassName());
         return 0; 
      }
      h2 = (TH2D*)h2obj;
      // check histogram compatibility (not perfect for variable bins histograms)
      // note that the x axis of the projected histogram is  labeld  Y of the original
      if ( ( h2->GetNbinsX()           == projY->GetNbins()  && 
             h2->GetXaxis()->GetXmin() == projY->GetXmin()   &&
             h2->GetXaxis()->GetXmax() == projY->GetXmax() ) && 
           ( h2->GetNbinsY()          ==  projX->GetNbins()  && 
             h2->GetYaxis()->GetXmin() == projX->GetXmin()   &&
             h2->GetYaxis()->GetXmax() == projX->GetXmax() )  ) {  
         // enable originalRange option in case a range is set in the outer axis
         originalRange = kTRUE; 
         h2->Reset();
      }
      else if ( ( h2->GetNbinsX()           ==  ny                          && 
                  h2->GetXaxis()->GetXmin() == projY->GetBinLowEdge(iymin)  &&
                  h2->GetXaxis()->GetXmax() == projY->GetBinUpEdge(iymax) ) &&
                ( h2->GetNbinsY()           ==  nx                          && 
                  h2->GetYaxis()->GetXmin() == projX->GetBinLowEdge(ixmin)  &&
                  h2->GetYaxis()->GetXmax() == projX->GetBinUpEdge(ixmax) )  ) { 
         // reset also in case an histogram exists with compatible axis with the zoomed original axis
         h2->Reset();   
      }      
      else {  
         Error("DoProject2D","Histogram with name %s alread exists and it is not compatible",name);
         return 0; 
      }
   }

      
   if (!h2) { 
      const TArrayD *xbins = projX->GetXbins();
      const TArrayD *ybins = projY->GetXbins();
      if ( originalRange )
      {
         if (xbins->fN == 0 && ybins->fN == 0) {
            h2 = new TH2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
                          ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
         } else if (ybins->fN == 0) {
            h2 = new TH2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
                          ,projX->GetNbins(),&xbins->fArray[ixmin-1]);
         } else if (xbins->fN == 0) {
            h2 = new TH2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1]
                          ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
         } else {
            h2 = new TH2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1],projX->GetNbins(),&xbins->fArray[ixmin-1]);
         }
      } else {
         if (xbins->fN == 0 && ybins->fN == 0) {
            h2 = new TH2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
                          ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
         } else if (ybins->fN == 0) {
            h2 = new TH2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
                          ,nx,&xbins->fArray[ixmin-1]);
         } else if (xbins->fN == 0) {
            h2 = new TH2D(name,title,ny,&ybins->fArray[iymin-1]
                          ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
         } else {
            h2 = new TH2D(name,title,ny,&ybins->fArray[iymin-1],nx,&xbins->fArray[ixmin-1]);
         }
      }
   }

   // Copy the axis attributes and the axis labels if needed.
   THashList* labels1 = 0;
   THashList* labels2 = 0;
   // "xy"
   h2->GetXaxis()->ImportAttributes(projY);
   h2->GetYaxis()->ImportAttributes(projX);
   labels1 = projY->GetLabels();
   labels2 = projX->GetLabels();
   if (labels1) {
      TIter iL(labels1);
      TObjString* lb;
      Int_t i = 1;
      while ((lb=(TObjString*)iL())) {
         h2->GetXaxis()->SetBinLabel(i,lb->String().Data());
         i++;
      }
   }
   if (labels2) {
      TIter iL(labels2);
      TObjString* lb;
      Int_t i = 1;
      while ((lb=(TObjString*)iL())) {
         h2->GetYaxis()->SetBinLabel(i,lb->String().Data());
         i++;
      }
   }
   h2->SetLineColor(this->GetLineColor());
   h2->SetFillColor(this->GetFillColor());
   h2->SetMarkerColor(this->GetMarkerColor());
   h2->SetMarkerStyle(this->GetMarkerStyle());

   // Activate errors
   if ( computeErrors) h2->Sumw2();

   // Set references to the axis, so that the bucle has no branches.
   TAxis* out = 0;
   if ( projX != GetXaxis() && projY != GetXaxis() ) {
      out = GetXaxis();
   } else if ( projX != GetYaxis() && projY != GetYaxis() ) {
      out = GetYaxis();
   } else {
      out = GetZaxis();
   }

   Int_t *refX = 0, *refY = 0, *refZ = 0;
   Int_t ixbin, iybin, outbin;
   if ( projX == GetXaxis() && projY == GetYaxis() ) { refX = &ixbin;  refY = &iybin;  refZ = &outbin; }
   if ( projX == GetYaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &ixbin;  refZ = &outbin; }
   if ( projX == GetXaxis() && projY == GetZaxis() ) { refX = &ixbin;  refY = &outbin; refZ = &iybin;  }
   if ( projX == GetZaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &outbin; refZ = &ixbin;  }
   if ( projX == GetYaxis() && projY == GetZaxis() ) { refX = &outbin; refY = &ixbin;  refZ = &iybin;  }
   if ( projX == GetZaxis() && projY == GetYaxis() ) { refX = &outbin; refY = &iybin;  refZ = &ixbin;  }

   // Fill the projected histogram excluding underflow/overflows if considered in the option
   // if specified in the option (by default they considered)
   Double_t totcont  = 0;

   Int_t outmin = out->GetFirst(); 
   Int_t outmax = out->GetLast(); 
   // GetFirst(), GetLast() can return (0,0) when the range bit is set artifically (see TAxis::SetRange)
   if (outmin == 0 && outmax == 0) { outmin = 1; outmax = out->GetNbins(); }
   // correct for underflow/overflows
   if (useUF && !out->TestBit(TAxis::kAxisRange) )  outmin -= 1; 
   if (useOF && !out->TestBit(TAxis::kAxisRange) )  outmax += 1; 

   for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++){
      if ( projX->TestBit(TAxis::kAxisRange) && ( ixbin < ixmin || ixbin > ixmax )) continue;
      Int_t ix = h2->GetYaxis()->FindBin( projX->GetBinCenter(ixbin) );

      for (iybin=0;iybin<=1+projY->GetNbins();iybin++){
         if ( projY->TestBit(TAxis::kAxisRange) && ( iybin < iymin || iybin > iymax )) continue;
         Int_t iy = h2->GetXaxis()->FindBin( projY->GetBinCenter(iybin) );

         Double_t cont = 0; 
         Double_t err2 = 0;

         // loop on the bins to be integrated (outbin should be called inbin)
         for (outbin = outmin; outbin <= outmax; outbin++){

            Int_t bin = GetBin(*refX,*refY,*refZ);

            // sum the bin contents and errors if needed
            cont += GetBinContent(bin);
            if (computeErrors) { 
               Double_t exyz = GetBinError(bin);
               err2 += exyz*exyz;
            }

         }

         // remember axis are inverted 
         h2->SetBinContent(iy , ix, cont);
         if (computeErrors) h2->SetBinError(iy, ix, TMath::Sqrt(err2) ); 
         // sum all content
         totcont += cont;

      }
   }

   // since we use fill we need to reset and recalculate the statistics (see comment in DoProject1D )
   // or keep original statistics if consistent sumw2  
   bool resetStats = true; 
   double eps = 1.E-12;
   if (IsA() == TH3F::Class() ) eps = 1.E-6;
   if (fTsumw != 0 && TMath::Abs( fTsumw - totcont) <  TMath::Abs(fTsumw) * eps) resetStats = false; 

   bool resetEntries = resetStats; 
   // entries are calculated using underflow/overflow. If excluded entries must be reset
   resetEntries |= !useUF || !useOF; 

   if (!resetStats) {
      Double_t stats[kNstat];
      Double_t oldst[kNstat]; // old statistics
      GetStats(oldst); 
      std::copy(oldst,oldst+kNstat,stats);
      // not that projX refer to Y axis and projX refer to the X axis of projected histogram
      // nothing to do for projection in Y vs X
      if ( projY == GetXaxis() && projX == GetZaxis() ) {  // case XZ
         stats[4] = oldst[7];
         stats[5] = oldst[8];
         stats[6] = oldst[9];
      }
      if ( projY == GetYaxis() ) {
         stats[2] = oldst[4];
         stats[3] = oldst[5]; 
         if ( projX == GetXaxis() )  { // case YX
            stats[4] = oldst[2]; 
            stats[5] = oldst[3];
         }
         if ( projX == GetZaxis() )  { // case YZ
            stats[4] = oldst[7]; 
            stats[5] = oldst[8];
            stats[6] = oldst[10];
         }
      }
      else if  ( projY == GetZaxis() ) {
         stats[2] = oldst[7];
         stats[3] = oldst[8]; 
         if ( projX == GetXaxis() )  { // case ZX
            stats[4] = oldst[2]; 
            stats[5] = oldst[3];
            stats[6] = oldst[9];
         }
         if ( projX == GetZaxis() )  { // case ZY
            stats[4] = oldst[4]; 
            stats[5] = oldst[5];
            stats[6] = oldst[10];
         }
      }
      // set the new statistics 
      h2->PutStats(stats);
   }
   else { 
      // recalculate the statistics
      h2->ResetStats(); 
   }

   if (resetEntries) { 
      // use the effective entries for the entries
      // since this  is the only way to estimate them
      Double_t entries =  h2->GetEffectiveEntries();
      if (!computeErrors) entries = TMath::Floor( entries + 0.5); // to avoid numerical rounding
      h2->SetEntries( entries );  
   }
   else { 
      h2->SetEntries( fEntries );  
   }


   return h2;
}


//______________________________________________________________________________
TH1 *TH3::Project3D(Option_t *option) const
{
   // Project a 3-d histogram into 1 or 2-d histograms depending on the
   // option parameter
   // option may contain a combination of the characters x,y,z,e
   // option = "x" return the x projection into a TH1D histogram
   // option = "y" return the y projection into a TH1D histogram
   // option = "z" return the z projection into a TH1D histogram
   // option = "xy" return the x versus y projection into a TH2D histogram
   // option = "yx" return the y versus x projection into a TH2D histogram
   // option = "xz" return the x versus z projection into a TH2D histogram
   // option = "zx" return the z versus x projection into a TH2D histogram
   // option = "yz" return the y versus z projection into a TH2D histogram
   // option = "zy" return the z versus y projection into a TH2D histogram
   // NB: the notation "a vs b" means "a" vertical and "b" horizontal
   //
   // option = "o" original axis range of the taget axes will be
   //   kept, but only bins inside the selected range will be filled.
   //
   // If option contains the string "e", errors are computed
   //
   // The projection is made for the selected bins only.
   // To select a bin range along an axis, use TAxis::SetRange, eg
   //    h3.GetYaxis()->SetRange(23,56);
   //
   // NOTE 1: The generated histogram is named th3name + option
   // eg if the TH3* h histogram is named "myhist", then
   // h->Project3D("xy"); produces a TH2D histogram named "myhist_xy"
   // if a histogram of the same type already exists, it is overwritten.
   // The following sequence
   //    h->Project3D("xy");
   //    h->Project3D("xy2");
   //  will generate two TH2D histograms named "myhist_xy" and "myhist_xy2"
   //  A different name can be generated by attaching a string to the option
   //  For example h->Project3D("name_xy") will generate an histogram with the name:  h3dname_name_xy. 
   //
   //  NOTE 2: If an histogram of the same type already exists with compatible axes, 
   //  the histogram is reset and filled again with the projected contents of the TH3.
   //  In the case of axes incompatibility, an error is reported and a NULL pointer is returned.
   //
   //  NOTE 3: The number of entries in the projected histogram is estimated from the number of 
   //  effective entries for all the cells included in the projection. 
   //
   //  NOTE 4: underflow/overflow are included by default in the projection 
   //  To exclude underflow and/or overflow (for both axis in case of a projection to a 1D histogram) use option "NUF" and/or "NOF"
   //  With SetRange() you can have all bins except underflow/overflow only if you set the axis bit range as 
   //  following after having called SetRange: 
   //    axis->SetRange(1, axis->GetNbins());
   //    axis->SetBit(TAxis::kAxisRange);  
   //          

   TString opt = option; opt.ToLower();
   Int_t pcase = 0;
   TString ptype; 
   if (opt.Contains("x"))  { pcase = 1; ptype = "x"; }
   if (opt.Contains("y"))  { pcase = 2; ptype = "y"; }
   if (opt.Contains("z"))  { pcase = 3; ptype = "z"; }
   if (opt.Contains("xy")) { pcase = 4; ptype = "xy"; }
   if (opt.Contains("yx")) { pcase = 5; ptype = "yx"; }
   if (opt.Contains("xz")) { pcase = 6; ptype = "xz"; }
   if (opt.Contains("zx")) { pcase = 7; ptype = "zx"; }
   if (opt.Contains("yz")) { pcase = 8; ptype = "yz"; }
   if (opt.Contains("zy")) { pcase = 9; ptype = "zy"; }
   
   if (pcase == 0) { 
      Error("Project3D","No projection axis specified - return a NULL pointer"); 
      return 0; 
   }
   // do not remove ptype from opt to use later in the projected histo name

   Bool_t computeErrors = GetSumw2N();
   if (opt.Contains("e") ) { 
      computeErrors = kTRUE;
      opt.Remove(opt.First("e"),1);
   }

   Bool_t useUF = kTRUE;
   Bool_t useOF = kTRUE;
   if (opt.Contains("nuf") ) { 
      useUF = kFALSE;
      opt.Remove(opt.Index("nuf"),3);
   }
   if (opt.Contains("nof") ) { 
      useOF = kFALSE;
      opt.Remove(opt.Index("nof"),3);
   }

   Bool_t originalRange = kFALSE;
   if (opt.Contains('o') ) { 
      originalRange = kTRUE; 
      opt.Remove(opt.First("o"),1);
   }


   // Create the projection histogram
   TH1 *h = 0;

   TString name = GetName();
   TString title = GetTitle();
   name  += "_";   name  += opt;  // opt may include a user defined name
   title += " ";   title += ptype; title += " projection";   

   switch (pcase) {
      case 1: 
         // "x"
         h = DoProject1D(name, title, this->GetXaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 2:
         // "y"
         h = DoProject1D(name, title, this->GetYaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 3:
         // "z"
         h = DoProject1D(name, title, this->GetZaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 4:
         // "xy"
         h = DoProject2D(name, title, this->GetXaxis(),this->GetYaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 5:
         // "yx"
         h = DoProject2D(name, title, this->GetYaxis(),this->GetXaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 6:
         // "xz"
         h = DoProject2D(name, title, this->GetXaxis(),this->GetZaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;
         
      case 7:
         // "zx"
         h = DoProject2D(name, title, this->GetZaxis(),this->GetXaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 8:
         // "yz"
         h = DoProject2D(name, title, this->GetYaxis(),this->GetZaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

      case 9:
         // "zy"
         h = DoProject2D(name, title, this->GetZaxis(),this->GetYaxis(), 
                       computeErrors, originalRange, useUF, useOF);
         break;

   }

   // draw in current pad 
   if (h && opt.Contains("d")) {
      opt.Remove(opt.First("d"),1);
      TVirtualPad *padsav = gPad;
      TVirtualPad *pad = gROOT->GetSelectedPad();
      if (pad) pad->cd();
      if (!gPad->FindObject(h)) {
         h->Draw(opt);
      } else {
         h->Paint(opt);
      }
      if (padsav) padsav->cd();
   }

   return h;
}

void TH3::DoFillProfileProjection(TProfile2D * p2, const TAxis & a1, const TAxis & a2,  const TAxis & a3, Int_t bin1, Int_t bin2, Int_t bin3, Int_t inBin, Bool_t useWeights ) const { 
   // internal function to fill the bins of the projected profile 2D histogram 
   // called from DoProjectProfile2D

   Double_t cont = GetBinContent(inBin); 
   if (!cont) return; 
   TArrayD & binSumw2 = *(p2->GetBinSumw2()); 
   if (useWeights && binSumw2.fN <= 0) useWeights = false;  
   // the following fill update wrongly the fBinSumw2- need to save it before
   Double_t u = a1.GetBinCenter(bin1);
   Double_t v = a2.GetBinCenter(bin2);
   Double_t w = a3.GetBinCenter(bin3);
   Int_t outBin = p2->FindBin(u, v);
   Double_t tmp = 0;
   if ( useWeights ) tmp = binSumw2.fArray[outBin];            
   p2->Fill( u , v, w, cont);
//    std::cout << "use "  << useWeights; 
//    std::cout << " size " << binSumw2.fN << " inBin " << inBin << " o " << outBin << "  "  << bin1 << "  " << bin2 << " " << fSumw2.fN 
//              << " u " << u << " v " << v << " w " << w << " tmp " << tmp << " sumw2 " << fSumw2.fArray[outBin] 
//              << " fbinsumw2 " << binSumw2.fArray[outBin]
//              << std::endl; 
   if (useWeights ) binSumw2.fArray[outBin] = tmp + fSumw2.fArray[inBin];
} 

//______________________________________________________________________________
TProfile2D *TH3::DoProjectProfile2D(const char* name, const char * title, TAxis* projX, TAxis* projY, 
                                          bool originalRange, bool useUF, bool useOF) const
{
   // internal method to project to a 2D Profile
   // called from TH3::Project3DProfile

   // Get the ranges where we will work.
   Int_t ixmin = projX->GetFirst();
   Int_t ixmax = projX->GetLast();
   Int_t iymin = projY->GetFirst();
   Int_t iymax = projY->GetLast();
   if (ixmin == 0 && ixmax == 0) { ixmin = 1; ixmax = projX->GetNbins(); }
   if (iymin == 0 && iymax == 0) { iymin = 1; iymax = projY->GetNbins(); }
   Int_t nx = ixmax-ixmin+1;
   Int_t ny = iymax-iymin+1;

   // Create the projected profiles
   TProfile2D *p2 = 0;

   // Create the histogram, either reseting a preexisting one 
   // if compatible or creating one from scratch.
   // Does an object with the same name exists?
   TObject *p2obj = gROOT->FindObject(name);
   if (p2obj && p2obj->InheritsFrom("TH1")) {
      if (p2obj->IsA() != TProfile2D::Class() ) { 
         Error("DoProjectProfile2D","Histogram with name %s must be a TProfile2D and is a %s",name,p2obj->ClassName());
         return 0; 
      }
      p2 = (TProfile2D*)p2obj;
      // check histogram compatibility (not perfect for variable bins histograms)
      // note that the x axis of the projected histogram is  labeld  Y of the original
      if ( ( p2->GetNbinsX()           == projY->GetNbins()  && 
             p2->GetXaxis()->GetXmin() == projY->GetXmin()   &&
             p2->GetXaxis()->GetXmax() == projY->GetXmax() ) && 
           ( p2->GetNbinsY()          ==  projX->GetNbins()  && 
             p2->GetYaxis()->GetXmin() == projX->GetXmin()   &&
             p2->GetYaxis()->GetXmax() == projX->GetXmax() )  ) {  
         // enable originalRange option in case a range is set in the outer axis
         originalRange = kTRUE; 
         p2->Reset();
      }
      else if ( ( p2->GetNbinsX()           ==  ny                          && 
                  p2->GetXaxis()->GetXmin() == projY->GetBinLowEdge(iymin)  &&
                  p2->GetXaxis()->GetXmax() == projY->GetBinUpEdge(iymax) ) &&
                ( p2->GetNbinsY()           ==  nx                          && 
                  p2->GetYaxis()->GetXmin() == projX->GetBinLowEdge(ixmin)  &&
                  p2->GetYaxis()->GetXmax() == projX->GetBinUpEdge(ixmax) )  ) { 
         // reset also in case an histogram exists with compatible axis with the zoomed original axis
         p2->Reset();   
      }      
      else {  
         p2->Dump();
         projY->Dump(); projX->Dump(); 
         std::cout << ny << "  " << iymin << " , " << iymax << " nx " << nx << "  " << ixmin << " , " << ixmax << std::endl;
         Error("DoProjectProfile2D","Profile2D with name %s alread exists and it is not compatible",name);
         return 0; 
      }
   }

   if (!p2) { 
      const TArrayD *xbins = projX->GetXbins();
      const TArrayD *ybins = projY->GetXbins();
      if ( originalRange ) {
         if (xbins->fN == 0 && ybins->fN == 0) {
            p2 = new TProfile2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
                                ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
         } else if (ybins->fN == 0) {
            p2 = new TProfile2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
                                ,projX->GetNbins(),&xbins->fArray[ixmin-1]);
         } else if (xbins->fN == 0) {
            p2 = new TProfile2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1]
                                ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
         } else {
            p2 = new TProfile2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1],projX->GetNbins(),&xbins->fArray[ixmin-1]);
         }
      } else {
         if (xbins->fN == 0 && ybins->fN == 0) {
            p2 = new TProfile2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
                                ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
         } else if (ybins->fN == 0) {
            p2 = new TProfile2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
                                ,nx,&xbins->fArray[ixmin-1]);
         } else if (xbins->fN == 0) {
            p2 = new TProfile2D(name,title,ny,&ybins->fArray[iymin-1]
                                ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
         } else {
            p2 = new TProfile2D(name,title,ny,&ybins->fArray[iymin-1],nx,&xbins->fArray[ixmin-1]);
         }
      }
   }

   // Set references to the axis, so that the loop has no branches.
   TAxis* outAxis = 0;
   if ( projX != GetXaxis() && projY != GetXaxis() ) {
      outAxis = GetXaxis();
   } else if ( projX != GetYaxis() && projY != GetYaxis() ) {
      outAxis = GetYaxis();
   } else {
      outAxis = GetZaxis();
   }

   // Weights management
   bool useWeights = (GetSumw2N() > 0); 
   if (useWeights ) p2->Sumw2(); // store sum of w2 in profile if histo is weighted
   
   // Set references to the bins, so that the loop has no branches.
   Int_t *refX = 0, *refY = 0, *refZ = 0;
   Int_t ixbin, iybin, outbin;
   if ( projX == GetXaxis() && projY == GetYaxis() ) { refX = &ixbin;  refY = &iybin;  refZ = &outbin; }
   if ( projX == GetYaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &ixbin;  refZ = &outbin; }
   if ( projX == GetXaxis() && projY == GetZaxis() ) { refX = &ixbin;  refY = &outbin; refZ = &iybin;  }
   if ( projX == GetZaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &outbin; refZ = &ixbin;  }
   if ( projX == GetYaxis() && projY == GetZaxis() ) { refX = &outbin; refY = &ixbin;  refZ = &iybin;  }
   if ( projX == GetZaxis() && projY == GetYaxis() ) { refX = &outbin; refY = &iybin;  refZ = &ixbin;  }

   Int_t outmin = outAxis->GetFirst(); 
   Int_t outmax = outAxis->GetLast(); 
   // GetFirst(), GetLast() can return (0,0) when the range bit is set artifically (see TAxis::SetRange)
   if (outmin == 0 && outmax == 0) { outmin = 1; outmax = outAxis->GetNbins(); }
   // correct for underflow/overflows
   if (useUF && !outAxis->TestBit(TAxis::kAxisRange) )  outmin -= 1; 
   if (useOF && !outAxis->TestBit(TAxis::kAxisRange) )  outmax += 1; 

   TArrayD & binSumw2 = *(p2->GetBinSumw2()); 
   if (useWeights && binSumw2.fN <= 0) useWeights = false;  

   // Call specific method for the projection
   for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++){
      if ( (ixbin < ixmin || ixbin > ixmax) && projX->TestBit(TAxis::kAxisRange)) continue;
      for ( iybin=0;iybin<=1+projY->GetNbins();iybin++){
         if ( (iybin < iymin || iybin > iymax) && projX->TestBit(TAxis::kAxisRange)) continue;

         // profile output bin
         Int_t poutBin = p2->FindBin(projY->GetBinCenter(iybin), projX->GetBinCenter(ixbin));

         // loop on the bins to be integrated (outbin should be called inbin)
         for (outbin = outmin; outbin <= outmax; outbin++){

            Int_t bin = GetBin(*refX,*refY,*refZ);

            //DoFillProfileProjection(p2, *projY, *projX, *outAxis, iybin, ixbin, outbin, bin, useWeights); 

            Double_t cont = GetBinContent(bin); 
            if (!cont) continue; 

            Double_t tmp = 0;
            // the following fill update wrongly the fBinSumw2- need to save it before
            if ( useWeights ) tmp = binSumw2.fArray[poutBin];            
            p2->Fill( projY->GetBinCenter(iybin) , projX->GetBinCenter(ixbin), outAxis->GetBinCenter(outbin), cont);
            if (useWeights ) binSumw2.fArray[poutBin] = tmp + fSumw2.fArray[bin];
  
         }
      }
   }

   // recompute statistics for the projected profiles 
   // forget about preserving old statistics
   bool resetStats = true; 
   Double_t stats[kNstat];
   // reset statistics 
   if (resetStats) 
      for (Int_t i=0;i<kNstat;i++) stats[i] = 0;

   p2->PutStats(stats);
   Double_t entries = fEntries; 
   // recalculate the statistics
   if (resetStats) { 
      entries =  p2->GetEffectiveEntries();
      if (!useWeights) entries = TMath::Floor( entries + 0.5); // to avoid numerical rounding
      p2->SetEntries( entries );  
   }

   p2->SetEntries(entries);

   return p2;
}

//______________________________________________________________________________
TProfile2D *TH3::Project3DProfile(Option_t *option) const
{
   // Project a 3-d histogram into a 2-d profile histograms depending
   // on the option parameter
   // option may contain a combination of the characters x,y,z
   // option = "xy" return the x versus y projection into a TProfile2D histogram
   // option = "yx" return the y versus x projection into a TProfile2D histogram
   // option = "xz" return the x versus z projection into a TProfile2D histogram
   // option = "zx" return the z versus x projection into a TProfile2D histogram
   // option = "yz" return the y versus z projection into a TProfile2D histogram
   // option = "zy" return the z versus y projection into a TProfile2D histogram
   // NB: the notation "a vs b" means "a" vertical and "b" horizontal
   //
   // option = "o" original axis range of the taget axes will be
   //   kept, but only bins inside the selected range will be filled.
   //
   // The projection is made for the selected bins only.
   // To select a bin range along an axis, use TAxis::SetRange, eg
   //    h3.GetYaxis()->SetRange(23,56);
   //
   // NOTE 1: The generated histogram is named th3name + _poption
   // eg if the TH3* h histogram is named "myhist", then
   // h->Project3D("xy"); produces a TProfile2D histogram named "myhist_pxy".
   // The following sequence
   //    h->Project3DProfile("xy");
   //    h->Project3DProfile("xy2");
   //  will generate two TProfile2D histograms named "myhist_pxy" and "myhist_pxy2"
   //
   //  NOTE 2: If a profile of the same type already exists with compatible axes, 
   //  the profile is reset and filled again with the projected contents of the TH3.
   //  In the case of axes incompatibility, an error is reported and a NULL pointer is returned.
   //
   //  NOTE 3: The number of entries in the projected profile is estimated from the number of 
   //  effective entries for all the cells included in the projection. 
   //
   //  NOTE 4: underflow/overflow are by default excluded from the projection 
   //  (Note that this is a different default behavior compared to the projection to an histogram) 
   //  To include the underflow and/or overflow use option "UF" and/or "OF"

   TString opt = option; opt.ToLower();
   Int_t pcase = 0;
   TString ptype; 
   if (opt.Contains("xy")) { pcase = 4; ptype = "xy"; }
   if (opt.Contains("yx")) { pcase = 5; ptype = "yx"; }
   if (opt.Contains("xz")) { pcase = 6; ptype = "xz"; }
   if (opt.Contains("zx")) { pcase = 7; ptype = "zx"; }
   if (opt.Contains("yz")) { pcase = 8; ptype = "yz"; }
   if (opt.Contains("zy")) { pcase = 9; ptype = "zy"; }

   if (pcase == 0) { 
      Error("Project3D","No projection axis specified - return a NULL pointer"); 
      return 0; 
   }
   // do not remove ptype from opt to use later in the projected histo name

   Bool_t useUF = kFALSE;
   if (opt.Contains("uf") ) { 
      useUF = kTRUE;
      opt.Remove(opt.Index("uf"),2);
   }
   Bool_t useOF = kFALSE;
   if (opt.Contains("of") ) { 
      useOF = kTRUE;
      opt.Remove(opt.Index("of"),2);
   }

   Bool_t originalRange = kFALSE;
   if (opt.Contains('o') ) { 
      originalRange = kTRUE; 
      opt.Remove(opt.First("o"),1);
   }

   // Create the projected profile
   TProfile2D *p2 = 0;
   TString name = GetName();
   TString title = GetTitle();
   name  += "_";   name  += opt;  // opt may include a user defined name
   title += " ";   title += ptype; title += " projection";   

   // Call the method with the specific projected axes.
   switch (pcase) {
      case 4:
         // "xy"
         p2 = DoProjectProfile2D(name, title, GetXaxis(), GetYaxis(), originalRange, useUF, useOF);
         break;

      case 5:
         // "yx"
         p2 = DoProjectProfile2D(name, title, GetYaxis(), GetXaxis(), originalRange, useUF, useOF);
         break;

      case 6:
         // "xz"
         p2 = DoProjectProfile2D(name, title, GetXaxis(), GetZaxis(), originalRange, useUF, useOF);
         break;

      case 7:
         // "zx"
         p2 = DoProjectProfile2D(name, title, GetZaxis(), GetXaxis(), originalRange, useUF, useOF);
         break;

      case 8:
         // "yz"
         p2 = DoProjectProfile2D(name, title, GetYaxis(), GetZaxis(), originalRange, useUF, useOF);
         break;

      case 9:
         // "zy"
         p2 = DoProjectProfile2D(name, title, GetZaxis(), GetYaxis(), originalRange, useUF, useOF);
         break;

   }

   return p2;
}


//______________________________________________________________________________
void TH3::PutStats(Double_t *stats)
{
   // Replace current statistics with the values in array stats

   TH1::PutStats(stats);
   fTsumwy  = stats[4];
   fTsumwy2 = stats[5];
   fTsumwxy = stats[6];
   fTsumwz  = stats[7];
   fTsumwz2 = stats[8];
   fTsumwxz = stats[9];
   fTsumwyz = stats[10];
}

//______________________________________________________________________________
void TH3::Reset(Option_t *option)
{
   //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
   //*-*            ===========================================

   TH1::Reset(option);
   TString opt = option;
   opt.ToUpper();
   if (opt.Contains("ICE")) return;
   fTsumwy  = 0;
   fTsumwy2 = 0;
   fTsumwxy = 0;
   fTsumwz  = 0;
   fTsumwz2 = 0;
   fTsumwxz = 0;
   fTsumwyz = 0;
}

//______________________________________________________________________________
void TH3::Streamer(TBuffer &R__b)
{
   // Stream an object of class TH3.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         R__b.ReadClassBuffer(TH3::Class(), this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TH1::Streamer(R__b);
      TAtt3D::Streamer(R__b);
      R__b.CheckByteCount(R__s, R__c, TH3::IsA());
      //====end of old versions

   } else {
      R__b.WriteClassBuffer(TH3::Class(),this);
   }
}



//______________________________________________________________________________
//                     TH3C methods
//  TH3C a 3-D histogram with one byte per cell (char)
//______________________________________________________________________________

ClassImp(TH3C)

//______________________________________________________________________________
TH3C::TH3C(): TH3(), TArrayC()
{
   // Constructor.
   SetBinsLength(27);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3C::~TH3C()
{
   // Destructor.
}

//______________________________________________________________________________
TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
           ,Int_t nbinsy,Double_t ylow,Double_t yup
           ,Int_t nbinsz,Double_t zlow,Double_t zup)
           :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
{
   //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
   //*-*              ==================================================

   TArrayC::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();

   if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
}

//______________________________________________________________________________
TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
           ,Int_t nbinsy,const Float_t *ybins
           ,Int_t nbinsz,const Float_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayC::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
           ,Int_t nbinsy,const Double_t *ybins
           ,Int_t nbinsz,const Double_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayC::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3C::TH3C(const TH3C &h3c) : TH3(), TArrayC()
{
   // Copy constructor.

   ((TH3C&)h3c).Copy(*this);
}

//______________________________________________________________________________
void TH3C::AddBinContent(Int_t bin)
{
   //*-*-*-*-*-*-*-*-*-*Increment bin content by 1*-*-*-*-*-*-*-*-*-*-*-*-*-*
   //*-*                ==========================

   if (fArray[bin] < 127) fArray[bin]++;
}

//______________________________________________________________________________
void TH3C::AddBinContent(Int_t bin, Double_t w)
{
   //*-*-*-*-*-*-*-*-*-*Increment bin content by w*-*-*-*-*-*-*-*-*-*-*-*-*-*
   //*-*                ==========================

   Int_t newval = fArray[bin] + Int_t(w);
   if (newval > -128 && newval < 128) {fArray[bin] = Char_t(newval); return;}
   if (newval < -127) fArray[bin] = -127;
   if (newval >  127) fArray[bin] =  127;
}

//______________________________________________________________________________
void TH3C::Copy(TObject &newth3) const
{
   //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
   //*-*          ===========================================

   TH3::Copy((TH3C&)newth3);
}

//______________________________________________________________________________
TH1 *TH3C::DrawCopy(Option_t *option) const
{
   // Draw copy.

   TString opt = option;
   opt.ToLower();
   if (gPad && !opt.Contains("same")) gPad->Clear();
   TH3C *newth3 = (TH3C*)Clone();
   newth3->SetDirectory(0);
   newth3->SetBit(kCanDelete);
   newth3->AppendPad(option);
   return newth3;
}

//______________________________________________________________________________
Double_t TH3C::GetBinContent(Int_t bin) const
{
   // Get bin content.

   if (fBuffer) ((TH3C*)this)->BufferEmpty();
   if (bin < 0) bin = 0;
   if (bin >= fNcells) bin = fNcells-1;
   if (!fArray) return 0;
   return Double_t (fArray[bin]);
}

//______________________________________________________________________________
void TH3C::Reset(Option_t *option)
{
   //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
   //*-*            ===========================================

   TH3::Reset(option);
   TArrayC::Reset();
   // should also reset statistics once statistics are implemented for TH3
}

//______________________________________________________________________________
void TH3C::SetBinsLength(Int_t n)
{
   // Set total number of bins including under/overflow
   // Reallocate bin contents array

   if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
   fNcells = n;
   TArrayC::Set(n);
}

//______________________________________________________________________________
void TH3C::SetBinContent(Int_t bin, Double_t content)
{
   // Set bin content
   fEntries++;
   fTsumw = 0;
   if (bin < 0) return;
   if (bin >= fNcells) return;
   fArray[bin] = Char_t (content);
}


//______________________________________________________________________________
void TH3::SetShowProjection(const char *option,Int_t nbins)
{
   // When the mouse is moved in a pad containing a 3-d view of this histogram
   // a second canvas shows a projection type given as option.
   // To stop the generation of the projections, delete the canvas
   // containing the projection.
   // option may contain a combination of the characters x,y,z,e
   // option = "x" return the x projection into a TH1D histogram
   // option = "y" return the y projection into a TH1D histogram
   // option = "z" return the z projection into a TH1D histogram
   // option = "xy" return the x versus y projection into a TH2D histogram
   // option = "yx" return the y versus x projection into a TH2D histogram
   // option = "xz" return the x versus z projection into a TH2D histogram
   // option = "zx" return the z versus x projection into a TH2D histogram
   // option = "yz" return the y versus z projection into a TH2D histogram
   // option = "zy" return the z versus y projection into a TH2D histogram
   // option can also include the drawing option for the projection, eg to draw
   // the xy projection using the draw option "box" do
   //   myhist.SetShowProjection("xy box");
   // This function is typically called from the context menu.
   // NB: the notation "a vs b" means "a" vertical and "b" horizontal

   GetPainter();

   if (fPainter) fPainter->SetShowProjection(option,nbins);
}

//______________________________________________________________________________
void TH3C::Streamer(TBuffer &R__b)
{
   // Stream an object of class TH3C.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         R__b.ReadClassBuffer(TH3C::Class(), this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      if (R__v < 2) {
         R__b.ReadVersion();
         TH1::Streamer(R__b);
         TArrayC::Streamer(R__b);
         R__b.ReadVersion(&R__s, &R__c);
         TAtt3D::Streamer(R__b);
      } else {
         TH3::Streamer(R__b);
         TArrayC::Streamer(R__b);
         R__b.CheckByteCount(R__s, R__c, TH3C::IsA());
      }
      //====end of old versions

   } else {
      R__b.WriteClassBuffer(TH3C::Class(),this);
   }
}

//______________________________________________________________________________
TH3C& TH3C::operator=(const TH3C &h1)
{
   // Operator =

   if (this != &h1)  ((TH3C&)h1).Copy(*this);
   return *this;
}

//______________________________________________________________________________
TH3C operator*(Float_t c1, TH3C &h1)
{
   // Operator *

   TH3C hnew = h1;
   hnew.Scale(c1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3C operator+(TH3C &h1, TH3C &h2)
{
   // Operator +

   TH3C hnew = h1;
   hnew.Add(&h2,1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3C operator-(TH3C &h1, TH3C &h2)
{
   // Operator -

   TH3C hnew = h1;
   hnew.Add(&h2,-1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3C operator*(TH3C &h1, TH3C &h2)
{
   // Operator *

   TH3C hnew = h1;
   hnew.Multiply(&h2);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3C operator/(TH3C &h1, TH3C &h2)
{
   // Operator /

   TH3C hnew = h1;
   hnew.Divide(&h2);
   hnew.SetDirectory(0);
   return hnew;
}


//______________________________________________________________________________
//                     TH3S methods
//  TH3S a 3-D histogram with two bytes per cell (short integer)
//______________________________________________________________________________

ClassImp(TH3S)

//______________________________________________________________________________
TH3S::TH3S(): TH3(), TArrayS()
{
   // Constructor.
   SetBinsLength(27);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3S::~TH3S()
{
   // Destructor.
}

//______________________________________________________________________________
TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
           ,Int_t nbinsy,Double_t ylow,Double_t yup
           ,Int_t nbinsz,Double_t zlow,Double_t zup)
           :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
{
   //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
   //*-*              ==================================================
   TH3S::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();

   if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
}

//______________________________________________________________________________
TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
           ,Int_t nbinsy,const Float_t *ybins
           ,Int_t nbinsz,const Float_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TH3S::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
           ,Int_t nbinsy,const Double_t *ybins
           ,Int_t nbinsz,const Double_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TH3S::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3S::TH3S(const TH3S &h3s) : TH3(), TArrayS()
{
   // Copy Constructor.

   ((TH3S&)h3s).Copy(*this);
}

//______________________________________________________________________________
void TH3S::AddBinContent(Int_t bin)
{
   //*-*-*-*-*-*-*-*-*-*Increment bin content by 1*-*-*-*-*-*-*-*-*-*-*-*-*-*
   //*-*                ==========================

   if (fArray[bin] < 32767) fArray[bin]++;
}

//______________________________________________________________________________
void TH3S::AddBinContent(Int_t bin, Double_t w)
{
   //*-*-*-*-*-*-*-*-*-*Increment bin content by w*-*-*-*-*-*-*-*-*-*-*-*-*-*
   //*-*                ==========================

   Int_t newval = fArray[bin] + Int_t(w);
   if (newval > -32768 && newval < 32768) {fArray[bin] = Short_t(newval); return;}
   if (newval < -32767) fArray[bin] = -32767;
   if (newval >  32767) fArray[bin] =  32767;
}

//______________________________________________________________________________
void TH3S::Copy(TObject &newth3) const
{
   //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
   //*-*          ===========================================

   TH3::Copy((TH3S&)newth3);
}

//______________________________________________________________________________
TH1 *TH3S::DrawCopy(Option_t *option) const
{
   // Draw copy.

   TString opt = option;
   opt.ToLower();
   if (gPad && !opt.Contains("same")) gPad->Clear();
   TH3S *newth3 = (TH3S*)Clone();
   newth3->SetDirectory(0);
   newth3->SetBit(kCanDelete);
   newth3->AppendPad(option);
   return newth3;
}

//______________________________________________________________________________
Double_t TH3S::GetBinContent(Int_t bin) const
{
   // Get bin content.

   if (fBuffer) ((TH3S*)this)->BufferEmpty();
   if (bin < 0) bin = 0;
   if (bin >= fNcells) bin = fNcells-1;
   if (!fArray) return 0;
   return Double_t (fArray[bin]);
}

//______________________________________________________________________________
void TH3S::Reset(Option_t *option)
{
   //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
   //*-*            ===========================================

   TH3::Reset(option);
   TArrayS::Reset();
   // should also reset statistics once statistics are implemented for TH3
}

//______________________________________________________________________________
void TH3S::SetBinContent(Int_t bin, Double_t content)
{
   // Set bin content
   fEntries++;
   fTsumw = 0;
   if (bin < 0) return;
   if (bin >= fNcells) return;
   fArray[bin] = Short_t (content);
}

//______________________________________________________________________________
void TH3S::SetBinsLength(Int_t n)
{
   // Set total number of bins including under/overflow
   // Reallocate bin contents array

   if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
   fNcells = n;
   TArrayS::Set(n);
}

//______________________________________________________________________________
void TH3S::Streamer(TBuffer &R__b)
{
   // Stream an object of class TH3S.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         R__b.ReadClassBuffer(TH3S::Class(), this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      if (R__v < 2) {
         R__b.ReadVersion();
         TH1::Streamer(R__b);
         TArrayS::Streamer(R__b);
         R__b.ReadVersion(&R__s, &R__c);
         TAtt3D::Streamer(R__b);
      } else {
         TH3::Streamer(R__b);
         TArrayS::Streamer(R__b);
         R__b.CheckByteCount(R__s, R__c, TH3S::IsA());
      }
      //====end of old versions

   } else {
      R__b.WriteClassBuffer(TH3S::Class(),this);
   }
}

//______________________________________________________________________________
TH3S& TH3S::operator=(const TH3S &h1)
{
   // Operator =

   if (this != &h1)  ((TH3S&)h1).Copy(*this);
   return *this;
}

//______________________________________________________________________________
TH3S operator*(Float_t c1, TH3S &h1)
{
   // Operator *

   TH3S hnew = h1;
   hnew.Scale(c1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3S operator+(TH3S &h1, TH3S &h2)
{
   // Operator +

   TH3S hnew = h1;
   hnew.Add(&h2,1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3S operator-(TH3S &h1, TH3S &h2)
{
   // Operator -

   TH3S hnew = h1;
   hnew.Add(&h2,-1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3S operator*(TH3S &h1, TH3S &h2)
{
   // Operator *

   TH3S hnew = h1;
   hnew.Multiply(&h2);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3S operator/(TH3S &h1, TH3S &h2)
{
   // Operator /

   TH3S hnew = h1;
   hnew.Divide(&h2);
   hnew.SetDirectory(0);
   return hnew;
}


//______________________________________________________________________________
//                     TH3I methods
//  TH3I a 3-D histogram with four bytes per cell (32 bits integer)
//______________________________________________________________________________

ClassImp(TH3I)

//______________________________________________________________________________
TH3I::TH3I(): TH3(), TArrayI()
{
   // Constructor.
   SetBinsLength(27);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3I::~TH3I()
{
   // Destructor.
}

//______________________________________________________________________________
TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
           ,Int_t nbinsy,Double_t ylow,Double_t yup
           ,Int_t nbinsz,Double_t zlow,Double_t zup)
           :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
{
   //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
   //*-*              ==================================================
   TH3I::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();

   if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
}

//______________________________________________________________________________
TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
           ,Int_t nbinsy,const Float_t *ybins
           ,Int_t nbinsz,const Float_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayI::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
           ,Int_t nbinsy,const Double_t *ybins
           ,Int_t nbinsz,const Double_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayI::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3I::TH3I(const TH3I &h3i) : TH3(), TArrayI()
{
   // Copy constructor.

   ((TH3I&)h3i).Copy(*this);
}

//______________________________________________________________________________
void TH3I::AddBinContent(Int_t bin)
{
   //*-*-*-*-*-*-*-*-*-*Increment bin content by 1*-*-*-*-*-*-*-*-*-*-*-*-*-*
   //*-*                ==========================

   if (fArray[bin] < 2147483647) fArray[bin]++;
}

//______________________________________________________________________________
void TH3I::AddBinContent(Int_t bin, Double_t w)
{
   //*-*-*-*-*-*-*-*-*-*Increment bin content by w*-*-*-*-*-*-*-*-*-*-*-*-*-*
   //*-*                ==========================

   Int_t newval = fArray[bin] + Int_t(w);
   if (newval > -2147483647 && newval < 2147483647) {fArray[bin] = Int_t(newval); return;}
   if (newval < -2147483647) fArray[bin] = -2147483647;
   if (newval >  2147483647) fArray[bin] =  2147483647;
}

//______________________________________________________________________________
void TH3I::Copy(TObject &newth3) const
{
   //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
   //*-*          ===========================================

   TH3::Copy((TH3I&)newth3);
}

//______________________________________________________________________________
TH1 *TH3I::DrawCopy(Option_t *option) const
{
   // Draw copy.

   TString opt = option;
   opt.ToLower();
   if (gPad && !opt.Contains("same")) gPad->Clear();
   TH3I *newth3 = (TH3I*)Clone();
   newth3->SetDirectory(0);
   newth3->SetBit(kCanDelete);
   newth3->AppendPad(option);
   return newth3;
}

//______________________________________________________________________________
Double_t TH3I::GetBinContent(Int_t bin) const
{
   // Get bin content.

   if (fBuffer) ((TH3I*)this)->BufferEmpty();
   if (bin < 0) bin = 0;
   if (bin >= fNcells) bin = fNcells-1;
   if (!fArray) return 0;
   return Double_t (fArray[bin]);
}

//______________________________________________________________________________
void TH3I::Reset(Option_t *option)
{
   //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
   //*-*            ===========================================

   TH3::Reset(option);
   TArrayI::Reset();
   // should also reset statistics once statistics are implemented for TH3
}

//______________________________________________________________________________
void TH3I::SetBinContent(Int_t bin, Double_t content)
{
   // Set bin content
   fEntries++;
   fTsumw = 0;
   if (bin < 0) return;
   if (bin >= fNcells) return;
   fArray[bin] = Int_t (content);
}

//______________________________________________________________________________
void TH3I::SetBinsLength(Int_t n)
{
   // Set total number of bins including under/overflow
   // Reallocate bin contents array

   if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
   fNcells = n;
   TArrayI::Set(n);
}

//______________________________________________________________________________
TH3I& TH3I::operator=(const TH3I &h1)
{
   // Operator =

   if (this != &h1)  ((TH3I&)h1).Copy(*this);
   return *this;
}

//______________________________________________________________________________
TH3I operator*(Float_t c1, TH3I &h1)
{
   // Operator *

   TH3I hnew = h1;
   hnew.Scale(c1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3I operator+(TH3I &h1, TH3I &h2)
{
   // Operator +

   TH3I hnew = h1;
   hnew.Add(&h2,1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3I operator-(TH3I &h1, TH3I &h2)
{
   // Operator _

   TH3I hnew = h1;
   hnew.Add(&h2,-1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3I operator*(TH3I &h1, TH3I &h2)
{
   // Operator *

   TH3I hnew = h1;
   hnew.Multiply(&h2);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3I operator/(TH3I &h1, TH3I &h2)
{
   // Operator /

   TH3I hnew = h1;
   hnew.Divide(&h2);
   hnew.SetDirectory(0);
   return hnew;
}


//______________________________________________________________________________
//                     TH3F methods
//  TH3F a 3-D histogram with four bytes per cell (float)
//______________________________________________________________________________

ClassImp(TH3F)

//______________________________________________________________________________
TH3F::TH3F(): TH3(), TArrayF()
{
   // Constructor.
   SetBinsLength(27);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3F::~TH3F()
{
   // Destructor.
}

//______________________________________________________________________________
TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
           ,Int_t nbinsy,Double_t ylow,Double_t yup
           ,Int_t nbinsz,Double_t zlow,Double_t zup)
           :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
{
   //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
   //*-*              ==================================================
   TArrayF::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();

   if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
}

//______________________________________________________________________________
TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
           ,Int_t nbinsy,const Float_t *ybins
           ,Int_t nbinsz,const Float_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayF::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
           ,Int_t nbinsy,const Double_t *ybins
           ,Int_t nbinsz,const Double_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayF::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3F::TH3F(const TH3F &h3f) : TH3(), TArrayF()
{
   // Copy constructor.

   ((TH3F&)h3f).Copy(*this);
}

//______________________________________________________________________________
void TH3F::Copy(TObject &newth3) const
{
   //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
   //*-*          ===========================================

   TH3::Copy((TH3F&)newth3);
}

//______________________________________________________________________________
TH1 *TH3F::DrawCopy(Option_t *option) const
{
   // Draw copy.

   TString opt = option;
   opt.ToLower();
   if (gPad && !opt.Contains("same")) gPad->Clear();
   TH3F *newth3 = (TH3F*)Clone();
   newth3->SetDirectory(0);
   newth3->SetBit(kCanDelete);
   newth3->AppendPad(option);
   return newth3;
}

//______________________________________________________________________________
Double_t TH3F::GetBinContent(Int_t bin) const
{
   // Get bin content.

   if (fBuffer) ((TH3F*)this)->BufferEmpty();
   if (bin < 0) bin = 0;
   if (bin >= fNcells) bin = fNcells-1;
   if (!fArray) return 0;
   return Double_t (fArray[bin]);
}

//______________________________________________________________________________
void TH3F::Reset(Option_t *option)
{
   //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
   //*-*            ===========================================

   TH3::Reset(option);
   TArrayF::Reset();
   // should also reset statistics once statistics are implemented for TH3
}

//______________________________________________________________________________
void TH3F::SetBinContent(Int_t bin, Double_t content)
{
   // Set bin content
   fEntries++;
   fTsumw = 0;
   if (bin < 0) return;
   if (bin >= fNcells) return;
   fArray[bin] = Float_t (content);
}

//______________________________________________________________________________
void TH3F::SetBinsLength(Int_t n)
{
   // Set total number of bins including under/overflow
   // Reallocate bin contents array

   if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
   fNcells = n;
   TArrayF::Set(n);
}

//______________________________________________________________________________
void TH3F::Streamer(TBuffer &R__b)
{
   // Stream an object of class TH3F.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         R__b.ReadClassBuffer(TH3F::Class(), this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      if (R__v < 2) {
         R__b.ReadVersion();
         TH1::Streamer(R__b);
         TArrayF::Streamer(R__b);
         R__b.ReadVersion(&R__s, &R__c);
         TAtt3D::Streamer(R__b);
      } else {
         TH3::Streamer(R__b);
         TArrayF::Streamer(R__b);
         R__b.CheckByteCount(R__s, R__c, TH3F::IsA());
      }
      //====end of old versions

   } else {
      R__b.WriteClassBuffer(TH3F::Class(),this);
   }
}

//______________________________________________________________________________
TH3F& TH3F::operator=(const TH3F &h1)
{
   // Operator =

   if (this != &h1)  ((TH3F&)h1).Copy(*this);
   return *this;
}

//______________________________________________________________________________
TH3F operator*(Float_t c1, TH3F &h1)
{
   // Operator *

   TH3F hnew = h1;
   hnew.Scale(c1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3F operator+(TH3F &h1, TH3F &h2)
{
   // Operator +

   TH3F hnew = h1;
   hnew.Add(&h2,1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3F operator-(TH3F &h1, TH3F &h2)
{
   // Operator -

   TH3F hnew = h1;
   hnew.Add(&h2,-1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3F operator*(TH3F &h1, TH3F &h2)
{
   // Operator *

   TH3F hnew = h1;
   hnew.Multiply(&h2);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3F operator/(TH3F &h1, TH3F &h2)
{
   // Operator /

   TH3F hnew = h1;
   hnew.Divide(&h2);
   hnew.SetDirectory(0);
   return hnew;
}


//______________________________________________________________________________
//                     TH3D methods
//  TH3D a 3-D histogram with eight bytes per cell (double)
//______________________________________________________________________________

ClassImp(TH3D)

//______________________________________________________________________________
TH3D::TH3D(): TH3(), TArrayD()
{
   // Constructor.
   SetBinsLength(27);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3D::~TH3D()
{
   // Destructor.
}

//______________________________________________________________________________
TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
           ,Int_t nbinsy,Double_t ylow,Double_t yup
           ,Int_t nbinsz,Double_t zlow,Double_t zup)
           :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
{
   //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
   //*-*              ==================================================
   TArrayD::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();

   if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
}

//______________________________________________________________________________
TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
           ,Int_t nbinsy,const Float_t *ybins
           ,Int_t nbinsz,const Float_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayD::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
           ,Int_t nbinsy,const Double_t *ybins
           ,Int_t nbinsz,const Double_t *zbins)
           :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
{
   //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
   //*-*            =======================================================
   TArrayD::Set(fNcells);
   if (fgDefaultSumw2) Sumw2();
}

//______________________________________________________________________________
TH3D::TH3D(const TH3D &h3d) : TH3(), TArrayD()
{
   // Copy constructor.

   ((TH3D&)h3d).Copy(*this);
}

//______________________________________________________________________________
void TH3D::Copy(TObject &newth3) const
{
   //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
   //*-*          ===========================================

   TH3::Copy((TH3D&)newth3);
}

//______________________________________________________________________________
TH1 *TH3D::DrawCopy(Option_t *option) const
{
   // Draw copy.

   TString opt = option;
   opt.ToLower();
   if (gPad && !opt.Contains("same")) gPad->Clear();
   TH3D *newth3 = (TH3D*)Clone();
   newth3->SetDirectory(0);
   newth3->SetBit(kCanDelete);
   newth3->AppendPad(option);
   return newth3;
}

//______________________________________________________________________________
Double_t TH3D::GetBinContent(Int_t bin) const
{
   // Get bin content.

   if (fBuffer) ((TH3D*)this)->BufferEmpty();
   if (bin < 0) bin = 0;
   if (bin >= fNcells) bin = fNcells-1;
   if (!fArray) return 0;
   return Double_t (fArray[bin]);
}

//______________________________________________________________________________
void TH3D::Reset(Option_t *option)
{
   //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
   //*-*            ===========================================

   TH3::Reset(option);
   TArrayD::Reset();
   // should also reset statistics once statistics are implemented for TH3
}

//______________________________________________________________________________
void TH3D::SetBinContent(Int_t bin, Double_t content)
{
   // Set bin content
   fEntries++;
   fTsumw = 0;
   if (bin < 0) return;
   if (bin >= fNcells) return;
   fArray[bin] = Double_t (content);
}


//______________________________________________________________________________
void TH3D::SetBinsLength(Int_t n)
{
   // Set total number of bins including under/overflow
   // Reallocate bin contents array

   if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
   fNcells = n;
   TArrayD::Set(n);
}

//______________________________________________________________________________
void TH3D::Streamer(TBuffer &R__b)
{
   // Stream an object of class TH3D.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         R__b.ReadClassBuffer(TH3D::Class(), this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      if (R__v < 2) {
         R__b.ReadVersion();
         TH1::Streamer(R__b);
         TArrayD::Streamer(R__b);
         R__b.ReadVersion(&R__s, &R__c);
         TAtt3D::Streamer(R__b);
      } else {
         TH3::Streamer(R__b);
         TArrayD::Streamer(R__b);
         R__b.CheckByteCount(R__s, R__c, TH3D::IsA());
      }
      //====end of old versions

   } else {
      R__b.WriteClassBuffer(TH3D::Class(),this);
   }
}

//______________________________________________________________________________
TH3D& TH3D::operator=(const TH3D &h1)
{
   // Operator =

   if (this != &h1)  ((TH3D&)h1).Copy(*this);
   return *this;
}

//______________________________________________________________________________
TH3D operator*(Float_t c1, TH3D &h1)
{
   // Operator *

   TH3D hnew = h1;
   hnew.Scale(c1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3D operator+(TH3D &h1, TH3D &h2)
{
   // Operator +

   TH3D hnew = h1;
   hnew.Add(&h2,1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3D operator-(TH3D &h1, TH3D &h2)
{
   // Operator -

   TH3D hnew = h1;
   hnew.Add(&h2,-1);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3D operator*(TH3D &h1, TH3D &h2)
{
   // Operator *

   TH3D hnew = h1;
   hnew.Multiply(&h2);
   hnew.SetDirectory(0);
   return hnew;
}

//______________________________________________________________________________
TH3D operator/(TH3D &h1, TH3D &h2)
{
   // Operator /

   TH3D hnew = h1;
   hnew.Divide(&h2);
   hnew.SetDirectory(0);
   return hnew;
}
 TH3.cxx:1
 TH3.cxx:2
 TH3.cxx:3
 TH3.cxx:4
 TH3.cxx:5
 TH3.cxx:6
 TH3.cxx:7
 TH3.cxx:8
 TH3.cxx:9
 TH3.cxx:10
 TH3.cxx:11
 TH3.cxx:12
 TH3.cxx:13
 TH3.cxx:14
 TH3.cxx:15
 TH3.cxx:16
 TH3.cxx:17
 TH3.cxx:18
 TH3.cxx:19
 TH3.cxx:20
 TH3.cxx:21
 TH3.cxx:22
 TH3.cxx:23
 TH3.cxx:24
 TH3.cxx:25
 TH3.cxx:26
 TH3.cxx:27
 TH3.cxx:28
 TH3.cxx:29
 TH3.cxx:30
 TH3.cxx:31
 TH3.cxx:32
 TH3.cxx:33
 TH3.cxx:34
 TH3.cxx:35
 TH3.cxx:36
 TH3.cxx:37
 TH3.cxx:38
 TH3.cxx:39
 TH3.cxx:40
 TH3.cxx:41
 TH3.cxx:42
 TH3.cxx:43
 TH3.cxx:44
 TH3.cxx:45
 TH3.cxx:46
 TH3.cxx:47
 TH3.cxx:48
 TH3.cxx:49
 TH3.cxx:50
 TH3.cxx:51
 TH3.cxx:52
 TH3.cxx:53
 TH3.cxx:54
 TH3.cxx:55
 TH3.cxx:56
 TH3.cxx:57
 TH3.cxx:58
 TH3.cxx:59
 TH3.cxx:60
 TH3.cxx:61
 TH3.cxx:62
 TH3.cxx:63
 TH3.cxx:64
 TH3.cxx:65
 TH3.cxx:66
 TH3.cxx:67
 TH3.cxx:68
 TH3.cxx:69
 TH3.cxx:70
 TH3.cxx:71
 TH3.cxx:72
 TH3.cxx:73
 TH3.cxx:74
 TH3.cxx:75
 TH3.cxx:76
 TH3.cxx:77
 TH3.cxx:78
 TH3.cxx:79
 TH3.cxx:80
 TH3.cxx:81
 TH3.cxx:82
 TH3.cxx:83
 TH3.cxx:84
 TH3.cxx:85
 TH3.cxx:86
 TH3.cxx:87
 TH3.cxx:88
 TH3.cxx:89
 TH3.cxx:90
 TH3.cxx:91
 TH3.cxx:92
 TH3.cxx:93
 TH3.cxx:94
 TH3.cxx:95
 TH3.cxx:96
 TH3.cxx:97
 TH3.cxx:98
 TH3.cxx:99
 TH3.cxx:100
 TH3.cxx:101
 TH3.cxx:102
 TH3.cxx:103
 TH3.cxx:104
 TH3.cxx:105
 TH3.cxx:106
 TH3.cxx:107
 TH3.cxx:108
 TH3.cxx:109
 TH3.cxx:110
 TH3.cxx:111
 TH3.cxx:112
 TH3.cxx:113
 TH3.cxx:114
 TH3.cxx:115
 TH3.cxx:116
 TH3.cxx:117
 TH3.cxx:118
 TH3.cxx:119
 TH3.cxx:120
 TH3.cxx:121
 TH3.cxx:122
 TH3.cxx:123
 TH3.cxx:124
 TH3.cxx:125
 TH3.cxx:126
 TH3.cxx:127
 TH3.cxx:128
 TH3.cxx:129
 TH3.cxx:130
 TH3.cxx:131
 TH3.cxx:132
 TH3.cxx:133
 TH3.cxx:134
 TH3.cxx:135
 TH3.cxx:136
 TH3.cxx:137
 TH3.cxx:138
 TH3.cxx:139
 TH3.cxx:140
 TH3.cxx:141
 TH3.cxx:142
 TH3.cxx:143
 TH3.cxx:144
 TH3.cxx:145
 TH3.cxx:146
 TH3.cxx:147
 TH3.cxx:148
 TH3.cxx:149
 TH3.cxx:150
 TH3.cxx:151
 TH3.cxx:152
 TH3.cxx:153
 TH3.cxx:154
 TH3.cxx:155
 TH3.cxx:156
 TH3.cxx:157
 TH3.cxx:158
 TH3.cxx:159
 TH3.cxx:160
 TH3.cxx:161
 TH3.cxx:162
 TH3.cxx:163
 TH3.cxx:164
 TH3.cxx:165
 TH3.cxx:166
 TH3.cxx:167
 TH3.cxx:168
 TH3.cxx:169
 TH3.cxx:170
 TH3.cxx:171
 TH3.cxx:172
 TH3.cxx:173
 TH3.cxx:174
 TH3.cxx:175
 TH3.cxx:176
 TH3.cxx:177
 TH3.cxx:178
 TH3.cxx:179
 TH3.cxx:180
 TH3.cxx:181
 TH3.cxx:182
 TH3.cxx:183
 TH3.cxx:184
 TH3.cxx:185
 TH3.cxx:186
 TH3.cxx:187
 TH3.cxx:188
 TH3.cxx:189
 TH3.cxx:190
 TH3.cxx:191
 TH3.cxx:192
 TH3.cxx:193
 TH3.cxx:194
 TH3.cxx:195
 TH3.cxx:196
 TH3.cxx:197
 TH3.cxx:198
 TH3.cxx:199
 TH3.cxx:200
 TH3.cxx:201
 TH3.cxx:202
 TH3.cxx:203
 TH3.cxx:204
 TH3.cxx:205
 TH3.cxx:206
 TH3.cxx:207
 TH3.cxx:208
 TH3.cxx:209
 TH3.cxx:210
 TH3.cxx:211
 TH3.cxx:212
 TH3.cxx:213
 TH3.cxx:214
 TH3.cxx:215
 TH3.cxx:216
 TH3.cxx:217
 TH3.cxx:218
 TH3.cxx:219
 TH3.cxx:220
 TH3.cxx:221
 TH3.cxx:222
 TH3.cxx:223
 TH3.cxx:224
 TH3.cxx:225
 TH3.cxx:226
 TH3.cxx:227
 TH3.cxx:228
 TH3.cxx:229
 TH3.cxx:230
 TH3.cxx:231
 TH3.cxx:232
 TH3.cxx:233
 TH3.cxx:234
 TH3.cxx:235
 TH3.cxx:236
 TH3.cxx:237
 TH3.cxx:238
 TH3.cxx:239
 TH3.cxx:240
 TH3.cxx:241
 TH3.cxx:242
 TH3.cxx:243
 TH3.cxx:244
 TH3.cxx:245
 TH3.cxx:246
 TH3.cxx:247
 TH3.cxx:248
 TH3.cxx:249
 TH3.cxx:250
 TH3.cxx:251
 TH3.cxx:252
 TH3.cxx:253
 TH3.cxx:254
 TH3.cxx:255
 TH3.cxx:256
 TH3.cxx:257
 TH3.cxx:258
 TH3.cxx:259
 TH3.cxx:260
 TH3.cxx:261
 TH3.cxx:262
 TH3.cxx:263
 TH3.cxx:264
 TH3.cxx:265
 TH3.cxx:266
 TH3.cxx:267
 TH3.cxx:268
 TH3.cxx:269
 TH3.cxx:270
 TH3.cxx:271
 TH3.cxx:272
 TH3.cxx:273
 TH3.cxx:274
 TH3.cxx:275
 TH3.cxx:276
 TH3.cxx:277
 TH3.cxx:278
 TH3.cxx:279
 TH3.cxx:280
 TH3.cxx:281
 TH3.cxx:282
 TH3.cxx:283
 TH3.cxx:284
 TH3.cxx:285
 TH3.cxx:286
 TH3.cxx:287
 TH3.cxx:288
 TH3.cxx:289
 TH3.cxx:290
 TH3.cxx:291
 TH3.cxx:292
 TH3.cxx:293
 TH3.cxx:294
 TH3.cxx:295
 TH3.cxx:296
 TH3.cxx:297
 TH3.cxx:298
 TH3.cxx:299
 TH3.cxx:300
 TH3.cxx:301
 TH3.cxx:302
 TH3.cxx:303
 TH3.cxx:304
 TH3.cxx:305
 TH3.cxx:306
 TH3.cxx:307
 TH3.cxx:308
 TH3.cxx:309
 TH3.cxx:310
 TH3.cxx:311
 TH3.cxx:312
 TH3.cxx:313
 TH3.cxx:314
 TH3.cxx:315
 TH3.cxx:316
 TH3.cxx:317
 TH3.cxx:318
 TH3.cxx:319
 TH3.cxx:320
 TH3.cxx:321
 TH3.cxx:322
 TH3.cxx:323
 TH3.cxx:324
 TH3.cxx:325
 TH3.cxx:326
 TH3.cxx:327
 TH3.cxx:328
 TH3.cxx:329
 TH3.cxx:330
 TH3.cxx:331
 TH3.cxx:332
 TH3.cxx:333
 TH3.cxx:334
 TH3.cxx:335
 TH3.cxx:336
 TH3.cxx:337
 TH3.cxx:338
 TH3.cxx:339
 TH3.cxx:340
 TH3.cxx:341
 TH3.cxx:342
 TH3.cxx:343
 TH3.cxx:344
 TH3.cxx:345
 TH3.cxx:346
 TH3.cxx:347
 TH3.cxx:348
 TH3.cxx:349
 TH3.cxx:350
 TH3.cxx:351
 TH3.cxx:352
 TH3.cxx:353
 TH3.cxx:354
 TH3.cxx:355
 TH3.cxx:356
 TH3.cxx:357
 TH3.cxx:358
 TH3.cxx:359
 TH3.cxx:360
 TH3.cxx:361
 TH3.cxx:362
 TH3.cxx:363
 TH3.cxx:364
 TH3.cxx:365
 TH3.cxx:366
 TH3.cxx:367
 TH3.cxx:368
 TH3.cxx:369
 TH3.cxx:370
 TH3.cxx:371
 TH3.cxx:372
 TH3.cxx:373
 TH3.cxx:374
 TH3.cxx:375
 TH3.cxx:376
 TH3.cxx:377
 TH3.cxx:378
 TH3.cxx:379
 TH3.cxx:380
 TH3.cxx:381
 TH3.cxx:382
 TH3.cxx:383
 TH3.cxx:384
 TH3.cxx:385
 TH3.cxx:386
 TH3.cxx:387
 TH3.cxx:388
 TH3.cxx:389
 TH3.cxx:390
 TH3.cxx:391
 TH3.cxx:392
 TH3.cxx:393
 TH3.cxx:394
 TH3.cxx:395
 TH3.cxx:396
 TH3.cxx:397
 TH3.cxx:398
 TH3.cxx:399
 TH3.cxx:400
 TH3.cxx:401
 TH3.cxx:402
 TH3.cxx:403
 TH3.cxx:404
 TH3.cxx:405
 TH3.cxx:406
 TH3.cxx:407
 TH3.cxx:408
 TH3.cxx:409
 TH3.cxx:410
 TH3.cxx:411
 TH3.cxx:412
 TH3.cxx:413
 TH3.cxx:414
 TH3.cxx:415
 TH3.cxx:416
 TH3.cxx:417
 TH3.cxx:418
 TH3.cxx:419
 TH3.cxx:420
 TH3.cxx:421
 TH3.cxx:422
 TH3.cxx:423
 TH3.cxx:424
 TH3.cxx:425
 TH3.cxx:426
 TH3.cxx:427
 TH3.cxx:428
 TH3.cxx:429
 TH3.cxx:430
 TH3.cxx:431
 TH3.cxx:432
 TH3.cxx:433
 TH3.cxx:434
 TH3.cxx:435
 TH3.cxx:436
 TH3.cxx:437
 TH3.cxx:438
 TH3.cxx:439
 TH3.cxx:440
 TH3.cxx:441
 TH3.cxx:442
 TH3.cxx:443
 TH3.cxx:444
 TH3.cxx:445
 TH3.cxx:446
 TH3.cxx:447
 TH3.cxx:448
 TH3.cxx:449
 TH3.cxx:450
 TH3.cxx:451
 TH3.cxx:452
 TH3.cxx:453
 TH3.cxx:454
 TH3.cxx:455
 TH3.cxx:456
 TH3.cxx:457
 TH3.cxx:458
 TH3.cxx:459
 TH3.cxx:460
 TH3.cxx:461
 TH3.cxx:462
 TH3.cxx:463
 TH3.cxx:464
 TH3.cxx:465
 TH3.cxx:466
 TH3.cxx:467
 TH3.cxx:468
 TH3.cxx:469
 TH3.cxx:470
 TH3.cxx:471
 TH3.cxx:472
 TH3.cxx:473
 TH3.cxx:474
 TH3.cxx:475
 TH3.cxx:476
 TH3.cxx:477
 TH3.cxx:478
 TH3.cxx:479
 TH3.cxx:480
 TH3.cxx:481
 TH3.cxx:482
 TH3.cxx:483
 TH3.cxx:484
 TH3.cxx:485
 TH3.cxx:486
 TH3.cxx:487
 TH3.cxx:488
 TH3.cxx:489
 TH3.cxx:490
 TH3.cxx:491
 TH3.cxx:492
 TH3.cxx:493
 TH3.cxx:494
 TH3.cxx:495
 TH3.cxx:496
 TH3.cxx:497
 TH3.cxx:498
 TH3.cxx:499
 TH3.cxx:500
 TH3.cxx:501
 TH3.cxx:502
 TH3.cxx:503
 TH3.cxx:504
 TH3.cxx:505
 TH3.cxx:506
 TH3.cxx:507
 TH3.cxx:508
 TH3.cxx:509
 TH3.cxx:510
 TH3.cxx:511
 TH3.cxx:512
 TH3.cxx:513
 TH3.cxx:514
 TH3.cxx:515
 TH3.cxx:516
 TH3.cxx:517
 TH3.cxx:518
 TH3.cxx:519
 TH3.cxx:520
 TH3.cxx:521
 TH3.cxx:522
 TH3.cxx:523
 TH3.cxx:524
 TH3.cxx:525
 TH3.cxx:526
 TH3.cxx:527
 TH3.cxx:528
 TH3.cxx:529
 TH3.cxx:530
 TH3.cxx:531
 TH3.cxx:532
 TH3.cxx:533
 TH3.cxx:534
 TH3.cxx:535
 TH3.cxx:536
 TH3.cxx:537
 TH3.cxx:538
 TH3.cxx:539
 TH3.cxx:540
 TH3.cxx:541
 TH3.cxx:542
 TH3.cxx:543
 TH3.cxx:544
 TH3.cxx:545
 TH3.cxx:546
 TH3.cxx:547
 TH3.cxx:548
 TH3.cxx:549
 TH3.cxx:550
 TH3.cxx:551
 TH3.cxx:552
 TH3.cxx:553
 TH3.cxx:554
 TH3.cxx:555
 TH3.cxx:556
 TH3.cxx:557
 TH3.cxx:558
 TH3.cxx:559
 TH3.cxx:560
 TH3.cxx:561
 TH3.cxx:562
 TH3.cxx:563
 TH3.cxx:564
 TH3.cxx:565
 TH3.cxx:566
 TH3.cxx:567
 TH3.cxx:568
 TH3.cxx:569
 TH3.cxx:570
 TH3.cxx:571
 TH3.cxx:572
 TH3.cxx:573
 TH3.cxx:574
 TH3.cxx:575
 TH3.cxx:576
 TH3.cxx:577
 TH3.cxx:578
 TH3.cxx:579
 TH3.cxx:580
 TH3.cxx:581
 TH3.cxx:582
 TH3.cxx:583
 TH3.cxx:584
 TH3.cxx:585
 TH3.cxx:586
 TH3.cxx:587
 TH3.cxx:588
 TH3.cxx:589
 TH3.cxx:590
 TH3.cxx:591
 TH3.cxx:592
 TH3.cxx:593
 TH3.cxx:594
 TH3.cxx:595
 TH3.cxx:596
 TH3.cxx:597
 TH3.cxx:598
 TH3.cxx:599
 TH3.cxx:600
 TH3.cxx:601
 TH3.cxx:602
 TH3.cxx:603
 TH3.cxx:604
 TH3.cxx:605
 TH3.cxx:606
 TH3.cxx:607
 TH3.cxx:608
 TH3.cxx:609
 TH3.cxx:610
 TH3.cxx:611
 TH3.cxx:612
 TH3.cxx:613
 TH3.cxx:614
 TH3.cxx:615
 TH3.cxx:616
 TH3.cxx:617
 TH3.cxx:618
 TH3.cxx:619
 TH3.cxx:620
 TH3.cxx:621
 TH3.cxx:622
 TH3.cxx:623
 TH3.cxx:624
 TH3.cxx:625
 TH3.cxx:626
 TH3.cxx:627
 TH3.cxx:628
 TH3.cxx:629
 TH3.cxx:630
 TH3.cxx:631
 TH3.cxx:632
 TH3.cxx:633
 TH3.cxx:634
 TH3.cxx:635
 TH3.cxx:636
 TH3.cxx:637
 TH3.cxx:638
 TH3.cxx:639
 TH3.cxx:640
 TH3.cxx:641
 TH3.cxx:642
 TH3.cxx:643
 TH3.cxx:644
 TH3.cxx:645
 TH3.cxx:646
 TH3.cxx:647
 TH3.cxx:648
 TH3.cxx:649
 TH3.cxx:650
 TH3.cxx:651
 TH3.cxx:652
 TH3.cxx:653
 TH3.cxx:654
 TH3.cxx:655
 TH3.cxx:656
 TH3.cxx:657
 TH3.cxx:658
 TH3.cxx:659
 TH3.cxx:660
 TH3.cxx:661
 TH3.cxx:662
 TH3.cxx:663
 TH3.cxx:664
 TH3.cxx:665
 TH3.cxx:666
 TH3.cxx:667
 TH3.cxx:668
 TH3.cxx:669
 TH3.cxx:670
 TH3.cxx:671
 TH3.cxx:672
 TH3.cxx:673
 TH3.cxx:674
 TH3.cxx:675
 TH3.cxx:676
 TH3.cxx:677
 TH3.cxx:678
 TH3.cxx:679
 TH3.cxx:680
 TH3.cxx:681
 TH3.cxx:682
 TH3.cxx:683
 TH3.cxx:684
 TH3.cxx:685
 TH3.cxx:686
 TH3.cxx:687
 TH3.cxx:688
 TH3.cxx:689
 TH3.cxx:690
 TH3.cxx:691
 TH3.cxx:692
 TH3.cxx:693
 TH3.cxx:694
 TH3.cxx:695
 TH3.cxx:696
 TH3.cxx:697
 TH3.cxx:698
 TH3.cxx:699
 TH3.cxx:700
 TH3.cxx:701
 TH3.cxx:702
 TH3.cxx:703
 TH3.cxx:704
 TH3.cxx:705
 TH3.cxx:706
 TH3.cxx:707
 TH3.cxx:708
 TH3.cxx:709
 TH3.cxx:710
 TH3.cxx:711
 TH3.cxx:712
 TH3.cxx:713
 TH3.cxx:714
 TH3.cxx:715
 TH3.cxx:716
 TH3.cxx:717
 TH3.cxx:718
 TH3.cxx:719
 TH3.cxx:720
 TH3.cxx:721
 TH3.cxx:722
 TH3.cxx:723
 TH3.cxx:724
 TH3.cxx:725
 TH3.cxx:726
 TH3.cxx:727
 TH3.cxx:728
 TH3.cxx:729
 TH3.cxx:730
 TH3.cxx:731
 TH3.cxx:732
 TH3.cxx:733
 TH3.cxx:734
 TH3.cxx:735
 TH3.cxx:736
 TH3.cxx:737
 TH3.cxx:738
 TH3.cxx:739
 TH3.cxx:740
 TH3.cxx:741
 TH3.cxx:742
 TH3.cxx:743
 TH3.cxx:744
 TH3.cxx:745
 TH3.cxx:746
 TH3.cxx:747
 TH3.cxx:748
 TH3.cxx:749
 TH3.cxx:750
 TH3.cxx:751
 TH3.cxx:752
 TH3.cxx:753
 TH3.cxx:754
 TH3.cxx:755
 TH3.cxx:756
 TH3.cxx:757
 TH3.cxx:758
 TH3.cxx:759
 TH3.cxx:760
 TH3.cxx:761
 TH3.cxx:762
 TH3.cxx:763
 TH3.cxx:764
 TH3.cxx:765
 TH3.cxx:766
 TH3.cxx:767
 TH3.cxx:768
 TH3.cxx:769
 TH3.cxx:770
 TH3.cxx:771
 TH3.cxx:772
 TH3.cxx:773
 TH3.cxx:774
 TH3.cxx:775
 TH3.cxx:776
 TH3.cxx:777
 TH3.cxx:778
 TH3.cxx:779
 TH3.cxx:780
 TH3.cxx:781
 TH3.cxx:782
 TH3.cxx:783
 TH3.cxx:784
 TH3.cxx:785
 TH3.cxx:786
 TH3.cxx:787
 TH3.cxx:788
 TH3.cxx:789
 TH3.cxx:790
 TH3.cxx:791
 TH3.cxx:792
 TH3.cxx:793
 TH3.cxx:794
 TH3.cxx:795
 TH3.cxx:796
 TH3.cxx:797
 TH3.cxx:798
 TH3.cxx:799
 TH3.cxx:800
 TH3.cxx:801
 TH3.cxx:802
 TH3.cxx:803
 TH3.cxx:804
 TH3.cxx:805
 TH3.cxx:806
 TH3.cxx:807
 TH3.cxx:808
 TH3.cxx:809
 TH3.cxx:810
 TH3.cxx:811
 TH3.cxx:812
 TH3.cxx:813
 TH3.cxx:814
 TH3.cxx:815
 TH3.cxx:816
 TH3.cxx:817
 TH3.cxx:818
 TH3.cxx:819
 TH3.cxx:820
 TH3.cxx:821
 TH3.cxx:822
 TH3.cxx:823
 TH3.cxx:824
 TH3.cxx:825
 TH3.cxx:826
 TH3.cxx:827
 TH3.cxx:828
 TH3.cxx:829
 TH3.cxx:830
 TH3.cxx:831
 TH3.cxx:832
 TH3.cxx:833
 TH3.cxx:834
 TH3.cxx:835
 TH3.cxx:836
 TH3.cxx:837
 TH3.cxx:838
 TH3.cxx:839
 TH3.cxx:840
 TH3.cxx:841
 TH3.cxx:842
 TH3.cxx:843
 TH3.cxx:844
 TH3.cxx:845
 TH3.cxx:846
 TH3.cxx:847
 TH3.cxx:848
 TH3.cxx:849
 TH3.cxx:850
 TH3.cxx:851
 TH3.cxx:852
 TH3.cxx:853
 TH3.cxx:854
 TH3.cxx:855
 TH3.cxx:856
 TH3.cxx:857
 TH3.cxx:858
 TH3.cxx:859
 TH3.cxx:860
 TH3.cxx:861
 TH3.cxx:862
 TH3.cxx:863
 TH3.cxx:864
 TH3.cxx:865
 TH3.cxx:866
 TH3.cxx:867
 TH3.cxx:868
 TH3.cxx:869
 TH3.cxx:870
 TH3.cxx:871
 TH3.cxx:872
 TH3.cxx:873
 TH3.cxx:874
 TH3.cxx:875
 TH3.cxx:876
 TH3.cxx:877
 TH3.cxx:878
 TH3.cxx:879
 TH3.cxx:880
 TH3.cxx:881
 TH3.cxx:882
 TH3.cxx:883
 TH3.cxx:884
 TH3.cxx:885
 TH3.cxx:886
 TH3.cxx:887
 TH3.cxx:888
 TH3.cxx:889
 TH3.cxx:890
 TH3.cxx:891
 TH3.cxx:892
 TH3.cxx:893
 TH3.cxx:894
 TH3.cxx:895
 TH3.cxx:896
 TH3.cxx:897
 TH3.cxx:898
 TH3.cxx:899
 TH3.cxx:900
 TH3.cxx:901
 TH3.cxx:902
 TH3.cxx:903
 TH3.cxx:904
 TH3.cxx:905
 TH3.cxx:906
 TH3.cxx:907
 TH3.cxx:908
 TH3.cxx:909
 TH3.cxx:910
 TH3.cxx:911
 TH3.cxx:912
 TH3.cxx:913
 TH3.cxx:914
 TH3.cxx:915
 TH3.cxx:916
 TH3.cxx:917
 TH3.cxx:918
 TH3.cxx:919
 TH3.cxx:920
 TH3.cxx:921
 TH3.cxx:922
 TH3.cxx:923
 TH3.cxx:924
 TH3.cxx:925
 TH3.cxx:926
 TH3.cxx:927
 TH3.cxx:928
 TH3.cxx:929
 TH3.cxx:930
 TH3.cxx:931
 TH3.cxx:932
 TH3.cxx:933
 TH3.cxx:934
 TH3.cxx:935
 TH3.cxx:936
 TH3.cxx:937
 TH3.cxx:938
 TH3.cxx:939
 TH3.cxx:940
 TH3.cxx:941
 TH3.cxx:942
 TH3.cxx:943
 TH3.cxx:944
 TH3.cxx:945
 TH3.cxx:946
 TH3.cxx:947
 TH3.cxx:948
 TH3.cxx:949
 TH3.cxx:950
 TH3.cxx:951
 TH3.cxx:952
 TH3.cxx:953
 TH3.cxx:954
 TH3.cxx:955
 TH3.cxx:956
 TH3.cxx:957
 TH3.cxx:958
 TH3.cxx:959
 TH3.cxx:960
 TH3.cxx:961
 TH3.cxx:962
 TH3.cxx:963
 TH3.cxx:964
 TH3.cxx:965
 TH3.cxx:966
 TH3.cxx:967
 TH3.cxx:968
 TH3.cxx:969
 TH3.cxx:970
 TH3.cxx:971
 TH3.cxx:972
 TH3.cxx:973
 TH3.cxx:974
 TH3.cxx:975
 TH3.cxx:976
 TH3.cxx:977
 TH3.cxx:978
 TH3.cxx:979
 TH3.cxx:980
 TH3.cxx:981
 TH3.cxx:982
 TH3.cxx:983
 TH3.cxx:984
 TH3.cxx:985
 TH3.cxx:986
 TH3.cxx:987
 TH3.cxx:988
 TH3.cxx:989
 TH3.cxx:990
 TH3.cxx:991
 TH3.cxx:992
 TH3.cxx:993
 TH3.cxx:994
 TH3.cxx:995
 TH3.cxx:996
 TH3.cxx:997
 TH3.cxx:998
 TH3.cxx:999
 TH3.cxx:1000
 TH3.cxx:1001
 TH3.cxx:1002
 TH3.cxx:1003
 TH3.cxx:1004
 TH3.cxx:1005
 TH3.cxx:1006
 TH3.cxx:1007
 TH3.cxx:1008
 TH3.cxx:1009
 TH3.cxx:1010
 TH3.cxx:1011
 TH3.cxx:1012
 TH3.cxx:1013
 TH3.cxx:1014
 TH3.cxx:1015
 TH3.cxx:1016
 TH3.cxx:1017
 TH3.cxx:1018
 TH3.cxx:1019
 TH3.cxx:1020
 TH3.cxx:1021
 TH3.cxx:1022
 TH3.cxx:1023
 TH3.cxx:1024
 TH3.cxx:1025
 TH3.cxx:1026
 TH3.cxx:1027
 TH3.cxx:1028
 TH3.cxx:1029
 TH3.cxx:1030
 TH3.cxx:1031
 TH3.cxx:1032
 TH3.cxx:1033
 TH3.cxx:1034
 TH3.cxx:1035
 TH3.cxx:1036
 TH3.cxx:1037
 TH3.cxx:1038
 TH3.cxx:1039
 TH3.cxx:1040
 TH3.cxx:1041
 TH3.cxx:1042
 TH3.cxx:1043
 TH3.cxx:1044
 TH3.cxx:1045
 TH3.cxx:1046
 TH3.cxx:1047
 TH3.cxx:1048
 TH3.cxx:1049
 TH3.cxx:1050
 TH3.cxx:1051
 TH3.cxx:1052
 TH3.cxx:1053
 TH3.cxx:1054
 TH3.cxx:1055
 TH3.cxx:1056
 TH3.cxx:1057
 TH3.cxx:1058
 TH3.cxx:1059
 TH3.cxx:1060
 TH3.cxx:1061
 TH3.cxx:1062
 TH3.cxx:1063
 TH3.cxx:1064
 TH3.cxx:1065
 TH3.cxx:1066
 TH3.cxx:1067
 TH3.cxx:1068
 TH3.cxx:1069
 TH3.cxx:1070
 TH3.cxx:1071
 TH3.cxx:1072
 TH3.cxx:1073
 TH3.cxx:1074
 TH3.cxx:1075
 TH3.cxx:1076
 TH3.cxx:1077
 TH3.cxx:1078
 TH3.cxx:1079
 TH3.cxx:1080
 TH3.cxx:1081
 TH3.cxx:1082
 TH3.cxx:1083
 TH3.cxx:1084
 TH3.cxx:1085
 TH3.cxx:1086
 TH3.cxx:1087
 TH3.cxx:1088
 TH3.cxx:1089
 TH3.cxx:1090
 TH3.cxx:1091
 TH3.cxx:1092
 TH3.cxx:1093
 TH3.cxx:1094
 TH3.cxx:1095
 TH3.cxx:1096
 TH3.cxx:1097
 TH3.cxx:1098
 TH3.cxx:1099
 TH3.cxx:1100
 TH3.cxx:1101
 TH3.cxx:1102
 TH3.cxx:1103
 TH3.cxx:1104
 TH3.cxx:1105
 TH3.cxx:1106
 TH3.cxx:1107
 TH3.cxx:1108
 TH3.cxx:1109
 TH3.cxx:1110
 TH3.cxx:1111
 TH3.cxx:1112
 TH3.cxx:1113
 TH3.cxx:1114
 TH3.cxx:1115
 TH3.cxx:1116
 TH3.cxx:1117
 TH3.cxx:1118
 TH3.cxx:1119
 TH3.cxx:1120
 TH3.cxx:1121
 TH3.cxx:1122
 TH3.cxx:1123
 TH3.cxx:1124
 TH3.cxx:1125
 TH3.cxx:1126
 TH3.cxx:1127
 TH3.cxx:1128
 TH3.cxx:1129
 TH3.cxx:1130
 TH3.cxx:1131
 TH3.cxx:1132
 TH3.cxx:1133
 TH3.cxx:1134
 TH3.cxx:1135
 TH3.cxx:1136
 TH3.cxx:1137
 TH3.cxx:1138
 TH3.cxx:1139
 TH3.cxx:1140
 TH3.cxx:1141
 TH3.cxx:1142
 TH3.cxx:1143
 TH3.cxx:1144
 TH3.cxx:1145
 TH3.cxx:1146
 TH3.cxx:1147
 TH3.cxx:1148
 TH3.cxx:1149
 TH3.cxx:1150
 TH3.cxx:1151
 TH3.cxx:1152
 TH3.cxx:1153
 TH3.cxx:1154
 TH3.cxx:1155
 TH3.cxx:1156
 TH3.cxx:1157
 TH3.cxx:1158
 TH3.cxx:1159
 TH3.cxx:1160
 TH3.cxx:1161
 TH3.cxx:1162
 TH3.cxx:1163
 TH3.cxx:1164
 TH3.cxx:1165
 TH3.cxx:1166
 TH3.cxx:1167
 TH3.cxx:1168
 TH3.cxx:1169
 TH3.cxx:1170
 TH3.cxx:1171
 TH3.cxx:1172
 TH3.cxx:1173
 TH3.cxx:1174
 TH3.cxx:1175
 TH3.cxx:1176
 TH3.cxx:1177
 TH3.cxx:1178
 TH3.cxx:1179
 TH3.cxx:1180
 TH3.cxx:1181
 TH3.cxx:1182
 TH3.cxx:1183
 TH3.cxx:1184
 TH3.cxx:1185
 TH3.cxx:1186
 TH3.cxx:1187
 TH3.cxx:1188
 TH3.cxx:1189
 TH3.cxx:1190
 TH3.cxx:1191
 TH3.cxx:1192
 TH3.cxx:1193
 TH3.cxx:1194
 TH3.cxx:1195
 TH3.cxx:1196
 TH3.cxx:1197
 TH3.cxx:1198
 TH3.cxx:1199
 TH3.cxx:1200
 TH3.cxx:1201
 TH3.cxx:1202
 TH3.cxx:1203
 TH3.cxx:1204
 TH3.cxx:1205
 TH3.cxx:1206
 TH3.cxx:1207
 TH3.cxx:1208
 TH3.cxx:1209
 TH3.cxx:1210
 TH3.cxx:1211
 TH3.cxx:1212
 TH3.cxx:1213
 TH3.cxx:1214
 TH3.cxx:1215
 TH3.cxx:1216
 TH3.cxx:1217
 TH3.cxx:1218
 TH3.cxx:1219
 TH3.cxx:1220
 TH3.cxx:1221
 TH3.cxx:1222
 TH3.cxx:1223
 TH3.cxx:1224
 TH3.cxx:1225
 TH3.cxx:1226
 TH3.cxx:1227
 TH3.cxx:1228
 TH3.cxx:1229
 TH3.cxx:1230
 TH3.cxx:1231
 TH3.cxx:1232
 TH3.cxx:1233
 TH3.cxx:1234
 TH3.cxx:1235
 TH3.cxx:1236
 TH3.cxx:1237
 TH3.cxx:1238
 TH3.cxx:1239
 TH3.cxx:1240
 TH3.cxx:1241
 TH3.cxx:1242
 TH3.cxx:1243
 TH3.cxx:1244
 TH3.cxx:1245
 TH3.cxx:1246
 TH3.cxx:1247
 TH3.cxx:1248
 TH3.cxx:1249
 TH3.cxx:1250
 TH3.cxx:1251
 TH3.cxx:1252
 TH3.cxx:1253
 TH3.cxx:1254
 TH3.cxx:1255
 TH3.cxx:1256
 TH3.cxx:1257
 TH3.cxx:1258
 TH3.cxx:1259
 TH3.cxx:1260
 TH3.cxx:1261
 TH3.cxx:1262
 TH3.cxx:1263
 TH3.cxx:1264
 TH3.cxx:1265
 TH3.cxx:1266
 TH3.cxx:1267
 TH3.cxx:1268
 TH3.cxx:1269
 TH3.cxx:1270
 TH3.cxx:1271
 TH3.cxx:1272
 TH3.cxx:1273
 TH3.cxx:1274
 TH3.cxx:1275
 TH3.cxx:1276
 TH3.cxx:1277
 TH3.cxx:1278
 TH3.cxx:1279
 TH3.cxx:1280
 TH3.cxx:1281
 TH3.cxx:1282
 TH3.cxx:1283
 TH3.cxx:1284
 TH3.cxx:1285
 TH3.cxx:1286
 TH3.cxx:1287
 TH3.cxx:1288
 TH3.cxx:1289
 TH3.cxx:1290
 TH3.cxx:1291
 TH3.cxx:1292
 TH3.cxx:1293
 TH3.cxx:1294
 TH3.cxx:1295
 TH3.cxx:1296
 TH3.cxx:1297
 TH3.cxx:1298
 TH3.cxx:1299
 TH3.cxx:1300
 TH3.cxx:1301
 TH3.cxx:1302
 TH3.cxx:1303
 TH3.cxx:1304
 TH3.cxx:1305
 TH3.cxx:1306
 TH3.cxx:1307
 TH3.cxx:1308
 TH3.cxx:1309
 TH3.cxx:1310
 TH3.cxx:1311
 TH3.cxx:1312
 TH3.cxx:1313
 TH3.cxx:1314
 TH3.cxx:1315
 TH3.cxx:1316
 TH3.cxx:1317
 TH3.cxx:1318
 TH3.cxx:1319
 TH3.cxx:1320
 TH3.cxx:1321
 TH3.cxx:1322
 TH3.cxx:1323
 TH3.cxx:1324
 TH3.cxx:1325
&nbs