TH3.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TH3.cxx 35921 2010-09-30 14:38:54Z brun $
00002 // Author: Rene Brun   27/10/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TROOT.h"
00013 #include "TClass.h"
00014 #include "THashList.h"
00015 #include "TH3.h"
00016 #include "TProfile2D.h"
00017 #include "TH2.h"
00018 #include "TF1.h"
00019 #include "TVirtualPad.h"
00020 #include "TVirtualHistPainter.h"
00021 #include "THLimitsFinder.h"
00022 #include "TRandom.h"
00023 #include "TError.h"
00024 #include "TMath.h"
00025 #include "TObjString.h"
00026 
00027 ClassImp(TH3)
00028 
00029 //______________________________________________________________________________
00030 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00031 //*-*
00032 //*-*  The 3-D histogram classes derived from the 1-D histogram classes.
00033 //*-*  all operations are supported (fill, fit).
00034 //*-*  Drawing is currently restricted to one single option.
00035 //*-*  A cloud of points is drawn. The number of points is proportional to
00036 //*-*  cell content.
00037 //*-*
00038 //
00039 //  TH3C a 3-D histogram with one byte per cell (char)
00040 //  TH3S a 3-D histogram with two bytes per cell (short integer)
00041 //  TH3I a 3-D histogram with four bytes per cell (32 bits integer)
00042 //  TH3F a 3-D histogram with four bytes per cell (float)
00043 //  TH3D a 3-D histogram with eight bytes per cell (double)
00044 //
00045 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00046 
00047 //______________________________________________________________________________
00048 TH3::TH3()
00049 {
00050    // Default constructor.
00051    fDimension   = 3;
00052    fTsumwy      = fTsumwy2 = fTsumwxy = 0;
00053    fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
00054 }
00055 
00056 //______________________________________________________________________________
00057 TH3::TH3(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
00058                                      ,Int_t nbinsy,Double_t ylow,Double_t yup
00059                                      ,Int_t nbinsz,Double_t zlow,Double_t zup)
00060      :TH1(name,title,nbinsx,xlow,xup),
00061       TAtt3D()
00062 {
00063 //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
00064 //*-*              ==================================================
00065 
00066    fDimension   = 3;
00067    if (nbinsy <= 0) nbinsy = 1;
00068    if (nbinsz <= 0) nbinsz = 1;
00069    fYaxis.Set(nbinsy,ylow,yup);
00070    fZaxis.Set(nbinsz,zlow,zup);
00071    fNcells      = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
00072    fTsumwy      = fTsumwy2 = fTsumwxy = 0;
00073    fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
00074 }
00075 
00076 //______________________________________________________________________________
00077 TH3::TH3(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
00078                                            ,Int_t nbinsy,const Float_t *ybins
00079                                            ,Int_t nbinsz,const Float_t *zbins)
00080      :TH1(name,title,nbinsx,xbins),
00081       TAtt3D()
00082 {
00083 //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
00084 //*-*            =======================================================
00085    fDimension   = 3;
00086    if (nbinsy <= 0) nbinsy = 1;
00087    if (nbinsz <= 0) nbinsz = 1;
00088    if (ybins) fYaxis.Set(nbinsy,ybins);
00089    else       fYaxis.Set(nbinsy,0,1);
00090    if (zbins) fZaxis.Set(nbinsz,zbins);
00091    else       fZaxis.Set(nbinsz,0,1);
00092    fNcells      = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
00093    fTsumwy      = fTsumwy2 = fTsumwxy = 0;
00094    fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
00095 }
00096 
00097 //______________________________________________________________________________
00098 TH3::TH3(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
00099                                            ,Int_t nbinsy,const Double_t *ybins
00100                                            ,Int_t nbinsz,const Double_t *zbins)
00101      :TH1(name,title,nbinsx,xbins),
00102       TAtt3D()
00103 {
00104 //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
00105 //*-*            =======================================================
00106    fDimension   = 3;
00107    if (nbinsy <= 0) nbinsy = 1;
00108    if (nbinsz <= 0) nbinsz = 1;
00109    if (ybins) fYaxis.Set(nbinsy,ybins);
00110    else       fYaxis.Set(nbinsy,0,1);
00111    if (zbins) fZaxis.Set(nbinsz,zbins);
00112    else       fZaxis.Set(nbinsz,0,1);
00113    fNcells      = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
00114    fTsumwy      = fTsumwy2 = fTsumwxy = 0;
00115    fTsumwz      = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
00116 }
00117 
00118 //______________________________________________________________________________
00119 TH3::TH3(const TH3 &h) : TH1(), TAtt3D()
00120 {
00121    // Copy constructor.
00122    // The list of functions is not copied. (Use Clone if needed)
00123 
00124    ((TH3&)h).Copy(*this);
00125 }
00126 
00127 //______________________________________________________________________________
00128 TH3::~TH3()
00129 {
00130    // Destructor.
00131 }
00132 
00133 //______________________________________________________________________________
00134 void TH3::Copy(TObject &obj) const
00135 {
00136    // Copy.
00137 
00138    TH1::Copy(obj);
00139    ((TH3&)obj).fTsumwy      = fTsumwy;
00140    ((TH3&)obj).fTsumwy2     = fTsumwy2;
00141    ((TH3&)obj).fTsumwxy     = fTsumwxy;
00142    ((TH3&)obj).fTsumwz      = fTsumwz;
00143    ((TH3&)obj).fTsumwz2     = fTsumwz2;
00144    ((TH3&)obj).fTsumwxz     = fTsumwxz;
00145    ((TH3&)obj).fTsumwyz     = fTsumwyz;
00146 }
00147 
00148 //______________________________________________________________________________
00149 Int_t TH3::BufferEmpty(Int_t action)
00150 {
00151    // Fill histogram with all entries in the buffer.
00152    // action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
00153    // action =  0 histogram is filled from the buffer
00154    // action =  1 histogram is filled and buffer is deleted
00155    //             The buffer is automatically deleted when the number of entries
00156    //             in the buffer is greater than the number of entries in the histogram
00157 
00158    // do we need to compute the bin size?
00159    if (!fBuffer) return 0;
00160    Int_t nbentries = (Int_t)fBuffer[0];
00161    if (!nbentries) return 0;
00162    Double_t *buffer = fBuffer;
00163    if (nbentries < 0) {
00164       if (action == 0) return 0;
00165       nbentries  = -nbentries;
00166       fBuffer=0;
00167       Reset();
00168       fBuffer = buffer;
00169    }
00170    if (TestBit(kCanRebin) || fXaxis.GetXmax() <= fXaxis.GetXmin() ||
00171       fYaxis.GetXmax() <= fYaxis.GetXmin() ||
00172       fZaxis.GetXmax() <= fZaxis.GetXmin()) {
00173          //find min, max of entries in buffer
00174          Double_t xmin = fBuffer[2];
00175          Double_t xmax = xmin;
00176          Double_t ymin = fBuffer[3];
00177          Double_t ymax = ymin;
00178          Double_t zmin = fBuffer[4];
00179          Double_t zmax = zmin;
00180          for (Int_t i=1;i<nbentries;i++) {
00181             Double_t x = fBuffer[4*i+2];
00182             if (x < xmin) xmin = x;
00183             if (x > xmax) xmax = x;
00184             Double_t y = fBuffer[4*i+3];
00185             if (y < ymin) ymin = y;
00186             if (y > ymax) ymax = y;
00187             Double_t z = fBuffer[4*i+4];
00188             if (z < zmin) zmin = z;
00189             if (z > zmax) zmax = z;
00190          }
00191          if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin() || fZaxis.GetXmax() <= fZaxis.GetXmin()) {
00192             THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax,zmin,zmax);
00193          } else {
00194             fBuffer = 0;
00195             Int_t keep = fBufferSize; fBufferSize = 0;
00196             if (xmin <  fXaxis.GetXmin()) RebinAxis(xmin,&fXaxis);
00197             if (xmax >= fXaxis.GetXmax()) RebinAxis(xmax,&fXaxis);
00198             if (ymin <  fYaxis.GetXmin()) RebinAxis(ymin,&fYaxis);
00199             if (ymax >= fYaxis.GetXmax()) RebinAxis(ymax,&fYaxis);
00200             if (zmin <  fZaxis.GetXmin()) RebinAxis(zmin,&fZaxis);
00201             if (zmax >= fZaxis.GetXmax()) RebinAxis(zmax,&fZaxis);
00202             fBuffer = buffer;
00203             fBufferSize = keep;
00204          }
00205    }
00206    fBuffer = 0;
00207 
00208    for (Int_t i=0;i<nbentries;i++) {
00209       Fill(buffer[4*i+2],buffer[4*i+3],buffer[4*i+4],buffer[4*i+1]);
00210    }
00211    fBuffer = buffer;
00212 
00213    if (action > 0) { delete [] fBuffer; fBuffer = 0; fBufferSize = 0;}
00214    else {
00215       if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
00216       else                              fBuffer[0] = 0;
00217    }
00218    return nbentries;
00219 }
00220 
00221 //______________________________________________________________________________
00222 Int_t TH3::BufferFill(Double_t x, Double_t y, Double_t z, Double_t w)
00223 {
00224    // accumulate arguments in buffer. When buffer is full, empty the buffer
00225    // fBuffer[0] = number of entries in buffer
00226    // fBuffer[1] = w of first entry
00227    // fBuffer[2] = x of first entry
00228    // fBuffer[3] = y of first entry
00229    // fBuffer[4] = z of first entry
00230 
00231    if (!fBuffer) return -3;
00232    Int_t nbentries = (Int_t)fBuffer[0];
00233    if (nbentries < 0) {
00234       nbentries  = -nbentries;
00235       fBuffer[0] =  nbentries;
00236       if (fEntries > 0) {
00237          Double_t *buffer = fBuffer; fBuffer=0;
00238          Reset();
00239          fBuffer = buffer;
00240       }
00241    }
00242    if (4*nbentries+4 >= fBufferSize) {
00243       BufferEmpty(1);
00244       return Fill(x,y,z,w);
00245    }
00246    fBuffer[4*nbentries+1] = w;
00247    fBuffer[4*nbentries+2] = x;
00248    fBuffer[4*nbentries+3] = y;
00249    fBuffer[4*nbentries+4] = z;
00250    fBuffer[0] += 1;
00251    return -3;
00252 }
00253 
00254 //______________________________________________________________________________
00255 Int_t TH3::Fill(Double_t x, Double_t y, Double_t z)
00256 {
00257    //*-*-*-*-*-*-*-*-*-*-*Increment cell defined by x,y,z by 1 *-*-*-*-*
00258    //*-*                  ====================================
00259    //*-*
00260    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00261 
00262    if (fBuffer) return BufferFill(x,y,z,1);
00263 
00264    Int_t binx, biny, binz, bin;
00265    fEntries++;
00266    binx = fXaxis.FindBin(x);
00267    biny = fYaxis.FindBin(y);
00268    binz = fZaxis.FindBin(z);
00269    if (binx <0 || biny <0 || binz<0) return -1;
00270    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00271    AddBinContent(bin);
00272    if (fSumw2.fN) ++fSumw2.fArray[bin];
00273    if (binx == 0 || binx > fXaxis.GetNbins()) {
00274       if (!fgStatOverflows) return -1;
00275    }
00276 
00277    if (biny == 0 || biny > fYaxis.GetNbins()) {
00278       if (!fgStatOverflows) return -1;
00279    }
00280    if (binz == 0 || binz > fZaxis.GetNbins()) {
00281       if (!fgStatOverflows) return -1;
00282    }
00283    ++fTsumw;
00284    ++fTsumw2;
00285    fTsumwx  += x;
00286    fTsumwx2 += x*x;
00287    fTsumwy  += y;
00288    fTsumwy2 += y*y;
00289    fTsumwxy += x*y;
00290    fTsumwz  += z;
00291    fTsumwz2 += z*z;
00292    fTsumwxz += x*z;
00293    fTsumwyz += y*z;
00294    return bin;
00295 }
00296 
00297 //______________________________________________________________________________
00298 Int_t TH3::Fill(Double_t x, Double_t y, Double_t z, Double_t w)
00299 {
00300    //*-*-*-*-*-*-*-*-*-*-*Increment cell defined by x,y,z by a weight w*-*-*-*-*
00301    //*-*                  =============================================
00302    //*-*
00303    //*-* If the storage of the sum of squares of weights has been triggered,
00304    //*-* via the function Sumw2, then the sum of the squares of weights is incremented
00305    //*-* by w^2 in the cell corresponding to x,y,z.
00306    //*-*
00307    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
00308 
00309    if (fBuffer) return BufferFill(x,y,z,w);
00310 
00311    Int_t binx, biny, binz, bin;
00312    fEntries++;
00313    binx = fXaxis.FindBin(x);
00314    biny = fYaxis.FindBin(y);
00315    binz = fZaxis.FindBin(z);
00316    if (binx <0 || biny <0 || binz<0) return -1;
00317    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00318    AddBinContent(bin,w);
00319    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00320    if (binx == 0 || binx > fXaxis.GetNbins()) {
00321       if (!fgStatOverflows) return -1;
00322    }
00323    if (biny == 0 || biny > fYaxis.GetNbins()) {
00324       if (!fgStatOverflows) return -1;
00325    }
00326    if (binz == 0 || binz > fZaxis.GetNbins()) {
00327       if (!fgStatOverflows) return -1;
00328    }
00329    fTsumw   += w;
00330    fTsumw2  += w*w;
00331    fTsumwx  += w*x;
00332    fTsumwx2 += w*x*x;
00333    fTsumwy  += w*y;
00334    fTsumwy2 += w*y*y;
00335    fTsumwxy += w*x*y;
00336    fTsumwz  += w*z;
00337    fTsumwz2 += w*z*z;
00338    fTsumwxz += w*x*z;
00339    fTsumwyz += w*y*z;
00340    return bin;
00341 }
00342 
00343 //______________________________________________________________________________
00344 Int_t TH3::Fill(const char *namex, const char *namey, const char *namez, Double_t w)
00345 {
00346    // Increment cell defined by namex,namey,namez by a weight w
00347    //
00348    // If the storage of the sum of squares of weights has been triggered,
00349    // via the function Sumw2, then the sum of the squares of weights is incremented
00350    // by w^2 in the cell corresponding to x,y,z.
00351    //
00352    Int_t binx, biny, binz, bin;
00353    fEntries++;
00354    binx = fXaxis.FindBin(namex);
00355    biny = fYaxis.FindBin(namey);
00356    binz = fZaxis.FindBin(namez);
00357    if (binx <0 || biny <0 || binz<0) return -1;
00358    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00359    AddBinContent(bin,w);
00360    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00361    if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
00362    if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
00363    if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
00364    Double_t x = fXaxis.GetBinCenter(binx);
00365    Double_t y = fYaxis.GetBinCenter(biny);
00366    Double_t z = fZaxis.GetBinCenter(binz);
00367    Double_t v = (w > 0 ? w : -w);
00368    fTsumw   += v;
00369    fTsumw2  += v*v;
00370    fTsumwx  += v*x;
00371    fTsumwx2 += v*x*x;
00372    fTsumwy  += v*y;
00373    fTsumwy2 += v*y*y;
00374    fTsumwxy += v*x*y;
00375    fTsumwz  += v*z;
00376    fTsumwz2 += v*z*z;
00377    fTsumwxz += v*x*z;
00378    fTsumwyz += v*y*z;
00379    return bin;
00380 }
00381 
00382 //______________________________________________________________________________
00383 Int_t TH3::Fill(const char *namex, Double_t y, const char *namez, Double_t w)
00384 {
00385    // Increment cell defined by namex,y,namez by a weight w
00386    //
00387    // If the storage of the sum of squares of weights has been triggered,
00388    // via the function Sumw2, then the sum of the squares of weights is incremented
00389    // by w^2 in the cell corresponding to x,y,z.
00390    //
00391    Int_t binx, biny, binz, bin;
00392    fEntries++;
00393    binx = fXaxis.FindBin(namex);
00394    biny = fYaxis.FindBin(y);
00395    binz = fZaxis.FindBin(namez);
00396    if (binx <0 || biny <0 || binz<0) return -1;
00397    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00398    AddBinContent(bin,w);
00399    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00400    if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
00401    if (biny == 0 || biny > fYaxis.GetNbins()) {
00402       if (!fgStatOverflows) return -1;
00403    }
00404    if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
00405    Double_t x = fXaxis.GetBinCenter(binx);
00406    Double_t z = fZaxis.GetBinCenter(binz);
00407    Double_t v = (w > 0 ? w : -w);
00408    fTsumw   += v;
00409    fTsumw2  += v*v;
00410    fTsumwx  += v*x;
00411    fTsumwx2 += v*x*x;
00412    fTsumwy  += v*y;
00413    fTsumwy2 += v*y*y;
00414    fTsumwxy += v*x*y;
00415    fTsumwz  += v*z;
00416    fTsumwz2 += v*z*z;
00417    fTsumwxz += v*x*z;
00418    fTsumwyz += v*y*z;
00419    return bin;
00420 }
00421 
00422 //______________________________________________________________________________
00423 Int_t TH3::Fill(const char *namex, const char *namey, Double_t z, Double_t w)
00424 {
00425    // Increment cell defined by namex,namey,z by a weight w
00426    //
00427    // If the storage of the sum of squares of weights has been triggered,
00428    // via the function Sumw2, then the sum of the squares of weights is incremented
00429    // by w^2 in the cell corresponding to x,y,z.
00430    //
00431    Int_t binx, biny, binz, bin;
00432    fEntries++;
00433    binx = fXaxis.FindBin(namex);
00434    biny = fYaxis.FindBin(namey);
00435    binz = fZaxis.FindBin(z);
00436    if (binx <0 || biny <0 || binz<0) return -1;
00437    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00438    AddBinContent(bin,w);
00439    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00440    if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
00441    if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
00442    if (binz == 0 || binz > fZaxis.GetNbins()) {
00443       if (!fgStatOverflows) return -1;
00444    }
00445    Double_t x = fXaxis.GetBinCenter(binx);
00446    Double_t y = fYaxis.GetBinCenter(biny);
00447    Double_t v = (w > 0 ? w : -w);
00448    fTsumw   += v;
00449    fTsumw2  += v*v;
00450    fTsumwx  += v*x;
00451    fTsumwx2 += v*x*x;
00452    fTsumwy  += v*y;
00453    fTsumwy2 += v*y*y;
00454    fTsumwxy += v*x*y;
00455    fTsumwz  += v*z;
00456    fTsumwz2 += v*z*z;
00457    fTsumwxz += v*x*z;
00458    fTsumwyz += v*y*z;
00459    return bin;
00460 }
00461 
00462 //______________________________________________________________________________
00463 Int_t TH3::Fill(Double_t x, const char *namey, const char *namez, Double_t w)
00464 {
00465    // Increment cell defined by x,namey,namezz by a weight w
00466    //
00467    // If the storage of the sum of squares of weights has been triggered,
00468    // via the function Sumw2, then the sum of the squares of weights is incremented
00469    // by w^2 in the cell corresponding to x,y,z.
00470    //
00471    Int_t binx, biny, binz, bin;
00472    fEntries++;
00473    binx = fXaxis.FindBin(x);
00474    biny = fYaxis.FindBin(namey);
00475    binz = fZaxis.FindBin(namez);
00476    if (binx <0 || biny <0 || binz<0) return -1;
00477    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00478    AddBinContent(bin,w);
00479    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00480    if (binx == 0 || binx > fXaxis.GetNbins()) {
00481       if (!fgStatOverflows) return -1;
00482    }
00483    if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
00484    if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
00485    Double_t y = fYaxis.GetBinCenter(biny);
00486    Double_t z = fZaxis.GetBinCenter(binz);
00487    Double_t v = (w > 0 ? w : -w);
00488    fTsumw   += v;
00489    fTsumw2  += v*v;
00490    fTsumwx  += v*x;
00491    fTsumwx2 += v*x*x;
00492    fTsumwy  += v*y;
00493    fTsumwy2 += v*y*y;
00494    fTsumwxy += v*x*y;
00495    fTsumwz  += v*z;
00496    fTsumwz2 += v*z*z;
00497    fTsumwxz += v*x*z;
00498    fTsumwyz += v*y*z;
00499    return bin;
00500 }
00501 
00502 //______________________________________________________________________________
00503 Int_t TH3::Fill(Double_t x, const char *namey, Double_t z, Double_t w)
00504 {
00505    // Increment cell defined by x,namey,z by a weight w
00506    //
00507    // If the storage of the sum of squares of weights has been triggered,
00508    // via the function Sumw2, then the sum of the squares of weights is incremented
00509    // by w^2 in the cell corresponding to x,y,z.
00510    //
00511    Int_t binx, biny, binz, bin;
00512    fEntries++;
00513    binx = fXaxis.FindBin(x);
00514    biny = fYaxis.FindBin(namey);
00515    binz = fZaxis.FindBin(z);
00516    if (binx <0 || biny <0 || binz<0) return -1;
00517    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00518    AddBinContent(bin,w);
00519    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00520    if (binx == 0 || binx > fXaxis.GetNbins()) {
00521       if (!fgStatOverflows) return -1;
00522    }
00523    if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
00524    if (binz == 0 || binz > fZaxis.GetNbins()) {
00525       if (!fgStatOverflows) return -1;
00526    }
00527    Double_t y = fYaxis.GetBinCenter(biny);
00528    Double_t v = (w > 0 ? w : -w);
00529    fTsumw   += v;
00530    fTsumw2  += v*v;
00531    fTsumwx  += v*x;
00532    fTsumwx2 += v*x*x;
00533    fTsumwy  += v*y;
00534    fTsumwy2 += v*y*y;
00535    fTsumwxy += v*x*y;
00536    fTsumwz  += v*z;
00537    fTsumwz2 += v*z*z;
00538    fTsumwxz += v*x*z;
00539    fTsumwyz += v*y*z;
00540    return bin;
00541 }
00542 
00543 //______________________________________________________________________________
00544 Int_t TH3::Fill(Double_t x, Double_t y, const char *namez, Double_t w)
00545 {
00546    // Increment cell defined by x,y,namez by a weight w
00547    //
00548    // If the storage of the sum of squares of weights has been triggered,
00549    // via the function Sumw2, then the sum of the squares of weights is incremented
00550    // by w^2 in the cell corresponding to x,y,z.
00551    //
00552    Int_t binx, biny, binz, bin;
00553    fEntries++;
00554    binx = fXaxis.FindBin(x);
00555    biny = fYaxis.FindBin(y);
00556    binz = fZaxis.FindBin(namez);
00557    if (binx <0 || biny <0 || binz<0) return -1;
00558    bin  =  binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
00559    AddBinContent(bin,w);
00560    if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
00561    if (binx == 0 || binx > fXaxis.GetNbins()) {
00562       if (!fgStatOverflows) return -1;
00563    }
00564    if (biny == 0 || biny > fYaxis.GetNbins()) {
00565       if (!fgStatOverflows) return -1;
00566    }
00567    if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
00568    Double_t z = fZaxis.GetBinCenter(binz);
00569    Double_t v = (w > 0 ? w : -w);
00570    fTsumw   += v;
00571    fTsumw2  += v*v;
00572    fTsumwx  += v*x;
00573    fTsumwx2 += v*x*x;
00574    fTsumwy  += v*y;
00575    fTsumwy2 += v*y*y;
00576    fTsumwxy += v*x*y;
00577    fTsumwz  += v*z;
00578    fTsumwz2 += v*z*z;
00579    fTsumwxz += v*x*z;
00580    fTsumwyz += v*y*z;
00581    return bin;
00582 }
00583 
00584 //______________________________________________________________________________
00585 void TH3::FillRandom(const char *fname, Int_t ntimes)
00586 {
00587    //*-*-*-*-*-*-*Fill histogram following distribution in function fname*-*-*-*
00588    //*-*          =======================================================
00589    //*-*
00590    //*-*   The distribution contained in the function fname (TF1) is integrated
00591    //*-*   over the channel contents.
00592    //*-*   It is normalized to 1.
00593    //*-*   Getting one random number implies:
00594    //*-*     - Generating a random number between 0 and 1 (say r1)
00595    //*-*     - Look in which bin in the normalized integral r1 corresponds to
00596    //*-*     - Fill histogram channel
00597    //*-*   ntimes random numbers are generated
00598    //*-*
00599    //*-*  One can also call TF1::GetRandom to get a random variate from a function.
00600    //*-*
00601    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*
00602 
00603    Int_t bin, binx, biny, binz, ibin, loop;
00604    Double_t r1, x, y,z, xv[3];
00605    //*-*- Search for fname in the list of ROOT defined functions
00606    TF1 *f1 = (TF1*)gROOT->GetFunction(fname);
00607    if (!f1) { Error("FillRandom", "Unknown function: %s",fname); return; }
00608 
00609    //*-*- Allocate temporary space to store the integral and compute integral
00610    Int_t nbinsx = GetNbinsX();
00611    Int_t nbinsy = GetNbinsY();
00612    Int_t nbinsz = GetNbinsZ();
00613    Int_t nxy    = nbinsx*nbinsy;
00614    Int_t nbins  = nxy*nbinsz;
00615 
00616    Double_t *integral = new Double_t[nbins+1];
00617    ibin = 0;
00618    integral[ibin] = 0;
00619    for (binz=1;binz<=nbinsz;binz++) {
00620       xv[2] = fZaxis.GetBinCenter(binz);
00621       for (biny=1;biny<=nbinsy;biny++) {
00622          xv[1] = fYaxis.GetBinCenter(biny);
00623          for (binx=1;binx<=nbinsx;binx++) {
00624             xv[0] = fXaxis.GetBinCenter(binx);
00625             ibin++;
00626             integral[ibin] = integral[ibin-1] + f1->Eval(xv[0],xv[1],xv[2]);
00627          }
00628       }
00629    }
00630 
00631    //*-*- Normalize integral to 1
00632    if (integral[nbins] == 0 ) {
00633       delete [] integral;
00634       Error("FillRandom", "Integral = zero"); return;
00635    }
00636    for (bin=1;bin<=nbins;bin++)  integral[bin] /= integral[nbins];
00637 
00638    //*-*--------------Start main loop ntimes
00639    if (fDimension < 2) nbinsy = -1;
00640    if (fDimension < 3) nbinsz = -1;
00641    for (loop=0;loop<ntimes;loop++) {
00642       r1 = gRandom->Rndm(loop);
00643       ibin = TMath::BinarySearch(nbins,&integral[0],r1);
00644       binz = ibin/nxy;
00645       biny = (ibin - nxy*binz)/nbinsx;
00646       binx = 1 + ibin - nbinsx*(biny + nbinsy*binz);
00647       if (nbinsz) binz++;
00648       if (nbinsy) biny++;
00649       x    = fXaxis.GetBinCenter(binx);
00650       y    = fYaxis.GetBinCenter(biny);
00651       z    = fZaxis.GetBinCenter(binz);
00652       Fill(x,y,z, 1.);
00653    }
00654    delete [] integral;
00655 }
00656 
00657 //______________________________________________________________________________
00658 void TH3::FillRandom(TH1 *h, Int_t ntimes)
00659 {
00660    //*-*-*-*-*-*-*Fill histogram following distribution in histogram h*-*-*-*
00661    //*-*          ====================================================
00662    //*-*
00663    //*-*   The distribution contained in the histogram h (TH3) is integrated
00664    //*-*   over the channel contents.
00665    //*-*   It is normalized to 1.
00666    //*-*   Getting one random number implies:
00667    //*-*     - Generating a random number between 0 and 1 (say r1)
00668    //*-*     - Look in which bin in the normalized integral r1 corresponds to
00669    //*-*     - Fill histogram channel
00670    //*-*   ntimes random numbers are generated
00671    //*-*
00672    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*
00673 
00674    if (!h) { Error("FillRandom", "Null histogram"); return; }
00675    if (fDimension != h->GetDimension()) {
00676       Error("FillRandom", "Histograms with different dimensions"); return;
00677    }
00678 
00679    if (h->ComputeIntegral() == 0) return;
00680 
00681    TH3 *h3 = (TH3*)h;
00682    Int_t loop;
00683    Double_t x,y,z;
00684    for (loop=0;loop<ntimes;loop++) {
00685       h3->GetRandom3(x,y,z);
00686       Fill(x,y,z,1.);
00687    }
00688 }
00689 
00690 
00691 //______________________________________________________________________________
00692 Int_t TH3::FindFirstBinAbove(Double_t threshold, Int_t axis) const
00693 {
00694    //find first bin with content > threshold for axis (1=x, 2=y, 3=z)
00695    //if no bins with content > threshold is found the function returns -1.
00696    
00697    if (axis < 1 || axis > 3) {
00698       Warning("FindFirstBinAbove","Invalid axis number : %d, axis x assumed\n",axis);
00699       axis = 1;
00700    }
00701    Int_t nbinsx = fXaxis.GetNbins();
00702    Int_t nbinsy = fYaxis.GetNbins();
00703    Int_t nbinsz = fZaxis.GetNbins();
00704    Int_t binx, biny, binz;
00705    if (axis == 1) {
00706       for (binx=1;binx<=nbinsx;binx++) {
00707          for (biny=1;biny<=nbinsy;biny++) {
00708             for (binz=1;binz<=nbinsz;binz++) {
00709                if (GetBinContent(binx,biny,binz) > threshold) return binx;
00710             }
00711          }
00712       }
00713    } else if (axis == 2) {
00714       for (biny=1;biny<=nbinsy;biny++) {
00715          for (binx=1;binx<=nbinsx;binx++) {
00716             for (binz=1;binz<=nbinsz;binz++) {
00717                if (GetBinContent(binx,biny,binz) > threshold) return biny;
00718             }
00719          }
00720       }
00721    } else {
00722       for (binz=1;binz<=nbinsz;binz++) {
00723          for (binx=1;binx<=nbinsx;binx++) {
00724             for (biny=1;biny<=nbinsy;biny++) {
00725                if (GetBinContent(binx,biny,binz) > threshold) return binz;
00726             }
00727          }
00728       }
00729    }
00730    return -1;
00731 }
00732 
00733 
00734 //______________________________________________________________________________
00735 Int_t TH3::FindLastBinAbove(Double_t threshold, Int_t axis) const
00736 {
00737    //find last bin with content > threshold for axis (1=x, 2=y, 3=z)
00738    //if no bins with content > threshold is found the function returns -1.
00739    
00740    if (axis < 1 || axis > 3) {
00741       Warning("FindLastBinAbove","Invalid axis number : %d, axis x assumed\n",axis);
00742       axis = 1;
00743    }
00744    Int_t nbinsx = fXaxis.GetNbins();
00745    Int_t nbinsy = fYaxis.GetNbins();
00746    Int_t nbinsz = fZaxis.GetNbins();
00747    Int_t binx, biny, binz;
00748    if (axis == 1) {
00749       for (binx=nbinsx;binx>=1;binx--) {
00750          for (biny=1;biny<=nbinsy;biny++) {
00751             for (binz=1;binz<=nbinsz;binz++) {
00752                if (GetBinContent(binx,biny,binz) > threshold) return binx;
00753             }
00754          }
00755       }
00756    } else if (axis == 2) {
00757       for (biny=nbinsy;biny>=1;biny--) {
00758          for (binx=1;binx<=nbinsx;binx++) {
00759             for (binz=1;binz<=nbinsz;binz++) {
00760                if (GetBinContent(binx,biny,binz) > threshold) return biny;
00761             }
00762          }
00763       }
00764    } else {
00765       for (binz=nbinsz;binz>=1;binz--) {
00766          for (binx=1;binx<=nbinsx;binx++) {
00767             for (biny=1;biny<=nbinsy;biny++) {
00768                if (GetBinContent(binx,biny,binz) > threshold) return binz;
00769             }
00770          }
00771       }
00772    }
00773    return -1;
00774 }
00775 
00776 
00777 //______________________________________________________________________________
00778 void TH3::FitSlicesZ(TF1 *f1, Int_t binminx, Int_t binmaxx, Int_t binminy, Int_t binmaxy, Int_t cut, Option_t *option)
00779 {
00780    // Project slices along Z in case of a 3-D histogram, then fit each slice
00781    // with function f1 and make a 2-d histogram for each fit parameter
00782    // Only cells in the bin range [binminx,binmaxx] and [binminy,binmaxy] are considered.
00783    // if f1=0, a gaussian is assumed
00784    // Before invoking this function, one can set a subrange to be fitted along Z
00785    // via f1->SetRange(zmin,zmax)
00786    // The argument option (default="QNR") can be used to change the fit options.
00787    //     "Q" means Quiet mode
00788    //     "N" means do not show the result of the fit
00789    //     "R" means fit the function in the specified function range
00790    //
00791    // Note that the generated histograms are added to the list of objects
00792    // in the current directory. It is the user's responsability to delete
00793    // these histograms.
00794    //
00795    //  Example: Assume a 3-d histogram h3
00796    //   Root > h3->FitSlicesZ(); produces 4 TH2D histograms
00797    //          with h3_0 containing parameter 0(Constant) for a Gaus fit
00798    //                    of each cell in X,Y projected along Z
00799    //          with h3_1 containing parameter 1(Mean) for a gaus fit
00800    //          with h3_2 containing parameter 2(RMS)  for a gaus fit
00801    //          with h3_chi2 containing the chisquare/number of degrees of freedom for a gaus fit
00802    //
00803    //   Root > h3->Fit(0,15,22,0,0,10);
00804    //          same as above, but only for bins 15 to 22 along X
00805    //          and only for cells in X,Y for which the corresponding projection
00806    //          along Z has more than cut bins filled.
00807    //
00808    //  NOTE: To access the generated histograms in the current directory, do eg:
00809    //     TH2D *h3_1 = (TH2D*)gDirectory->Get("h3_1");
00810 
00811    Int_t nbinsx  = fXaxis.GetNbins();
00812    Int_t nbinsy  = fYaxis.GetNbins();
00813    Int_t nbinsz  = fZaxis.GetNbins();
00814    if (binminx < 1) binminx = 1;
00815    if (binmaxx > nbinsx) binmaxx = nbinsx;
00816    if (binmaxx < binminx) {binminx = 1; binmaxx = nbinsx;}
00817    if (binminy < 1) binminy = 1;
00818    if (binmaxy > nbinsy) binmaxy = nbinsy;
00819    if (binmaxy < binminy) {binminy = 1; binmaxy = nbinsy;}
00820 
00821    //default is to fit with a gaussian
00822    if (f1 == 0) {
00823       f1 = (TF1*)gROOT->GetFunction("gaus");
00824       if (f1 == 0) f1 = new TF1("gaus","gaus",fZaxis.GetXmin(),fZaxis.GetXmax());
00825       else         f1->SetRange(fZaxis.GetXmin(),fZaxis.GetXmax());
00826    }
00827    const char *fname = f1->GetName();
00828    Int_t npar = f1->GetNpar();
00829    Double_t *parsave = new Double_t[npar];
00830    f1->GetParameters(parsave);
00831 
00832    //Create one 2-d histogram for each function parameter
00833    Int_t ipar;
00834    char name[80], title[80];
00835    TH2D *hlist[25];
00836    const TArrayD *xbins = fXaxis.GetXbins();
00837    const TArrayD *ybins = fYaxis.GetXbins();
00838    for (ipar=0;ipar<npar;ipar++) {
00839       snprintf(name,80,"%s_%d",GetName(),ipar);
00840       snprintf(title,80,"Fitted value of par[%d]=%s",ipar,f1->GetParName(ipar));
00841       if (xbins->fN == 0) {
00842          hlist[ipar] = new TH2D(name, title,
00843                                 nbinsx, fXaxis.GetXmin(), fXaxis.GetXmax(),
00844                                 nbinsy, fYaxis.GetXmin(), fYaxis.GetXmax());
00845       } else {
00846          hlist[ipar] = new TH2D(name, title,
00847                                 nbinsx, xbins->fArray,
00848                                 nbinsy, ybins->fArray);
00849       }
00850       hlist[ipar]->GetXaxis()->SetTitle(fXaxis.GetTitle());
00851       hlist[ipar]->GetYaxis()->SetTitle(fYaxis.GetTitle());
00852    }
00853    snprintf(name,80,"%s_chi2",GetName());
00854    TH2D *hchi2 = new TH2D(name,"chisquare", nbinsx, fXaxis.GetXmin(), fXaxis.GetXmax()
00855       , nbinsy, fYaxis.GetXmin(), fYaxis.GetXmax());
00856 
00857    //Loop on all cells in X,Y generate a projection along Z
00858    TH1D *hpz = new TH1D("R_temp","_temp",nbinsz, fZaxis.GetXmin(), fZaxis.GetXmax());
00859    Int_t bin,binx,biny,binz;
00860    for (biny=binminy;biny<=binmaxy;biny++) {
00861       Float_t y = fYaxis.GetBinCenter(biny);
00862       for (binx=binminx;binx<=binmaxx;binx++) {
00863          Float_t x = fXaxis.GetBinCenter(binx);
00864          hpz->Reset();
00865          Int_t nfill = 0;
00866          for (binz=1;binz<=nbinsz;binz++) {
00867             bin = GetBin(binx,biny,binz);
00868             Float_t w = GetBinContent(bin);
00869             if (w == 0) continue;
00870             hpz->Fill(fZaxis.GetBinCenter(binz),w);
00871             hpz->SetBinError(binz,GetBinError(bin));
00872             nfill++;
00873          }
00874          if (nfill < cut) continue;
00875          f1->SetParameters(parsave);
00876          hpz->Fit(fname,option);
00877          Int_t npfits = f1->GetNumberFitPoints();
00878          if (npfits > npar && npfits >= cut) {
00879             for (ipar=0;ipar<npar;ipar++) {
00880                hlist[ipar]->Fill(x,y,f1->GetParameter(ipar));
00881                hlist[ipar]->SetCellError(binx,biny,f1->GetParError(ipar));
00882             }
00883             hchi2->Fill(x,y,f1->GetChisquare()/(npfits-npar));
00884          }
00885       }
00886    }
00887    delete [] parsave;
00888    delete hpz;
00889 }
00890 
00891 //______________________________________________________________________________
00892 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
00893 {
00894    // compute first cell (binx,biny,binz) in the range [firstx,lastx](firsty,lasty][firstz,lastz] for which
00895    // diff = abs(cell_content-c) <= maxdiff
00896    // In case several cells in the specified range with diff=0 are found
00897    // the first cell found is returned in binx,biny,binz.
00898    // In case several cells in the specified range satisfy diff <=maxdiff
00899    // the cell with the smallest difference is returned in binx,biny,binz.
00900    // In all cases the function returns the smallest difference.
00901    //
00902    // NOTE1: if firstx <= 0, firstx is set to bin 1
00903    //        if (lastx < firstx then firstx is set to the number of bins in X
00904    //        ie if firstx=0 and lastx=0 (default) the search is on all bins in X.
00905    //        if firsty <= 0, firsty is set to bin 1
00906    //        if (lasty < firsty then firsty is set to the number of bins in Y
00907    //        ie if firsty=0 and lasty=0 (default) the search is on all bins in Y.
00908    //        if firstz <= 0, firstz is set to bin 1
00909    //        if (lastz < firstz then firstz is set to the number of bins in Z
00910    //        ie if firstz=0 and lastz=0 (default) the search is on all bins in Z.
00911    // NOTE2: if maxdiff=0 (default), the first cell with content=c is returned.
00912 
00913    if (fDimension != 3) {
00914       binx = 0;
00915       biny = 0;
00916       binz = 0;
00917       Error("GetBinWithContent3","function is only valid for 3-D histograms");
00918       return 0;
00919    }
00920    if (firstx <= 0) firstx = 1;
00921    if (lastx < firstx) lastx = fXaxis.GetNbins();
00922    if (firsty <= 0) firsty = 1;
00923    if (lasty < firsty) lasty = fYaxis.GetNbins();
00924    if (firstz <= 0) firstz = 1;
00925    if (lastz < firstz) lastz = fZaxis.GetNbins();
00926    Int_t binminx = 0, binminy=0, binminz=0;
00927    Double_t diff, curmax = 1.e240;
00928    for (Int_t k=firstz;k<=lastz;k++) {
00929       for (Int_t j=firsty;j<=lasty;j++) {
00930          for (Int_t i=firstx;i<=lastx;i++) {
00931             diff = TMath::Abs(GetBinContent(i,j,k)-c);
00932             if (diff <= 0) {binx = i; biny=j; binz=k; return diff;}
00933             if (diff < curmax && diff <= maxdiff) {curmax = diff, binminx=i; binminy=j;binminz=k;}
00934          }
00935       }
00936    }
00937    binx = binminx;
00938    biny = binminy;
00939    binz = binminz;
00940    return curmax;
00941 }
00942 
00943 //______________________________________________________________________________
00944 Double_t TH3::GetCorrelationFactor(Int_t axis1, Int_t axis2) const
00945 {
00946    //*-*-*-*-*-*-*-*Return correlation factor between axis1 and axis2*-*-*-*-*
00947    //*-*            ====================================================
00948    if (axis1 < 1 || axis2 < 1 || axis1 > 3 || axis2 > 3) {
00949       Error("GetCorrelationFactor","Wrong parameters");
00950       return 0;
00951    }
00952    if (axis1 == axis2) return 1;
00953    Double_t rms1 = GetRMS(axis1);
00954    if (rms1 == 0) return 0;
00955    Double_t rms2 = GetRMS(axis2);
00956    if (rms2 == 0) return 0;
00957    return GetCovariance(axis1,axis2)/rms1/rms2;
00958 }
00959 
00960 //______________________________________________________________________________
00961 Double_t TH3::GetCovariance(Int_t axis1, Int_t axis2) const
00962 {
00963    //*-*-*-*-*-*-*-*Return covariance between axis1 and axis2*-*-*-*-*
00964    //*-*            ====================================================
00965 
00966    if (axis1 < 1 || axis2 < 1 || axis1 > 3 || axis2 > 3) {
00967       Error("GetCovariance","Wrong parameters");
00968       return 0;
00969    }
00970    Double_t stats[kNstat];
00971    GetStats(stats);
00972    Double_t sumw   = stats[0];
00973    Double_t sumw2  = stats[1];
00974    Double_t sumwx  = stats[2];
00975    Double_t sumwx2 = stats[3];
00976    Double_t sumwy  = stats[4];
00977    Double_t sumwy2 = stats[5];
00978    Double_t sumwxy = stats[6];
00979    Double_t sumwz  = stats[7];
00980    Double_t sumwz2 = stats[8];
00981    Double_t sumwxz = stats[9];
00982    Double_t sumwyz = stats[10];
00983 
00984    if (sumw == 0) return 0;
00985    if (axis1 == 1 && axis2 == 1) {
00986       return TMath::Abs(sumwx2/sumw - sumwx*sumwx/sumw2);
00987    }
00988    if (axis1 == 2 && axis2 == 2) {
00989       return TMath::Abs(sumwy2/sumw - sumwy*sumwy/sumw2);
00990    }
00991    if (axis1 == 3 && axis2 == 3) {
00992       return TMath::Abs(sumwz2/sumw - sumwz*sumwz/sumw2);
00993    }
00994    if ((axis1 == 1 && axis2 == 2) || (axis1 == 2 && axis1 == 1)) {
00995       return sumwxy/sumw - sumwx/sumw*sumwy/sumw;
00996    }
00997    if ((axis1 == 1 && axis2 == 3) || (axis1 == 3 && axis2 == 1)) {
00998       return sumwxz/sumw - sumwx/sumw*sumwz/sumw;
00999    }
01000    if ((axis1 == 2 && axis2 == 3) || (axis1 == 3 && axis2 == 2)) {
01001       return sumwyz/sumw - sumwy/sumw*sumwz/sumw;
01002    }
01003    return 0;
01004 }
01005 
01006 
01007 //______________________________________________________________________________
01008 void TH3::GetRandom3(Double_t &x, Double_t &y, Double_t &z)
01009 {
01010    // return 3 random numbers along axis x , y and z distributed according
01011    // the cellcontents of a 3-dim histogram
01012 
01013    Int_t nbinsx = GetNbinsX();
01014    Int_t nbinsy = GetNbinsY();
01015    Int_t nbinsz = GetNbinsZ();
01016    Int_t nxy    = nbinsx*nbinsy;
01017    Int_t nbins  = nxy*nbinsz;
01018    Double_t integral;
01019    if (fIntegral) {
01020       if (fIntegral[nbins+1] != fEntries) integral = ComputeIntegral();
01021    } else {
01022       integral = ComputeIntegral();
01023       if (integral == 0 || fIntegral == 0) return;
01024    }
01025    Double_t r1 = gRandom->Rndm();
01026    Int_t ibin = TMath::BinarySearch(nbins,fIntegral,(Double_t) r1);
01027    Int_t binz = ibin/nxy;
01028    Int_t biny = (ibin - nxy*binz)/nbinsx;
01029    Int_t binx = ibin - nbinsx*(biny + nbinsy*binz);
01030    x = fXaxis.GetBinLowEdge(binx+1);
01031    if (r1 > fIntegral[ibin]) x +=
01032       fXaxis.GetBinWidth(binx+1)*(r1-fIntegral[ibin])/(fIntegral[ibin+1] - fIntegral[ibin]);
01033    y = fYaxis.GetBinLowEdge(biny+1) + fYaxis.GetBinWidth(biny+1)*gRandom->Rndm();
01034    z = fZaxis.GetBinLowEdge(binz+1) + fZaxis.GetBinWidth(binz+1)*gRandom->Rndm();
01035 }
01036 
01037 //______________________________________________________________________________
01038 void TH3::GetStats(Double_t *stats) const
01039 {
01040    // fill the array stats from the contents of this histogram
01041    // The array stats must be correctly dimensionned in the calling program.
01042    // stats[0] = sumw
01043    // stats[1] = sumw2
01044    // stats[2] = sumwx
01045    // stats[3] = sumwx2
01046    // stats[4] = sumwy
01047    // stats[5] = sumwy2
01048    // stats[6] = sumwxy
01049    // stats[7] = sumwz
01050    // stats[8] = sumwz2
01051    // stats[9] = sumwxz
01052    // stats[10]= sumwyz
01053 
01054    if (fBuffer) ((TH3*)this)->BufferEmpty();
01055 
01056    Int_t bin, binx, biny, binz;
01057    Double_t w,err;
01058    Double_t x,y,z;
01059    if ((fTsumw == 0 && fEntries > 0) || fXaxis.TestBit(TAxis::kAxisRange) || fYaxis.TestBit(TAxis::kAxisRange) || fZaxis.TestBit(TAxis::kAxisRange)) {
01060       for (bin=0;bin<9;bin++) stats[bin] = 0;
01061 
01062       Int_t firstBinX = fXaxis.GetFirst();
01063       Int_t lastBinX  = fXaxis.GetLast();
01064       Int_t firstBinY = fYaxis.GetFirst();
01065       Int_t lastBinY  = fYaxis.GetLast();
01066       Int_t firstBinZ = fZaxis.GetFirst();
01067       Int_t lastBinZ  = fZaxis.GetLast();
01068       // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
01069       if (fgStatOverflows) {
01070          if ( !fXaxis.TestBit(TAxis::kAxisRange) ) {
01071             if (firstBinX == 1) firstBinX = 0;
01072             if (lastBinX ==  fXaxis.GetNbins() ) lastBinX += 1;
01073          }
01074          if ( !fYaxis.TestBit(TAxis::kAxisRange) ) {
01075             if (firstBinY == 1) firstBinY = 0;
01076             if (lastBinY ==  fYaxis.GetNbins() ) lastBinY += 1;
01077          }
01078          if ( !fZaxis.TestBit(TAxis::kAxisRange) ) {
01079             if (firstBinZ == 1) firstBinZ = 0;
01080             if (lastBinZ ==  fZaxis.GetNbins() ) lastBinZ += 1;
01081          }
01082       }
01083       for (binz = firstBinZ; binz <= lastBinZ; binz++) {
01084          z = fZaxis.GetBinCenter(binz);
01085          for (biny = firstBinY; biny <= lastBinY; biny++) {
01086             y = fYaxis.GetBinCenter(biny);
01087             for (binx = firstBinX; binx <= lastBinX; binx++) {
01088                bin = GetBin(binx,biny,binz);
01089                x   = fXaxis.GetBinCenter(binx);
01090                w   = TMath::Abs(GetBinContent(bin));
01091                err = TMath::Abs(GetBinError(bin));
01092                stats[0] += w;
01093                stats[1] += err*err;
01094                stats[2] += w*x;
01095                stats[3] += w*x*x;
01096                stats[4] += w*y;
01097                stats[5] += w*y*y;
01098                stats[6] += w*x*y;
01099                stats[7] += w*z;
01100                stats[8] += w*z*z;
01101                stats[9] += w*x*z;
01102                stats[10]+= w*y*z;
01103             }
01104          }
01105       }
01106    } else {
01107       stats[0] = fTsumw;
01108       stats[1] = fTsumw2;
01109       stats[2] = fTsumwx;
01110       stats[3] = fTsumwx2;
01111       stats[4] = fTsumwy;
01112       stats[5] = fTsumwy2;
01113       stats[6] = fTsumwxy;
01114       stats[7] = fTsumwz;
01115       stats[8] = fTsumwz2;
01116       stats[9] = fTsumwxz;
01117       stats[10]= fTsumwyz;
01118    }
01119 }
01120 
01121 //______________________________________________________________________________
01122 Double_t TH3::Integral(Option_t *option) const
01123 {
01124    //Return integral of bin contents. Only bins in the bins range are considered.
01125    // By default the integral is computed as the sum of bin contents in the range.
01126    // if option "width" is specified, the integral is the sum of
01127    // the bin contents multiplied by the bin width in x, y and in z.
01128 
01129    return Integral(fXaxis.GetFirst(),fXaxis.GetLast(),
01130       fYaxis.GetFirst(),fYaxis.GetLast(),
01131       fZaxis.GetFirst(),fZaxis.GetLast(),option);
01132 }
01133 
01134 //______________________________________________________________________________
01135 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
01136 {
01137    //Return integral of bin contents in range [binx1,binx2],[biny1,biny2],[binz1,binz2]
01138    // for a 3-D histogram
01139    // By default the integral is computed as the sum of bin contents in the range.
01140    // if option "width" is specified, the integral is the sum of
01141    // the bin contents multiplied by the bin width in x, y and in z.
01142 
01143    Double_t err = 0; 
01144    return DoIntegral(binx1,binx2,biny1,biny2,binz1,binz2,err,option);
01145 }
01146 //______________________________________________________________________________
01147 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
01148 {
01149    //Return integral of bin contents in range [binx1,binx2],[biny1,biny2],[binz1,binz2]
01150    // for a 3-D histogram. Calculates also the integral error using error propagation 
01151    // from the bin errors assumming that all the bins are uncorrelated. 
01152    // By default the integral is computed as the sum of bin contents in the range.
01153    // if option "width" is specified, the integral is the sum of
01154    // the bin contents multiplied by the bin width in x, y and in z.
01155    return DoIntegral(binx1,binx2,biny1,biny2,binz1,binz2,error,option,kTRUE);
01156 }
01157 
01158 //______________________________________________________________________________
01159 Double_t TH3::Interpolate(Double_t)
01160 {
01161    
01162    //Not yet implemented
01163    Error("Interpolate","This function must be called with 3 arguments for a TH3");
01164    return 0;
01165 }
01166 
01167 //______________________________________________________________________________
01168 Double_t TH3::Interpolate(Double_t, Double_t)
01169 {
01170    
01171    //Not yet implemented
01172    Error("Interpolate","This function must be called with 3 arguments for a TH3");
01173    return 0;
01174 }
01175 
01176 //______________________________________________________________________________
01177 Double_t TH3::Interpolate(Double_t x, Double_t y, Double_t z)
01178 {
01179    // Given a point P(x,y,z), Interpolate approximates the value via trilinear interpolation
01180    // based on the 8 nearest bin center points ( corner of the cube surronding the points) 
01181    // The Algorithm is described in http://en.wikipedia.org/wiki/Trilinear_interpolation
01182    // The given values (x,y,z) must be between first bin center and  last bin center for each coordinate: 
01183    //
01184    //   fXAxis.GetBinCenter(1) < x  < fXaxis.GetBinCenter(nbinX)     AND
01185    //   fYAxis.GetBinCenter(1) < y  < fYaxis.GetBinCenter(nbinY)     AND
01186    //   fZAxis.GetBinCenter(1) < z  < fZaxis.GetBinCenter(nbinZ) 
01187 
01188    Int_t ubx = fXaxis.FindBin(x);
01189    if ( x < fXaxis.GetBinCenter(ubx) ) ubx -= 1;
01190    Int_t obx = ubx + 1;
01191 
01192    Int_t uby = fYaxis.FindBin(y);
01193    if ( y < fYaxis.GetBinCenter(uby) ) uby -= 1;
01194    Int_t oby = uby + 1;
01195 
01196    Int_t ubz = fZaxis.FindBin(z);
01197    if ( z < fZaxis.GetBinCenter(ubz) ) ubz -= 1;
01198    Int_t obz = ubz + 1;
01199 
01200 
01201 //    if ( IsBinUnderflow(GetBin(ubx, uby, ubz)) ||
01202 //         IsBinOverflow (GetBin(obx, oby, obz)) ) {
01203    if (ubx <=0 || uby <=0 || ubz <= 0 ||
01204        obx > fXaxis.GetNbins() || oby > fYaxis.GetNbins() || obz > fZaxis.GetNbins() ) {
01205       Error("Interpolate","Cannot interpolate outside histogram domain.");
01206       return 0;
01207    }
01208 
01209    Double_t xw = fXaxis.GetBinCenter(obx) - fXaxis.GetBinCenter(ubx);
01210    Double_t yw = fYaxis.GetBinCenter(oby) - fYaxis.GetBinCenter(uby);
01211    Double_t zw = fZaxis.GetBinCenter(obz) - fZaxis.GetBinCenter(ubz);
01212 
01213    Double_t xd = (x - fXaxis.GetBinCenter(ubx)) / xw;
01214    Double_t yd = (y - fYaxis.GetBinCenter(uby)) / yw;
01215    Double_t zd = (z - fZaxis.GetBinCenter(ubz)) / zw;
01216 
01217 
01218    Double_t v[] = { GetBinContent( ubx, uby, ubz ), GetBinContent( ubx, uby, obz ),
01219                     GetBinContent( ubx, oby, ubz ), GetBinContent( ubx, oby, obz ),
01220                     GetBinContent( obx, uby, ubz ), GetBinContent( obx, uby, obz ),
01221                     GetBinContent( obx, oby, ubz ), GetBinContent( obx, oby, obz ) };
01222 
01223 
01224    Double_t i1 = v[0] * (1 - zd) + v[1] * zd;
01225    Double_t i2 = v[2] * (1 - zd) + v[3] * zd;
01226    Double_t j1 = v[4] * (1 - zd) + v[5] * zd;
01227    Double_t j2 = v[6] * (1 - zd) + v[7] * zd;
01228 
01229 
01230    Double_t w1 = i1 * (1 - yd) + i2 * yd;
01231    Double_t w2 = j1 * (1 - yd) + j2 * yd;
01232 
01233 
01234    Double_t result = w1 * (1 - xd) + w2 * xd;
01235 
01236    return result;
01237 }
01238 
01239 //______________________________________________________________________________
01240 Double_t TH3::KolmogorovTest(const TH1 *h2, Option_t *option) const
01241 {
01242    //  Statistical test of compatibility in shape between
01243    //  THIS histogram and h2, using Kolmogorov test.
01244    //     Default: Ignore under- and overflow bins in comparison
01245    //
01246    //     option is a character string to specify options
01247    //         "U" include Underflows in test
01248    //         "O" include Overflows
01249    //         "N" include comparison of normalizations
01250    //         "D" Put out a line of "Debug" printout
01251    //         "M" Return the Maximum Kolmogorov distance instead of prob
01252    //
01253    //   The returned function value is the probability of test
01254    //       (much less than one means NOT compatible)
01255    //
01256    //   The KS test uses the distance between the pseudo-CDF's obtained 
01257    //   from the histogram. Since in more than 1D the order for generating the pseudo-CDF is 
01258    //   arbitrary, we use the pseudo-CDF's obtained from all the possible 6 combinatons of the 3 axis. 
01259    //   The average of all the maximum  distances obtained is used in the tests.  
01260 
01261    TString opt = option;
01262    opt.ToUpper();
01263 
01264    Double_t prb = 0;
01265    TH1 *h1 = (TH1*)this;
01266    if (h2 == 0) return 0;
01267    TAxis *xaxis1 = h1->GetXaxis();
01268    TAxis *xaxis2 = h2->GetXaxis();
01269    TAxis *yaxis1 = h1->GetYaxis();
01270    TAxis *yaxis2 = h2->GetYaxis();
01271    TAxis *zaxis1 = h1->GetZaxis();
01272    TAxis *zaxis2 = h2->GetZaxis();
01273    Int_t ncx1   = xaxis1->GetNbins();
01274    Int_t ncx2   = xaxis2->GetNbins();
01275    Int_t ncy1   = yaxis1->GetNbins();
01276    Int_t ncy2   = yaxis2->GetNbins();
01277    Int_t ncz1   = zaxis1->GetNbins();
01278    Int_t ncz2   = zaxis2->GetNbins();
01279 
01280    // Check consistency of dimensions
01281    if (h1->GetDimension() != 3 || h2->GetDimension() != 3) {
01282       Error("KolmogorovTest","Histograms must be 3-D\n");
01283       return 0;
01284    }
01285 
01286    // Check consistency in number of channels
01287    if (ncx1 != ncx2) {
01288       Error("KolmogorovTest","Number of channels in X is different, %d and %d\n",ncx1,ncx2);
01289       return 0;
01290    }
01291    if (ncy1 != ncy2) {
01292       Error("KolmogorovTest","Number of channels in Y is different, %d and %d\n",ncy1,ncy2);
01293       return 0;
01294    }
01295    if (ncz1 != ncz2) {
01296       Error("KolmogorovTest","Number of channels in Z is different, %d and %d\n",ncz1,ncz2);
01297       return 0;
01298    }
01299 
01300    // Check consistency in channel edges
01301    Bool_t afunc1 = kFALSE;
01302    Bool_t afunc2 = kFALSE;
01303    Double_t difprec = 1e-5;
01304    Double_t diff1 = TMath::Abs(xaxis1->GetXmin() - xaxis2->GetXmin());
01305    Double_t diff2 = TMath::Abs(xaxis1->GetXmax() - xaxis2->GetXmax());
01306    if (diff1 > difprec || diff2 > difprec) {
01307       Error("KolmogorovTest","histograms with different binning along X");
01308       return 0;
01309    }
01310    diff1 = TMath::Abs(yaxis1->GetXmin() - yaxis2->GetXmin());
01311    diff2 = TMath::Abs(yaxis1->GetXmax() - yaxis2->GetXmax());
01312    if (diff1 > difprec || diff2 > difprec) {
01313       Error("KolmogorovTest","histograms with different binning along Y");
01314       return 0;
01315    }
01316    diff1 = TMath::Abs(zaxis1->GetXmin() - zaxis2->GetXmin());
01317    diff2 = TMath::Abs(zaxis1->GetXmax() - zaxis2->GetXmax());
01318    if (diff1 > difprec || diff2 > difprec) {
01319       Error("KolmogorovTest","histograms with different binning along Z");
01320       return 0;
01321    }
01322 
01323    //   Should we include Uflows, Oflows?
01324    Int_t ibeg = 1, jbeg = 1, kbeg = 1;
01325    Int_t iend = ncx1, jend = ncy1, kend = ncz1;
01326    if (opt.Contains("U")) {ibeg = 0; jbeg = 0; kbeg = 0;}
01327    if (opt.Contains("O")) {iend = ncx1+1; jend = ncy1+1; kend = ncz1+1;}
01328 
01329    Int_t i,j,k,bin;
01330    Double_t sum1  = 0;
01331    Double_t sum2  = 0;
01332    Double_t w1    = 0;
01333    Double_t w2    = 0;
01334    for (i = ibeg; i <= iend; i++) {
01335       for (j = jbeg; j <= jend; j++) {
01336          for (k = kbeg; k <= kend; k++) {
01337             bin = h1->GetBin(i,j,k);
01338             sum1 += h1->GetBinContent(bin);
01339             sum2 += h2->GetBinContent(bin);
01340             Double_t ew1   = h1->GetBinError(bin);
01341             Double_t ew2   = h2->GetBinError(bin);
01342             w1   += ew1*ew1;
01343             w2   += ew2*ew2;
01344          }
01345       }
01346    }
01347 
01348 
01349    //    Check that both scatterplots contain events
01350    if (sum1 == 0) {
01351       Error("KolmogorovTest","Integral is zero for h1=%s\n",h1->GetName());
01352       return 0;
01353    }
01354    if (sum2 == 0) {
01355       Error("KolmogorovTest","Integral is zero for h2=%s\n",h2->GetName());
01356       return 0;
01357    }
01358    // calculate the effective entries.  
01359    // the case when errors are zero (w1 == 0 or w2 ==0) are equivalent to 
01360    // compare to a function. In that case the rescaling is done only on sqrt(esum2) or sqrt(esum1) 
01361    Double_t esum1 = 0, esum2 = 0; 
01362    if (w1 > 0) 
01363       esum1 = sum1 * sum1 / w1; 
01364    else 
01365       afunc1 = kTRUE;    // use later for calculating z
01366    
01367    if (w2 > 0) 
01368       esum2 = sum2 * sum2 / w2; 
01369    else 
01370       afunc2 = kTRUE;    // use later for calculating z
01371    
01372    if (afunc2 && afunc1) { 
01373       Error("KolmogorovTest","Errors are zero for both histograms\n");
01374       return 0;
01375    }
01376 
01377    //   Find Kolmogorov distance
01378    //   order is arbitrary take average of all possible 6 starting orders x,y,z 
01379    int order[3] = {0,1,2};
01380    int binbeg[3]; 
01381    int binend[3]; 
01382    int ibin[3];
01383    binbeg[0] = ibeg; binbeg[1] = jbeg; binbeg[2] = kbeg; 
01384    binend[0] = iend; binend[1] = jend; binend[2] = kend; 
01385    Double_t vdfmax[6]; // there are in total 6 combinations 
01386    int icomb = 0; 
01387    Double_t s1 = 1./(6.*sum1);
01388    Double_t s2 = 1./(6.*sum2);
01389    Double_t rsum1=0, rsum2=0;
01390    do { 
01391       // loop on bins
01392       Double_t dmax = 0;
01393       for (i = binbeg[order[0] ]; i <= binend[order[0] ]; i++) {
01394          for ( j = binbeg[order[1] ]; j <= binend[order[1] ]; j++) {
01395             for ( k = binbeg[order[2] ]; k <= binend[order[2] ]; k++) {
01396                   ibin[ order[0] ] = i;
01397                   ibin[ order[1] ] = j;
01398                   ibin[ order[2] ] = k;
01399                   bin = h1->GetBin(ibin[0],ibin[1],ibin[2]);
01400                   rsum1 += s1*h1->GetBinContent(bin);
01401                   rsum2 += s2*h2->GetBinContent(bin);
01402                   dmax   = TMath::Max(dmax, TMath::Abs(rsum1-rsum2));
01403             }
01404          }
01405       }
01406       vdfmax[icomb] = dmax; 
01407       icomb++;
01408    } while (TMath::Permute(3,order)  );
01409 
01410 
01411    // get average of distances 
01412    Double_t dfmax = TMath::Mean(6,vdfmax);
01413    
01414    //    Get Kolmogorov probability
01415    Double_t factnm;
01416    if (afunc1)      factnm = TMath::Sqrt(sum2);
01417    else if (afunc2) factnm = TMath::Sqrt(sum1);
01418    else             factnm = TMath::Sqrt(sum1*sum2/(sum1+sum2));
01419    Double_t z  = dfmax*factnm;
01420 
01421    prb = TMath::KolmogorovProb(z); 
01422 
01423    Double_t prb1 = 0, prb2 = 0; 
01424    // option N to combine normalization makes sense if both afunc1 and afunc2 are false
01425    if (opt.Contains("N")  && !(afunc1 || afunc2 ) ) { 
01426       // Combine probabilities for shape and normalization
01427       prb1   = prb;
01428       Double_t d12    = esum1-esum2;
01429       Double_t chi2   = d12*d12/(esum1+esum2);
01430       prb2   = TMath::Prob(chi2,1);
01431       //     see Eadie et al., section 11.6.2
01432       if (prb > 0 && prb2 > 0) prb = prb*prb2*(1-TMath::Log(prb*prb2));
01433       else                     prb = 0;
01434    }
01435 
01436    //    debug printout
01437    if (opt.Contains("D")) {
01438       printf(" Kolmo Prob  h1 = %s, sum1=%g\n",h1->GetName(),sum1);
01439       printf(" Kolmo Prob  h2 = %s, sum2=%g\n",h2->GetName(),sum2);
01440       printf(" Kolmo Probabil = %f, Max Dist = %g\n",prb,dfmax);
01441       if (opt.Contains("N"))
01442          printf(" Kolmo Probabil = %f for shape alone, =%f for normalisation alone\n",prb1,prb2);
01443    }
01444    // This numerical error condition should never occur:
01445    if (TMath::Abs(rsum1-1) > 0.002) Warning("KolmogorovTest","Numerical problems with h1=%s\n",h1->GetName());
01446    if (TMath::Abs(rsum2-1) > 0.002) Warning("KolmogorovTest","Numerical problems with h2=%s\n",h2->GetName());
01447 
01448    if(opt.Contains("M"))      return dfmax;  // return avergae of max distance
01449 
01450    return prb;
01451 }
01452 
01453 
01454 //______________________________________________________________________________
01455 Long64_t TH3::Merge(TCollection *list)
01456 {
01457    //Add all histograms in the collection to this histogram.
01458    //This function computes the min/max for the axes,
01459    //compute a new number of bins, if necessary,
01460    //add bin contents, errors and statistics.
01461    //If overflows are present and limits are different the function will fail.
01462    //The function returns the total number of entries in the result histogram
01463    //if the merge is successfull, -1 otherwise.
01464    //
01465    //IMPORTANT remark. The 2 axis x and y may have different number
01466    //of bins and different limits, BUT the largest bin width must be
01467    //a multiple of the smallest bin width and the upper limit must also
01468    //be a multiple of the bin width.
01469 
01470    if (!list) return 0;
01471    if (list->IsEmpty()) return (Int_t) GetEntries();
01472 
01473    TList inlist;
01474    TH1* hclone = (TH1*)Clone("FirstClone");
01475    R__ASSERT(hclone);
01476    BufferEmpty(1);         // To remove buffer.
01477    Reset();                // BufferEmpty sets limits so we can't use it later.
01478    SetEntries(0);
01479    inlist.Add(hclone);
01480    inlist.AddAll(list);
01481 
01482    TAxis newXAxis;
01483    TAxis newYAxis;
01484    TAxis newZAxis;
01485    Bool_t initialLimitsFound = kFALSE;
01486    Bool_t same = kTRUE;
01487    Bool_t allHaveLimits = kTRUE;
01488 
01489    TIter next(&inlist);
01490    while (TObject *o = next()) {
01491       TH3* h = dynamic_cast<TH3*> (o);
01492       if (!h) {
01493          Error("Add","Attempt to add object of class: %s to a %s",
01494             o->ClassName(),this->ClassName());
01495          return -1;
01496       }
01497       Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
01498       allHaveLimits = allHaveLimits && hasLimits;
01499 
01500       if (hasLimits) {
01501          h->BufferEmpty();
01502          if (!initialLimitsFound) {
01503             initialLimitsFound = kTRUE;
01504             newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
01505                h->GetXaxis()->GetXmax());
01506             newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
01507                h->GetYaxis()->GetXmax());
01508             newZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
01509                h->GetZaxis()->GetXmax());
01510          }
01511          else {
01512             if (!RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
01513                Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
01514                   "first: (%d, %f, %f), second: (%d, %f, %f)",
01515                   newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
01516                   h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
01517                   h->GetXaxis()->GetXmax());
01518             }
01519             if (!RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
01520                Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
01521                   "first: (%d, %f, %f), second: (%d, %f, %f)",
01522                   newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
01523                   h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
01524                   h->GetYaxis()->GetXmax());
01525             }
01526             if (!RecomputeAxisLimits(newZAxis, *(h->GetZaxis()))) {
01527                Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
01528                   "first: (%d, %f, %f), second: (%d, %f, %f)",
01529                   newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax(),
01530                   h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
01531                   h->GetZaxis()->GetXmax());
01532             }
01533          }
01534       }
01535    }
01536    next.Reset();
01537 
01538    same = same && SameLimitsAndNBins(newXAxis, *GetXaxis())
01539       && SameLimitsAndNBins(newYAxis, *GetYaxis());
01540    if (!same && initialLimitsFound)
01541       SetBins(newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
01542       newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
01543       newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax());
01544 
01545    if (!allHaveLimits) {
01546       // fill this histogram with all the data from buffers of histograms without limits
01547       while (TH3* h = dynamic_cast<TH3*> (next())) {
01548          if (h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && h->fBuffer) {
01549             // no limits
01550             Int_t nbentries = (Int_t)h->fBuffer[0];
01551             for (Int_t i = 0; i < nbentries; i++)
01552                Fill(h->fBuffer[4*i + 2], h->fBuffer[4*i + 3],
01553                h->fBuffer[4*i + 4], h->fBuffer[4*i + 1]);
01554             // Entries from buffers have to be filled one by one
01555             // because FillN doesn't resize histograms.
01556          }
01557       }
01558       if (!initialLimitsFound)
01559          return (Int_t) GetEntries();  // all histograms have been processed
01560       next.Reset();
01561    }
01562 
01563    //merge bin contents and errors
01564    Double_t stats[kNstat], totstats[kNstat];
01565    for (Int_t i=0;i<kNstat;i++) {totstats[i] = stats[i] = 0;}
01566    GetStats(totstats);
01567    Double_t nentries = GetEntries();
01568    Int_t binx, biny, binz, ix, iy, iz, nx, ny, nz, bin, ibin;
01569    Double_t cu;
01570    Int_t nbix = fXaxis.GetNbins();
01571    Int_t nbiy = fYaxis.GetNbins();
01572    Bool_t canRebin=TestBit(kCanRebin);
01573    ResetBit(kCanRebin); // reset, otherwise setting the under/overflow will rebin
01574 
01575    while (TH1* h=(TH1*)next()) {
01576       // process only if the histogram has limits; otherwise it was processed before
01577       if (h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
01578          // import statistics
01579          h->GetStats(stats);
01580          for (Int_t i = 0; i < kNstat; i++)
01581             totstats[i] += stats[i];
01582          nentries += h->GetEntries();
01583 
01584          nx = h->GetXaxis()->GetNbins();
01585          ny = h->GetYaxis()->GetNbins();
01586          nz = h->GetZaxis()->GetNbins();
01587 
01588          for (binz = 0; binz <= nz + 1; binz++) {
01589             iz = fZaxis.FindBin(h->GetZaxis()->GetBinCenter(binz));
01590             for (biny = 0; biny <= ny + 1; biny++) {
01591                iy = fYaxis.FindBin(h->GetYaxis()->GetBinCenter(biny));
01592                for (binx = 0; binx <= nx + 1; binx++) {
01593                   ix = fXaxis.FindBin(h->GetXaxis()->GetBinCenter(binx));
01594                   bin = binx +(nx+2)*(biny + (ny+2)*binz);
01595                   ibin = ix +(nbix+2)*(iy + (nbiy+2)*iz);
01596                   cu  = h->GetBinContent(bin);
01597                   if ((!same) && (binx == 0 || binx == nx + 1
01598                      || biny == 0 || biny == ny + 1
01599                      || binz == 0 || binz == nz + 1)) {
01600                         if (cu != 0) {
01601                            Error("Merge", "Cannot merge histograms - the histograms have"
01602                               " different limits and undeflows/overflows are present."
01603                               " The initial histogram is now broken!");
01604                            return -1;
01605                         }
01606                   }
01607                   if (ibin <0) continue;
01608                   AddBinContent(ibin,cu);
01609                   if (fSumw2.fN) {
01610                      Double_t error1 = h->GetBinError(bin);
01611                      fSumw2.fArray[ibin] += error1*error1;
01612                   }
01613                }
01614             }
01615          }
01616       }
01617    }
01618    if (canRebin) SetBit(kCanRebin);
01619 
01620    //copy merged stats
01621    PutStats(totstats);
01622    SetEntries(nentries);
01623    inlist.Remove(hclone);
01624    delete hclone;
01625    return (Long64_t)nentries;
01626 }
01627 
01628 //______________________________________________________________________________
01629 TH1D *TH3::ProjectionX(const char *name, Int_t iymin, Int_t iymax, Int_t izmin, Int_t izmax, Option_t *option) const
01630 {
01631    //*-*-*-*-*Project a 3-D histogram into a 1-D histogram along X*-*-*-*-*-*-*
01632    //*-*      ====================================================
01633    //
01634    //   The projection is always of the type TH1D.
01635    //   The projection is made from the cells along the X axis
01636    //   ranging from iymin to iymax and izmin to izmax included.
01637    //   By default, underflow and overflows are included
01638    //   By Setting iymin=1 and iymax=NbinsY the underflow and/or overflow will be excluded
01639    //
01640    //   if option "e" is specified, the errors are computed.
01641    //   if option "d" is specified, the projection is drawn in the current pad.
01642    //   if option "o" original axis range of the target axes will be
01643    //   kept, but only bins inside the selected range will be filled.
01644    //
01645    //   NOTE that if a TH1D named "name" exists in the current directory or pad and having   
01646    //   a compatible axis, the histogram is reset and filled again with the projected contents of the TH3.
01647    //   In the case of axis incompatibility, an error is reported and a NULL pointer is returned.
01648    //
01649    //  implemented using Project3D
01650 
01651 
01652    TString opt = option;
01653    opt.ToLower();
01654 
01655    Int_t piymin = GetYaxis()->GetFirst();
01656    Int_t piymax = GetYaxis()->GetLast();
01657    Int_t pizmin = GetZaxis()->GetFirst();
01658    Int_t pizmax = GetZaxis()->GetLast();   
01659 
01660    GetYaxis()->SetRange(iymin,iymax);
01661    GetZaxis()->SetRange(izmin,izmax);
01662 
01663    // exclude underflow/overflow by forcing the axis range bit
01664    // due to limitation of TAxis::SetRange cannot select only underflow or overflow cannot have underflow or overflow only   
01665    if (iymin == 1 && iymax ==  GetNbinsY() ) GetYaxis()->SetBit(TAxis::kAxisRange); 
01666    if (izmin == 1 && izmax ==  GetNbinsZ() ) GetZaxis()->SetBit(TAxis::kAxisRange); 
01667    // I can use the useUF or useOF flag for exclude/include the underflow/overflow separtly
01668    // (-1 in the imax is considered as an overflow)
01669    Bool_t useUF = (iymin == 0 || izmin == 0); 
01670    Bool_t useOF = ( (iymax < 0 ) || (iymax > GetNbinsY() ) || (izmax < 0) || (izmax > GetNbinsZ() ) ); 
01671 
01672    Bool_t computeErrors = GetSumw2N();
01673    if (opt.Contains("e") ) { 
01674       computeErrors = kTRUE;
01675       opt.Remove(opt.First("e"),1);
01676    }
01677    Bool_t originalRange = kFALSE;
01678    if (opt.Contains('o') ) { 
01679       originalRange = kTRUE; 
01680       opt.Remove(opt.First("o"),1);
01681    }
01682   
01683    TH1D * h1 = DoProject1D(name, GetTitle(), this->GetXaxis(), computeErrors, originalRange, useUF, useOF);
01684 
01685    // restore original range
01686    GetYaxis()->SetRange(piymin,piymax);
01687    GetZaxis()->SetRange(pizmin,pizmax);
01688 
01689    // draw in current pad 
01690    if (h1 && opt.Contains("d")) {
01691       opt.Remove(opt.First("d"),1);
01692       TVirtualPad *padsav = gPad;
01693       TVirtualPad *pad = gROOT->GetSelectedPad();
01694       if (pad) pad->cd();
01695       if (!gPad->FindObject(h1)) {
01696          h1->Draw(opt);
01697       } else {
01698          h1->Paint(opt);
01699       }
01700       if (padsav) padsav->cd();
01701    }
01702 
01703    return h1;
01704 }
01705 
01706 //______________________________________________________________________________
01707 TH1D *TH3::ProjectionY(const char *name, Int_t ixmin, Int_t ixmax, Int_t izmin, Int_t izmax, Option_t *option) const
01708 {
01709    //*-*-*-*-*Project a 3-D histogram into a 1-D histogram along Y*-*-*-*-*-*-*
01710    //*-*      ====================================================
01711    //
01712    //   The projection is always of the type TH1D.
01713    //   The projection is made from the cells along the Y axis
01714    //   ranging from ixmin to ixmax and izmin to izmax included.
01715    //   By default, underflow and overflow are included. 
01716    //   By Setting ixmin=1 and ixmax=NbinsX the underflow and/or overflow will be excluded
01717    //
01718    //   if option "e" is specified, the errors are computed.
01719    //   if option "d" is specified, the projection is drawn in the current pad.
01720    //   if option "o" original axis range of the target axes will be
01721    //   kept, but only bins inside the selected range will be filled.
01722    //
01723    //   NOTE that if a TH1D named "name" exists in the current directory or pad and having   
01724    //   a compatible axis, the histogram is reset and filled again with the projected contents of the TH3.
01725    //   In the case of axis incompatibility, an error is reported and a NULL pointer is returned.
01726    //
01727    //  implemented using Project3D
01728 
01729 
01730    TString opt = option;
01731    opt.ToLower();
01732 
01733    Int_t pixmin = GetXaxis()->GetFirst();
01734    Int_t pixmax = GetXaxis()->GetLast();
01735    Int_t pizmin = GetZaxis()->GetFirst();
01736    Int_t pizmax = GetZaxis()->GetLast();   
01737 
01738    GetXaxis()->SetRange(ixmin,ixmax);
01739    GetZaxis()->SetRange(izmin,izmax);
01740 
01741    // exclude underflow/overflow by forcing the axis range bit
01742    // due to limitation of TAxis::SetRange cannot select only underflow or overflow cannot have underflow or overflow only   
01743    if (ixmin == 1 && ixmax ==  GetNbinsX() ) GetXaxis()->SetBit(TAxis::kAxisRange); 
01744    if (izmin == 1 && izmax ==  GetNbinsZ() ) GetZaxis()->SetBit(TAxis::kAxisRange); 
01745    // I can use the useUF or useOF flag for exclude/include the underflow/overflow separtly
01746    // (-1 in the imax is considered as an overflow)
01747    Bool_t useUF = (ixmin == 0 || izmin == 0); 
01748    Bool_t useOF = ( (ixmax < 0 ) || (ixmax > GetNbinsX() ) || (izmax < 0) || (izmax > GetNbinsZ() ) ); 
01749 
01750    Bool_t computeErrors = GetSumw2N();
01751    if (opt.Contains("e") ) { 
01752       computeErrors = kTRUE;
01753       opt.Remove(opt.First("e"),1);
01754    }
01755    Bool_t originalRange = kFALSE;
01756    if (opt.Contains('o') ) { 
01757       originalRange = kTRUE; 
01758       opt.Remove(opt.First("o"),1);
01759    }
01760   
01761    TH1D * h1 = DoProject1D(name, GetTitle(), this->GetYaxis(), computeErrors, originalRange, useUF, useOF);
01762 
01763    // restore axis range
01764    GetXaxis()->SetRange(pixmin,pixmax);
01765    GetZaxis()->SetRange(pizmin,pizmax);
01766 
01767    // draw in current pad 
01768    if (h1 && opt.Contains("d")) {
01769       opt.Remove(opt.First("d"),1);
01770       TVirtualPad *padsav = gPad;
01771       TVirtualPad *pad = gROOT->GetSelectedPad();
01772       if (pad) pad->cd();
01773       if (!gPad->FindObject(h1)) {
01774          h1->Draw(opt);
01775       } else {
01776          h1->Paint(opt);
01777       }
01778       if (padsav) padsav->cd();
01779    }
01780    
01781    return h1;
01782 }
01783 
01784 //______________________________________________________________________________
01785 TH1D *TH3::ProjectionZ(const char *name, Int_t ixmin, Int_t ixmax, Int_t iymin, Int_t iymax, Option_t *option) const
01786 {
01787    //*-*-*-*-*Project a 3-D histogram into a 1-D histogram along Z*-*-*-*-*-*-*
01788    //*-*      ====================================================
01789    //
01790    //   The projection is always of the type TH1D.
01791    //   The projection is made from the cells along the X axis
01792    //   ranging from ixmin to ixmax and iymin to iymax included.
01793    //   By default, bins 1 to nx and 1 to ny  are included
01794    //   By setting ixmin=1 and/or ixmax=NbinsX the underflow and/or overflow in X will be excluded
01795    //   By setting iymin=1 and/or iymax=NbinsY the underflow and/or overflow in Y will be excluded
01796    //
01797    //   if option "e" is specified, the errors are computed.
01798    //   if option "d" is specified, the projection is drawn in the current pad.
01799    //   if option "o" original axis range of the target axes will be
01800    //   kept, but only bins inside the selected range will be filled.
01801    //
01802    //   NOTE that if a TH1D named "name" exists in the current directory or pad and having   
01803    //   a compatible axis, the histogram is reset and filled again with the projected contents of the TH3.
01804    //   In the case of axis incompatibility, an error is reported and a NULL pointer is returned.
01805    //
01806    //  implemented using Project3D
01807 
01808 
01809    TString opt = option;
01810    opt.ToLower();
01811 
01812    Int_t pixmin = GetXaxis()->GetFirst();
01813    Int_t pixmax = GetXaxis()->GetLast();
01814    Int_t piymin = GetYaxis()->GetFirst();
01815    Int_t piymax = GetYaxis()->GetLast();  
01816 
01817    GetXaxis()->SetRange(ixmin,ixmax);
01818    GetYaxis()->SetRange(iymin,iymax);
01819 
01820    // exclude underflow/overflow by forcing the axis range bit
01821    // due to limitation of TAxis::SetRange cannot select only underflow or overflow cannot have underflow or overflow only   
01822    if (ixmin == 1 && ixmax ==  GetNbinsX() ) GetXaxis()->SetBit(TAxis::kAxisRange); 
01823    if (iymin == 1 && iymax ==  GetNbinsY() ) GetYaxis()->SetBit(TAxis::kAxisRange); 
01824    // I can use the useUF or useOF flag for exclude/include the underflow/overflow separtly
01825    // (-1 in the imax is considered as an overflow)
01826    Bool_t useUF = (ixmin == 0 || iymin == 0); 
01827    Bool_t useOF = ( (ixmax < 0 ) || (ixmax > GetNbinsX() ) || (iymax < 0) || (iymax > GetNbinsY() ) ); 
01828 
01829    Bool_t computeErrors = GetSumw2N();
01830    if (opt.Contains("e") ) { 
01831       computeErrors = kTRUE;
01832       opt.Remove(opt.First("e"),1);
01833    }
01834    Bool_t originalRange = kFALSE;
01835    if (opt.Contains('o') ) { 
01836       originalRange = kTRUE; 
01837       opt.Remove(opt.First("o"),1);
01838    }
01839 
01840    TH1D * h1 =  DoProject1D(name, GetTitle(), this->GetZaxis(), computeErrors, originalRange, useUF, useOF);
01841 
01842    // restore the range
01843    GetXaxis()->SetRange(pixmin,pixmax);
01844    GetYaxis()->SetRange(piymin,piymax);
01845 
01846    // draw in current pad 
01847    if (h1 && opt.Contains("d")) {
01848       opt.Remove(opt.First("d"),1);
01849       TVirtualPad *padsav = gPad;
01850       TVirtualPad *pad = gROOT->GetSelectedPad();
01851       if (pad) pad->cd();
01852       if (!gPad->FindObject(h1)) {
01853          h1->Draw(opt);
01854       } else {
01855          h1->Paint(opt);
01856       }
01857       if (padsav) padsav->cd();
01858    }
01859 
01860    return h1;
01861 }
01862 
01863 //______________________________________________________________________________
01864 TH1D *TH3::DoProject1D(const char* name, const char* title, TAxis* projX, 
01865                     bool computeErrors, bool originalRange, 
01866                     bool useUF, bool useOF) const
01867 {
01868    // internal methdod performing the projection to 1D histogram
01869    // called from TH3::Project3D
01870 
01871    // Create the projection histogram
01872    TH1D *h1 = 0;
01873 
01874    // Get range to use as well as bin limits
01875    Int_t ixmin = projX->GetFirst();
01876    Int_t ixmax = projX->GetLast();
01877    if (ixmin == 0 && ixmax == 0) { ixmin = 1; ixmax = projX->GetNbins(); }
01878    Int_t nx = ixmax-ixmin+1;
01879 
01880    // Create the histogram, either reseting a preexisting one 
01881    // in case they have a compatible axis
01882    TObject *h1obj = gROOT->FindObject(name);
01883    if (h1obj && h1obj->InheritsFrom(TH1::Class())) {
01884       if (h1obj->IsA() != TH1D::Class() ) { 
01885          Error("DoProject1D","Histogram with name %s must be a TH1D and is a %s",name,h1obj->ClassName());
01886          return 0; 
01887       }
01888       h1 = (TH1D*)h1obj;
01889       // check histogram compatibility (not perfect for variable bins histograms)
01890       if ( h1->GetNbinsX() ==  projX->GetNbins() && 
01891            h1->GetXaxis()->GetXmin() == projX->GetXmin() &&
01892            h1->GetXaxis()->GetXmax() == projX->GetXmax() ) { 
01893          // enable originalRange option in case a range is set in the outer axis
01894          originalRange = kTRUE; 
01895          h1->Reset();
01896       }
01897       else if ( h1->GetNbinsX() ==  nx && 
01898                 h1->GetXaxis()->GetXmin() == projX->GetBinLowEdge(ixmin) &&
01899                 h1->GetXaxis()->GetXmax() == projX->GetBinUpEdge(ixmax) ) { 
01900          // reset also in case an histogram exists with compatible axis with the zoomed original axis
01901          h1->Reset();   
01902       }      
01903       else {  
01904          Error("DoProject1D","Histogram with name %s already exists and it is not compatible",name);
01905          return 0; 
01906       }
01907    }
01908 
01909    if (!h1) { 
01910       const TArrayD *bins = projX->GetXbins();
01911       if ( originalRange )
01912       {
01913          if (bins->fN == 0) {
01914             h1 = new TH1D(name,title,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
01915          } else {
01916             h1 = new TH1D(name,title,projX->GetNbins(),bins->fArray);
01917          }
01918       } else {
01919          if (bins->fN == 0) {
01920             h1 = new TH1D(name,title,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
01921          } else {
01922             h1 = new TH1D(name,title,nx,&bins->fArray[ixmin-1]);
01923          }
01924       }
01925    }
01926 
01927    // Copy the axis attributes and the axis labels if needed.
01928    h1->GetXaxis()->ImportAttributes(projX);
01929    THashList* labels = projX->GetLabels();
01930    if (labels) {
01931       TIter iL(labels);
01932       TObjString* lb;
01933       Int_t i = 1;
01934       while ((lb=(TObjString*)iL())) {
01935          h1->GetXaxis()->SetBinLabel(i,lb->String().Data());
01936          i++;
01937       }
01938    }
01939    h1->SetLineColor(this->GetLineColor());
01940    h1->SetFillColor(this->GetFillColor());
01941    h1->SetMarkerColor(this->GetMarkerColor());
01942    h1->SetMarkerStyle(this->GetMarkerStyle());
01943 
01944    // Activate errors
01945    if ( computeErrors ) h1->Sumw2();
01946 
01947    // Set references to the axis, so that the bucle has no branches.
01948    TAxis* out1 = 0;
01949    TAxis* out2 = 0;
01950    if ( projX == GetXaxis() ) {
01951       out1 = GetYaxis();
01952       out2 = GetZaxis();
01953    } else if ( projX == GetYaxis() ) {
01954       out1 = GetZaxis();
01955       out2 = GetXaxis();
01956    } else {
01957       out1 = GetYaxis();
01958       out2 = GetXaxis();
01959    }
01960 
01961    Int_t *refX = 0, *refY = 0, *refZ = 0;
01962    Int_t ixbin, out1bin, out2bin;
01963    if ( projX == GetXaxis() ) { refX = &ixbin;   refY = &out1bin; refZ = &out2bin; }
01964    if ( projX == GetYaxis() ) { refX = &out2bin; refY = &ixbin;   refZ = &out1bin; }
01965    if ( projX == GetZaxis() ) { refX = &out2bin; refY = &out1bin; refZ = &ixbin;   }
01966    R__ASSERT (refX != 0 && refY != 0 && refZ != 0); 
01967 
01968    // Fill the projected histogram excluding underflow/overflows if considered in the option
01969    // if specified in the option (by default they considered)
01970    Double_t totcont  = 0;
01971 
01972    Int_t out1min = out1->GetFirst(); 
01973    Int_t out1max = out1->GetLast(); 
01974    // GetFirst(), GetLast() can return (0,0) when the range bit is set artifically (see TAxis::SetRange)
01975    if (out1min == 0 && out1max == 0) { out1min = 1; out1max = out1->GetNbins(); }
01976    // correct for underflow/overflows
01977    if (useUF && !out1->TestBit(TAxis::kAxisRange) )  out1min -= 1; 
01978    if (useOF && !out1->TestBit(TAxis::kAxisRange) )  out1max += 1; 
01979    Int_t out2min = out2->GetFirst(); 
01980    Int_t out2max = out2->GetLast(); 
01981    if (out2min == 0 && out2max == 0) { out2min = 1; out2max = out2->GetNbins(); }
01982    if (useUF && !out2->TestBit(TAxis::kAxisRange) )  out2min -= 1; 
01983    if (useOF && !out2->TestBit(TAxis::kAxisRange) )  out2max += 1; 
01984 
01985    for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++){
01986       if ( projX->TestBit(TAxis::kAxisRange) && ( ixbin < ixmin || ixbin > ixmax )) continue;
01987 
01988       Double_t cont = 0; 
01989       Double_t err2 = 0; 
01990 
01991       // loop on the bins to be integrated (outbin should be called inbin)
01992       for (out1bin = out1min; out1bin <= out1max; out1bin++){
01993          for (out2bin = out2min; out2bin <= out2max; out2bin++){
01994 
01995             Int_t bin = GetBin(*refX, *refY, *refZ);
01996 
01997             // sum the bin contents and errors if needed
01998             cont += GetBinContent(bin);
01999             if (computeErrors) { 
02000                Double_t exyz = GetBinError(bin);
02001                err2 += exyz*exyz;
02002             }
02003          }
02004       }
02005       Int_t ix    = h1->FindBin( projX->GetBinCenter(ixbin) );
02006       h1->SetBinContent(ix ,cont);
02007       if (computeErrors) h1->SetBinError(ix, TMath::Sqrt(err2) ); 
02008       // sum all content
02009       totcont += cont;
02010       
02011    }
02012 
02013    // since we use a combination of fill and SetBinError we need to reset and recalculate the statistics
02014    // for weighted histograms otherwise sumw2 will be wrong. 
02015    // We  can keep the original statistics from the TH3 if the projected sumw is consistent with original one
02016    // i.e. when no events are thrown away  
02017    bool resetStats = true; 
02018    double eps = 1.E-12;
02019    if (IsA() == TH3F::Class() ) eps = 1.E-6;
02020    if (fTsumw != 0 && TMath::Abs( fTsumw - totcont) <  TMath::Abs(fTsumw) * eps) resetStats = false; 
02021 
02022    bool resetEntries = resetStats; 
02023    // entries are calculated using underflow/overflow. If excluded entries must be reset
02024    resetEntries |= !useUF || !useOF; 
02025    
02026 
02027    if (!resetStats) {
02028       Double_t stats[kNstat];
02029       GetStats(stats); 
02030       if ( projX == GetYaxis() ) {
02031          stats[2] = stats[4];
02032          stats[3] = stats[5]; 
02033       }
02034       else if  ( projX == GetZaxis() ) {
02035          stats[2] = stats[7];
02036          stats[3] = stats[8]; 
02037       }
02038       h1->PutStats(stats);
02039    }
02040    else {
02041       // reset statistics 
02042       h1->ResetStats();
02043    }
02044    if (resetEntries) { 
02045       // in case of error calculation (i.e. when Sumw2() is set) 
02046       // use the effective entries for the entries
02047       // since this  is the only way to estimate them
02048       Double_t entries =  TMath::Floor( totcont + 0.5); // to avoid numerical rounding         
02049       if (computeErrors) entries = h1->GetEffectiveEntries();
02050       h1->SetEntries( entries );  
02051    }
02052    else { 
02053       h1->SetEntries( fEntries );  
02054    }
02055 
02056    return h1;
02057 }
02058 
02059 //______________________________________________________________________________
02060 TH2D *TH3::DoProject2D(const char* name, const char * title, TAxis* projX, TAxis* projY,  
02061                     bool computeErrors, bool originalRange,
02062                     bool useUF, bool useOF) const
02063 {
02064    // internal method performing the projection to a 2D histogram
02065    // called from TH3::Project3D 
02066 
02067    TH2D *h2 = 0;
02068 
02069    // Get range to use as well as bin limits
02070    Int_t ixmin = projX->GetFirst();
02071    Int_t ixmax = projX->GetLast();
02072    Int_t iymin = projY->GetFirst();
02073    Int_t iymax = projY->GetLast();
02074    if (ixmin == 0 && ixmax == 0) { ixmin = 1; ixmax = projX->GetNbins(); }
02075    if (iymin == 0 && iymax == 0) { iymin = 1; iymax = projY->GetNbins(); }
02076    Int_t nx = ixmax-ixmin+1;
02077    Int_t ny = iymax-iymin+1;
02078 
02079    // Create the histogram, either reseting a preexisting one 
02080    // if compatible or creating one from scratch.
02081    // Does an object with the same name exists?
02082    TObject *h2obj = gROOT->FindObject(name);
02083    if (h2obj && h2obj->InheritsFrom(TH1::Class())) {
02084       if ( h2obj->IsA() != TH2D::Class() ) { 
02085          Error("DoProject2D","Histogram with name %s must be a TH2D and is a %s",name,h2obj->ClassName());
02086          return 0; 
02087       }
02088       h2 = (TH2D*)h2obj;
02089       // check histogram compatibility (not perfect for variable bins histograms)
02090       // note that the x axis of the projected histogram is  labeld  Y of the original
02091       if ( ( h2->GetNbinsX()           == projY->GetNbins()  && 
02092              h2->GetXaxis()->GetXmin() == projY->GetXmin()   &&
02093              h2->GetXaxis()->GetXmax() == projY->GetXmax() ) && 
02094            ( h2->GetNbinsY()          ==  projX->GetNbins()  && 
02095              h2->GetYaxis()->GetXmin() == projX->GetXmin()   &&
02096              h2->GetYaxis()->GetXmax() == projX->GetXmax() )  ) {  
02097          // enable originalRange option in case a range is set in the outer axis
02098          originalRange = kTRUE; 
02099          h2->Reset();
02100       }
02101       else if ( ( h2->GetNbinsX()           ==  ny                          && 
02102                   h2->GetXaxis()->GetXmin() == projY->GetBinLowEdge(iymin)  &&
02103                   h2->GetXaxis()->GetXmax() == projY->GetBinUpEdge(iymax) ) &&
02104                 ( h2->GetNbinsY()           ==  nx                          && 
02105                   h2->GetYaxis()->GetXmin() == projX->GetBinLowEdge(ixmin)  &&
02106                   h2->GetYaxis()->GetXmax() == projX->GetBinUpEdge(ixmax) )  ) { 
02107          // reset also in case an histogram exists with compatible axis with the zoomed original axis
02108          h2->Reset();   
02109       }      
02110       else {  
02111          Error("DoProject2D","Histogram with name %s already exists and it is not compatible",name);
02112          return 0; 
02113       }
02114    }
02115 
02116       
02117    if (!h2) { 
02118       const TArrayD *xbins = projX->GetXbins();
02119       const TArrayD *ybins = projY->GetXbins();
02120       if ( originalRange )
02121       {
02122          if (xbins->fN == 0 && ybins->fN == 0) {
02123             h2 = new TH2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
02124                           ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
02125          } else if (ybins->fN == 0) {
02126             h2 = new TH2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
02127                           ,projX->GetNbins(),&xbins->fArray[ixmin-1]);
02128          } else if (xbins->fN == 0) {
02129             h2 = new TH2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1]
02130                           ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
02131          } else {
02132             h2 = new TH2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1],projX->GetNbins(),&xbins->fArray[ixmin-1]);
02133          }
02134       } else {
02135          if (xbins->fN == 0 && ybins->fN == 0) {
02136             h2 = new TH2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
02137                           ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
02138          } else if (ybins->fN == 0) {
02139             h2 = new TH2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
02140                           ,nx,&xbins->fArray[ixmin-1]);
02141          } else if (xbins->fN == 0) {
02142             h2 = new TH2D(name,title,ny,&ybins->fArray[iymin-1]
02143                           ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
02144          } else {
02145             h2 = new TH2D(name,title,ny,&ybins->fArray[iymin-1],nx,&xbins->fArray[ixmin-1]);
02146          }
02147       }
02148    }
02149 
02150    // Copy the axis attributes and the axis labels if needed.
02151    THashList* labels1 = 0;
02152    THashList* labels2 = 0;
02153    // "xy"
02154    h2->GetXaxis()->ImportAttributes(projY);
02155    h2->GetYaxis()->ImportAttributes(projX);
02156    labels1 = projY->GetLabels();
02157    labels2 = projX->GetLabels();
02158    if (labels1) {
02159       TIter iL(labels1);
02160       TObjString* lb;
02161       Int_t i = 1;
02162       while ((lb=(TObjString*)iL())) {
02163          h2->GetXaxis()->SetBinLabel(i,lb->String().Data());
02164          i++;
02165       }
02166    }
02167    if (labels2) {
02168       TIter iL(labels2);
02169       TObjString* lb;
02170       Int_t i = 1;
02171       while ((lb=(TObjString*)iL())) {
02172          h2->GetYaxis()->SetBinLabel(i,lb->String().Data());
02173          i++;
02174       }
02175    }
02176    h2->SetLineColor(this->GetLineColor());
02177    h2->SetFillColor(this->GetFillColor());
02178    h2->SetMarkerColor(this->GetMarkerColor());
02179    h2->SetMarkerStyle(this->GetMarkerStyle());
02180 
02181    // Activate errors
02182    if ( computeErrors) h2->Sumw2();
02183 
02184    // Set references to the axis, so that the bucle has no branches.
02185    TAxis* out = 0;
02186    if ( projX != GetXaxis() && projY != GetXaxis() ) {
02187       out = GetXaxis();
02188    } else if ( projX != GetYaxis() && projY != GetYaxis() ) {
02189       out = GetYaxis();
02190    } else {
02191       out = GetZaxis();
02192    }
02193 
02194    Int_t *refX = 0, *refY = 0, *refZ = 0;
02195    Int_t ixbin, iybin, outbin;
02196    if ( projX == GetXaxis() && projY == GetYaxis() ) { refX = &ixbin;  refY = &iybin;  refZ = &outbin; }
02197    if ( projX == GetYaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &ixbin;  refZ = &outbin; }
02198    if ( projX == GetXaxis() && projY == GetZaxis() ) { refX = &ixbin;  refY = &outbin; refZ = &iybin;  }
02199    if ( projX == GetZaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &outbin; refZ = &ixbin;  }
02200    if ( projX == GetYaxis() && projY == GetZaxis() ) { refX = &outbin; refY = &ixbin;  refZ = &iybin;  }
02201    if ( projX == GetZaxis() && projY == GetYaxis() ) { refX = &outbin; refY = &iybin;  refZ = &ixbin;  }
02202    R__ASSERT (refX != 0 && refY != 0 && refZ != 0); 
02203 
02204    // Fill the projected histogram excluding underflow/overflows if considered in the option
02205    // if specified in the option (by default they considered)
02206    Double_t totcont  = 0;
02207 
02208    Int_t outmin = out->GetFirst(); 
02209    Int_t outmax = out->GetLast(); 
02210    // GetFirst(), GetLast() can return (0,0) when the range bit is set artifically (see TAxis::SetRange)
02211    if (outmin == 0 && outmax == 0) { outmin = 1; outmax = out->GetNbins(); }
02212    // correct for underflow/overflows
02213    if (useUF && !out->TestBit(TAxis::kAxisRange) )  outmin -= 1; 
02214    if (useOF && !out->TestBit(TAxis::kAxisRange) )  outmax += 1; 
02215 
02216    for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++){
02217       if ( projX->TestBit(TAxis::kAxisRange) && ( ixbin < ixmin || ixbin > ixmax )) continue;
02218       Int_t ix = h2->GetYaxis()->FindBin( projX->GetBinCenter(ixbin) );
02219 
02220       for (iybin=0;iybin<=1+projY->GetNbins();iybin++){
02221          if ( projY->TestBit(TAxis::kAxisRange) && ( iybin < iymin || iybin > iymax )) continue;
02222          Int_t iy = h2->GetXaxis()->FindBin( projY->GetBinCenter(iybin) );
02223 
02224          Double_t cont = 0; 
02225          Double_t err2 = 0;
02226 
02227          // loop on the bins to be integrated (outbin should be called inbin)
02228          for (outbin = outmin; outbin <= outmax; outbin++){
02229 
02230             Int_t bin = GetBin(*refX,*refY,*refZ);
02231 
02232             // sum the bin contents and errors if needed
02233             cont += GetBinContent(bin);
02234             if (computeErrors) { 
02235                Double_t exyz = GetBinError(bin);
02236                err2 += exyz*exyz;
02237             }
02238 
02239          }
02240 
02241          // remember axis are inverted 
02242          h2->SetBinContent(iy , ix, cont);
02243          if (computeErrors) h2->SetBinError(iy, ix, TMath::Sqrt(err2) ); 
02244          // sum all content
02245          totcont += cont;
02246 
02247       }
02248    }
02249 
02250    // since we use fill we need to reset and recalculate the statistics (see comment in DoProject1D )
02251    // or keep original statistics if consistent sumw2  
02252    bool resetStats = true; 
02253    double eps = 1.E-12;
02254    if (IsA() == TH3F::Class() ) eps = 1.E-6;
02255    if (fTsumw != 0 && TMath::Abs( fTsumw - totcont) <  TMath::Abs(fTsumw) * eps) resetStats = false; 
02256 
02257    bool resetEntries = resetStats; 
02258    // entries are calculated using underflow/overflow. If excluded entries must be reset
02259    resetEntries |= !useUF || !useOF; 
02260 
02261    if (!resetStats) {
02262       Double_t stats[kNstat];
02263       Double_t oldst[kNstat]; // old statistics
02264       for (Int_t i = 0; i < kNstat; ++i) { oldst[i] = 0; }
02265       GetStats(oldst); 
02266       std::copy(oldst,oldst+kNstat,stats);
02267       // not that projX refer to Y axis and projX refer to the X axis of projected histogram
02268       // nothing to do for projection in Y vs X
02269       if ( projY == GetXaxis() && projX == GetZaxis() ) {  // case XZ
02270          stats[4] = oldst[7];
02271          stats[5] = oldst[8];
02272          stats[6] = oldst[9];
02273       }
02274       if ( projY == GetYaxis() ) {
02275          stats[2] = oldst[4];
02276          stats[3] = oldst[5]; 
02277          if ( projX == GetXaxis() )  { // case YX
02278             stats[4] = oldst[2]; 
02279             stats[5] = oldst[3];
02280          }
02281          if ( projX == GetZaxis() )  { // case YZ
02282             stats[4] = oldst[7]; 
02283             stats[5] = oldst[8];
02284             stats[6] = oldst[10];
02285          }
02286       }
02287       else if  ( projY == GetZaxis() ) {
02288          stats[2] = oldst[7];
02289          stats[3] = oldst[8]; 
02290          if ( projX == GetXaxis() )  { // case ZX
02291             stats[4] = oldst[2]; 
02292             stats[5] = oldst[3];
02293             stats[6] = oldst[9];
02294          }
02295          if ( projX == GetZaxis() )  { // case ZY
02296             stats[4] = oldst[4]; 
02297             stats[5] = oldst[5];
02298             stats[6] = oldst[10];
02299          }
02300       }
02301       // set the new statistics 
02302       h2->PutStats(stats);
02303    }
02304    else { 
02305       // recalculate the statistics
02306       h2->ResetStats(); 
02307    }
02308 
02309    if (resetEntries) { 
02310       // use the effective entries for the entries
02311       // since this  is the only way to estimate them
02312       Double_t entries =  h2->GetEffectiveEntries();
02313       if (!computeErrors) entries = TMath::Floor( entries + 0.5); // to avoid numerical rounding
02314       h2->SetEntries( entries );  
02315    }
02316    else { 
02317       h2->SetEntries( fEntries );  
02318    }
02319 
02320 
02321    return h2;
02322 }
02323 
02324 
02325 //______________________________________________________________________________
02326 TH1 *TH3::Project3D(Option_t *option) const
02327 {
02328    // Project a 3-d histogram into 1 or 2-d histograms depending on the
02329    // option parameter
02330    // option may contain a combination of the characters x,y,z,e
02331    // option = "x" return the x projection into a TH1D histogram
02332    // option = "y" return the y projection into a TH1D histogram
02333    // option = "z" return the z projection into a TH1D histogram
02334    // option = "xy" return the x versus y projection into a TH2D histogram
02335    // option = "yx" return the y versus x projection into a TH2D histogram
02336    // option = "xz" return the x versus z projection into a TH2D histogram
02337    // option = "zx" return the z versus x projection into a TH2D histogram
02338    // option = "yz" return the y versus z projection into a TH2D histogram
02339    // option = "zy" return the z versus y projection into a TH2D histogram
02340    // NB: the notation "a vs b" means "a" vertical and "b" horizontal
02341    //
02342    // option = "o" original axis range of the target axes will be
02343    //   kept, but only bins inside the selected range will be filled.
02344    //
02345    // If option contains the string "e", errors are computed
02346    //
02347    // The projection is made for the selected bins only.
02348    // To select a bin range along an axis, use TAxis::SetRange, eg
02349    //    h3.GetYaxis()->SetRange(23,56);
02350    //
02351    // NOTE 1: The generated histogram is named th3name + option
02352    // eg if the TH3* h histogram is named "myhist", then
02353    // h->Project3D("xy"); produces a TH2D histogram named "myhist_xy"
02354    // if a histogram of the same type already exists, it is overwritten.
02355    // The following sequence
02356    //    h->Project3D("xy");
02357    //    h->Project3D("xy2");
02358    //  will generate two TH2D histograms named "myhist_xy" and "myhist_xy2"
02359    //  A different name can be generated by attaching a string to the option
02360    //  For example h->Project3D("name_xy") will generate an histogram with the name:  h3dname_name_xy. 
02361    //
02362    //  NOTE 2: If an histogram of the same type already exists with compatible axes, 
02363    //  the histogram is reset and filled again with the projected contents of the TH3.
02364    //  In the case of axes incompatibility, an error is reported and a NULL pointer is returned.
02365    //
02366    //  NOTE 3: The number of entries in the projected histogram is estimated from the number of 
02367    //  effective entries for all the cells included in the projection. 
02368    //
02369    //  NOTE 4: underflow/overflow are included by default in the projection 
02370    //  To exclude underflow and/or overflow (for both axis in case of a projection to a 1D histogram) use option "NUF" and/or "NOF"
02371    //  With SetRange() you can have all bins except underflow/overflow only if you set the axis bit range as 
02372    //  following after having called SetRange: 
02373    //    axis->SetRange(1, axis->GetNbins());
02374    //    axis->SetBit(TAxis::kAxisRange);  
02375    //          
02376 
02377    TString opt = option; opt.ToLower();
02378    Int_t pcase = 0;
02379    TString ptype; 
02380    if (opt.Contains("x"))  { pcase = 1; ptype = "x"; }
02381    if (opt.Contains("y"))  { pcase = 2; ptype = "y"; }
02382    if (opt.Contains("z"))  { pcase = 3; ptype = "z"; }
02383    if (opt.Contains("xy")) { pcase = 4; ptype = "xy"; }
02384    if (opt.Contains("yx")) { pcase = 5; ptype = "yx"; }
02385    if (opt.Contains("xz")) { pcase = 6; ptype = "xz"; }
02386    if (opt.Contains("zx")) { pcase = 7; ptype = "zx"; }
02387    if (opt.Contains("yz")) { pcase = 8; ptype = "yz"; }
02388    if (opt.Contains("zy")) { pcase = 9; ptype = "zy"; }
02389    
02390    if (pcase == 0) { 
02391       Error("Project3D","No projection axis specified - return a NULL pointer"); 
02392       return 0; 
02393    }
02394    // do not remove ptype from opt to use later in the projected histo name
02395 
02396    Bool_t computeErrors = GetSumw2N();
02397    if (opt.Contains("e") ) { 
02398       computeErrors = kTRUE;
02399       opt.Remove(opt.First("e"),1);
02400    }
02401 
02402    Bool_t useUF = kTRUE;
02403    Bool_t useOF = kTRUE;
02404    if (opt.Contains("nuf") ) { 
02405       useUF = kFALSE;
02406       opt.Remove(opt.Index("nuf"),3);
02407    }
02408    if (opt.Contains("nof") ) { 
02409       useOF = kFALSE;
02410       opt.Remove(opt.Index("nof"),3);
02411    }
02412 
02413    Bool_t originalRange = kFALSE;
02414    if (opt.Contains('o') ) { 
02415       originalRange = kTRUE; 
02416       opt.Remove(opt.First("o"),1);
02417    }
02418 
02419 
02420    // Create the projection histogram
02421    TH1 *h = 0;
02422 
02423    TString name = GetName();
02424    TString title = GetTitle();
02425    name  += "_";   name  += opt;  // opt may include a user defined name
02426    title += " ";   title += ptype; title += " projection";   
02427 
02428    switch (pcase) {
02429       case 1: 
02430          // "x"
02431          h = DoProject1D(name, title, this->GetXaxis(), 
02432                        computeErrors, originalRange, useUF, useOF);
02433          break;
02434 
02435       case 2:
02436          // "y"
02437          h = DoProject1D(name, title, this->GetYaxis(), 
02438                        computeErrors, originalRange, useUF, useOF);
02439          break;
02440 
02441       case 3:
02442          // "z"
02443          h = DoProject1D(name, title, this->GetZaxis(), 
02444                        computeErrors, originalRange, useUF, useOF);
02445          break;
02446 
02447       case 4:
02448          // "xy"
02449          h = DoProject2D(name, title, this->GetXaxis(),this->GetYaxis(), 
02450                        computeErrors, originalRange, useUF, useOF);
02451          break;
02452 
02453       case 5:
02454          // "yx"
02455          h = DoProject2D(name, title, this->GetYaxis(),this->GetXaxis(), 
02456                        computeErrors, originalRange, useUF, useOF);
02457          break;
02458 
02459       case 6:
02460          // "xz"
02461          h = DoProject2D(name, title, this->GetXaxis(),this->GetZaxis(), 
02462                        computeErrors, originalRange, useUF, useOF);
02463          break;
02464          
02465       case 7:
02466          // "zx"
02467          h = DoProject2D(name, title, this->GetZaxis(),this->GetXaxis(), 
02468                        computeErrors, originalRange, useUF, useOF);
02469          break;
02470 
02471       case 8:
02472          // "yz"
02473          h = DoProject2D(name, title, this->GetYaxis(),this->GetZaxis(), 
02474                        computeErrors, originalRange, useUF, useOF);
02475          break;
02476 
02477       case 9:
02478          // "zy"
02479          h = DoProject2D(name, title, this->GetZaxis(),this->GetYaxis(), 
02480                        computeErrors, originalRange, useUF, useOF);
02481          break;
02482 
02483    }
02484 
02485    // draw in current pad 
02486    if (h && opt.Contains("d")) {
02487       opt.Remove(opt.First("d"),1);
02488       TVirtualPad *padsav = gPad;
02489       TVirtualPad *pad = gROOT->GetSelectedPad();
02490       if (pad) pad->cd();
02491       if (!gPad->FindObject(h)) {
02492          h->Draw(opt);
02493       } else {
02494          h->Paint(opt);
02495       }
02496       if (padsav) padsav->cd();
02497    }
02498 
02499    return h;
02500 }
02501 
02502 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 { 
02503    // internal function to fill the bins of the projected profile 2D histogram 
02504    // called from DoProjectProfile2D
02505 
02506    Double_t cont = GetBinContent(inBin); 
02507    if (!cont) return; 
02508    TArrayD & binSumw2 = *(p2->GetBinSumw2()); 
02509    if (useWeights && binSumw2.fN <= 0) useWeights = false;  
02510    // the following fill update wrongly the fBinSumw2- need to save it before
02511    Double_t u = a1.GetBinCenter(bin1);
02512    Double_t v = a2.GetBinCenter(bin2);
02513    Double_t w = a3.GetBinCenter(bin3);
02514    Int_t outBin = p2->FindBin(u, v);
02515    if (outBin <0) return;
02516    Double_t tmp = 0;
02517    if ( useWeights ) tmp = binSumw2.fArray[outBin];            
02518    p2->Fill( u , v, w, cont);
02519 //    std::cout << "use "  << useWeights; 
02520 //    std::cout << " size " << binSumw2.fN << " inBin " << inBin << " o " << outBin << "  "  << bin1 << "  " << bin2 << " " << fSumw2.fN 
02521 //              << " u " << u << " v " << v << " w " << w << " tmp " << tmp << " sumw2 " << fSumw2.fArray[outBin] 
02522 //              << " fbinsumw2 " << binSumw2.fArray[outBin]
02523 //              << std::endl; 
02524    if (useWeights ) binSumw2.fArray[outBin] = tmp + fSumw2.fArray[inBin];
02525 } 
02526 
02527 //______________________________________________________________________________
02528 TProfile2D *TH3::DoProjectProfile2D(const char* name, const char * title, TAxis* projX, TAxis* projY, 
02529                                           bool originalRange, bool useUF, bool useOF) const
02530 {
02531    // internal method to project to a 2D Profile
02532    // called from TH3::Project3DProfile
02533 
02534    // Get the ranges where we will work.
02535    Int_t ixmin = projX->GetFirst();
02536    Int_t ixmax = projX->GetLast();
02537    Int_t iymin = projY->GetFirst();
02538    Int_t iymax = projY->GetLast();
02539    if (ixmin == 0 && ixmax == 0) { ixmin = 1; ixmax = projX->GetNbins(); }
02540    if (iymin == 0 && iymax == 0) { iymin = 1; iymax = projY->GetNbins(); }
02541    Int_t nx = ixmax-ixmin+1;
02542    Int_t ny = iymax-iymin+1;
02543 
02544    // Create the projected profiles
02545    TProfile2D *p2 = 0;
02546 
02547    // Create the histogram, either reseting a preexisting one 
02548    // if compatible or creating one from scratch.
02549    // Does an object with the same name exists?
02550    TObject *p2obj = gROOT->FindObject(name);
02551    if (p2obj && p2obj->InheritsFrom(TH1::Class())) {
02552       if (p2obj->IsA() != TProfile2D::Class() ) { 
02553          Error("DoProjectProfile2D","Histogram with name %s must be a TProfile2D and is a %s",name,p2obj->ClassName());
02554          return 0; 
02555       }
02556       p2 = (TProfile2D*)p2obj;
02557       // check histogram compatibility (not perfect for variable bins histograms)
02558       // note that the x axis of the projected histogram is  labeld  Y of the original
02559       if ( ( p2->GetNbinsX()           == projY->GetNbins()  && 
02560              p2->GetXaxis()->GetXmin() == projY->GetXmin()   &&
02561              p2->GetXaxis()->GetXmax() == projY->GetXmax() ) && 
02562            ( p2->GetNbinsY()          ==  projX->GetNbins()  && 
02563              p2->GetYaxis()->GetXmin() == projX->GetXmin()   &&
02564              p2->GetYaxis()->GetXmax() == projX->GetXmax() )  ) {  
02565          // enable originalRange option in case a range is set in the outer axis
02566          originalRange = kTRUE; 
02567          p2->Reset();
02568       }
02569       else if ( ( p2->GetNbinsX()           ==  ny                          && 
02570                   p2->GetXaxis()->GetXmin() == projY->GetBinLowEdge(iymin)  &&
02571                   p2->GetXaxis()->GetXmax() == projY->GetBinUpEdge(iymax) ) &&
02572                 ( p2->GetNbinsY()           ==  nx                          && 
02573                   p2->GetYaxis()->GetXmin() == projX->GetBinLowEdge(ixmin)  &&
02574                   p2->GetYaxis()->GetXmax() == projX->GetBinUpEdge(ixmax) )  ) { 
02575          // reset also in case an histogram exists with compatible axis with the zoomed original axis
02576          p2->Reset();   
02577       }      
02578       else {  
02579          p2->Dump();
02580          projY->Dump(); projX->Dump(); 
02581          std::cout << ny << "  " << iymin << " , " << iymax << " nx " << nx << "  " << ixmin << " , " << ixmax << std::endl;
02582          Error("DoProjectProfile2D","Profile2D with name %s already exists and it is not compatible",name);
02583          return 0; 
02584       }
02585    }
02586 
02587    if (!p2) { 
02588       const TArrayD *xbins = projX->GetXbins();
02589       const TArrayD *ybins = projY->GetXbins();
02590       if ( originalRange ) {
02591          if (xbins->fN == 0 && ybins->fN == 0) {
02592             p2 = new TProfile2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
02593                                 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
02594          } else if (ybins->fN == 0) {
02595             p2 = new TProfile2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
02596                                 ,projX->GetNbins(),&xbins->fArray[ixmin-1]);
02597          } else if (xbins->fN == 0) {
02598             p2 = new TProfile2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1]
02599                                 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
02600          } else {
02601             p2 = new TProfile2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1],projX->GetNbins(),&xbins->fArray[ixmin-1]);
02602          }
02603       } else {
02604          if (xbins->fN == 0 && ybins->fN == 0) {
02605             p2 = new TProfile2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
02606                                 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
02607          } else if (ybins->fN == 0) {
02608             p2 = new TProfile2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
02609                                 ,nx,&xbins->fArray[ixmin-1]);
02610          } else if (xbins->fN == 0) {
02611             p2 = new TProfile2D(name,title,ny,&ybins->fArray[iymin-1]
02612                                 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
02613          } else {
02614             p2 = new TProfile2D(name,title,ny,&ybins->fArray[iymin-1],nx,&xbins->fArray[ixmin-1]);
02615          }
02616       }
02617    }
02618 
02619    // Set references to the axis, so that the loop has no branches.
02620    TAxis* outAxis = 0;
02621    if ( projX != GetXaxis() && projY != GetXaxis() ) {
02622       outAxis = GetXaxis();
02623    } else if ( projX != GetYaxis() && projY != GetYaxis() ) {
02624       outAxis = GetYaxis();
02625    } else {
02626       outAxis = GetZaxis();
02627    }
02628 
02629    // Weights management
02630    bool useWeights = (GetSumw2N() > 0); 
02631    if (useWeights ) p2->Sumw2(); // store sum of w2 in profile if histo is weighted
02632    
02633    // Set references to the bins, so that the loop has no branches.
02634    Int_t *refX = 0, *refY = 0, *refZ = 0;
02635    Int_t ixbin, iybin, outbin;
02636    if ( projX == GetXaxis() && projY == GetYaxis() ) { refX = &ixbin;  refY = &iybin;  refZ = &outbin; }
02637    if ( projX == GetYaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &ixbin;  refZ = &outbin; }
02638    if ( projX == GetXaxis() && projY == GetZaxis() ) { refX = &ixbin;  refY = &outbin; refZ = &iybin;  }
02639    if ( projX == GetZaxis() && projY == GetXaxis() ) { refX = &iybin;  refY = &outbin; refZ = &ixbin;  }
02640    if ( projX == GetYaxis() && projY == GetZaxis() ) { refX = &outbin; refY = &ixbin;  refZ = &iybin;  }
02641    if ( projX == GetZaxis() && projY == GetYaxis() ) { refX = &outbin; refY = &iybin;  refZ = &ixbin;  }
02642    R__ASSERT (refX != 0 && refY != 0 && refZ != 0); 
02643 
02644    Int_t outmin = outAxis->GetFirst(); 
02645    Int_t outmax = outAxis->GetLast(); 
02646    // GetFirst(), GetLast() can return (0,0) when the range bit is set artifically (see TAxis::SetRange)
02647    if (outmin == 0 && outmax == 0) { outmin = 1; outmax = outAxis->GetNbins(); }
02648    // correct for underflow/overflows
02649    if (useUF && !outAxis->TestBit(TAxis::kAxisRange) )  outmin -= 1; 
02650    if (useOF && !outAxis->TestBit(TAxis::kAxisRange) )  outmax += 1; 
02651 
02652    TArrayD & binSumw2 = *(p2->GetBinSumw2()); 
02653    if (useWeights && binSumw2.fN <= 0) useWeights = false;  
02654 
02655    // Call specific method for the projection
02656    for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++){
02657       if ( (ixbin < ixmin || ixbin > ixmax) && projX->TestBit(TAxis::kAxisRange)) continue;
02658       for ( iybin=0;iybin<=1+projY->GetNbins();iybin++){
02659          if ( (iybin < iymin || iybin > iymax) && projX->TestBit(TAxis::kAxisRange)) continue;
02660 
02661          // profile output bin
02662          Int_t poutBin = p2->FindBin(projY->GetBinCenter(iybin), projX->GetBinCenter(ixbin));
02663          if (poutBin <0) continue;
02664          // loop on the bins to be integrated (outbin should be called inbin)
02665          for (outbin = outmin; outbin <= outmax; outbin++){
02666 
02667             Int_t bin = GetBin(*refX,*refY,*refZ);
02668 
02669             //DoFillProfileProjection(p2, *projY, *projX, *outAxis, iybin, ixbin, outbin, bin, useWeights); 
02670 
02671             Double_t cont = GetBinContent(bin); 
02672             if (!cont) continue; 
02673 
02674             Double_t tmp = 0;
02675             // the following fill update wrongly the fBinSumw2- need to save it before
02676             if ( useWeights ) tmp = binSumw2.fArray[poutBin];            
02677             p2->Fill( projY->GetBinCenter(iybin) , projX->GetBinCenter(ixbin), outAxis->GetBinCenter(outbin), cont);
02678             if (useWeights ) binSumw2.fArray[poutBin] = tmp + fSumw2.fArray[bin];
02679   
02680          }
02681       }
02682    }
02683 
02684    // recompute statistics for the projected profiles 
02685    // forget about preserving old statistics
02686    bool resetStats = true; 
02687    Double_t stats[kNstat];
02688    // reset statistics 
02689    if (resetStats) 
02690       for (Int_t i=0;i<kNstat;i++) stats[i] = 0;
02691 
02692    p2->PutStats(stats);
02693    Double_t entries = fEntries; 
02694    // recalculate the statistics
02695    if (resetStats) { 
02696       entries =  p2->GetEffectiveEntries();
02697       if (!useWeights) entries = TMath::Floor( entries + 0.5); // to avoid numerical rounding
02698       p2->SetEntries( entries );  
02699    }
02700 
02701    p2->SetEntries(entries);
02702 
02703    return p2;
02704 }
02705 
02706 //______________________________________________________________________________
02707 TProfile2D *TH3::Project3DProfile(Option_t *option) const
02708 {
02709    // Project a 3-d histogram into a 2-d profile histograms depending
02710    // on the option parameter
02711    // option may contain a combination of the characters x,y,z
02712    // option = "xy" return the x versus y projection into a TProfile2D histogram
02713    // option = "yx" return the y versus x projection into a TProfile2D histogram
02714    // option = "xz" return the x versus z projection into a TProfile2D histogram
02715    // option = "zx" return the z versus x projection into a TProfile2D histogram
02716    // option = "yz" return the y versus z projection into a TProfile2D histogram
02717    // option = "zy" return the z versus y projection into a TProfile2D histogram
02718    // NB: the notation "a vs b" means "a" vertical and "b" horizontal
02719    //
02720    // option = "o" original axis range of the target axes will be
02721    //   kept, but only bins inside the selected range will be filled.
02722    //
02723    // The projection is made for the selected bins only.
02724    // To select a bin range along an axis, use TAxis::SetRange, eg
02725    //    h3.GetYaxis()->SetRange(23,56);
02726    //
02727    // NOTE 1: The generated histogram is named th3name + _poption
02728    // eg if the TH3* h histogram is named "myhist", then
02729    // h->Project3D("xy"); produces a TProfile2D histogram named "myhist_pxy".
02730    // The following sequence
02731    //    h->Project3DProfile("xy");
02732    //    h->Project3DProfile("xy2");
02733    //  will generate two TProfile2D histograms named "myhist_pxy" and "myhist_pxy2"
02734    //
02735    //  NOTE 2: If a profile of the same type already exists with compatible axes, 
02736    //  the profile is reset and filled again with the projected contents of the TH3.
02737    //  In the case of axes incompatibility, an error is reported and a NULL pointer is returned.
02738    //
02739    //  NOTE 3: The number of entries in the projected profile is estimated from the number of 
02740    //  effective entries for all the cells included in the projection. 
02741    //
02742    //  NOTE 4: underflow/overflow are by default excluded from the projection 
02743    //  (Note that this is a different default behavior compared to the projection to an histogram) 
02744    //  To include the underflow and/or overflow use option "UF" and/or "OF"
02745 
02746    TString opt = option; opt.ToLower();
02747    Int_t pcase = 0;
02748    TString ptype; 
02749    if (opt.Contains("xy")) { pcase = 4; ptype = "xy"; }
02750    if (opt.Contains("yx")) { pcase = 5; ptype = "yx"; }
02751    if (opt.Contains("xz")) { pcase = 6; ptype = "xz"; }
02752    if (opt.Contains("zx")) { pcase = 7; ptype = "zx"; }
02753    if (opt.Contains("yz")) { pcase = 8; ptype = "yz"; }
02754    if (opt.Contains("zy")) { pcase = 9; ptype = "zy"; }
02755 
02756    if (pcase == 0) { 
02757       Error("Project3D","No projection axis specified - return a NULL pointer"); 
02758       return 0; 
02759    }
02760    // do not remove ptype from opt to use later in the projected histo name
02761 
02762    Bool_t useUF = kFALSE;
02763    if (opt.Contains("uf") ) { 
02764       useUF = kTRUE;
02765       opt.Remove(opt.Index("uf"),2);
02766    }
02767    Bool_t useOF = kFALSE;
02768    if (opt.Contains("of") ) { 
02769       useOF = kTRUE;
02770       opt.Remove(opt.Index("of"),2);
02771    }
02772 
02773    Bool_t originalRange = kFALSE;
02774    if (opt.Contains('o') ) { 
02775       originalRange = kTRUE; 
02776       opt.Remove(opt.First("o"),1);
02777    }
02778 
02779    // Create the projected profile
02780    TProfile2D *p2 = 0;
02781    TString name = GetName();
02782    TString title = GetTitle();
02783    name  += "_";   name  += opt;  // opt may include a user defined name
02784    title += " ";   title += ptype; title += " projection";   
02785 
02786    // Call the method with the specific projected axes.
02787    switch (pcase) {
02788       case 4:
02789          // "xy"
02790          p2 = DoProjectProfile2D(name, title, GetXaxis(), GetYaxis(), originalRange, useUF, useOF);
02791          break;
02792 
02793       case 5:
02794          // "yx"
02795          p2 = DoProjectProfile2D(name, title, GetYaxis(), GetXaxis(), originalRange, useUF, useOF);
02796          break;
02797 
02798       case 6:
02799          // "xz"
02800          p2 = DoProjectProfile2D(name, title, GetXaxis(), GetZaxis(), originalRange, useUF, useOF);
02801          break;
02802 
02803       case 7:
02804          // "zx"
02805          p2 = DoProjectProfile2D(name, title, GetZaxis(), GetXaxis(), originalRange, useUF, useOF);
02806          break;
02807 
02808       case 8:
02809          // "yz"
02810          p2 = DoProjectProfile2D(name, title, GetYaxis(), GetZaxis(), originalRange, useUF, useOF);
02811          break;
02812 
02813       case 9:
02814          // "zy"
02815          p2 = DoProjectProfile2D(name, title, GetZaxis(), GetYaxis(), originalRange, useUF, useOF);
02816          break;
02817 
02818    }
02819 
02820    return p2;
02821 }
02822 
02823 
02824 //______________________________________________________________________________
02825 void TH3::PutStats(Double_t *stats)
02826 {
02827    // Replace current statistics with the values in array stats
02828 
02829    TH1::PutStats(stats);
02830    fTsumwy  = stats[4];
02831    fTsumwy2 = stats[5];
02832    fTsumwxy = stats[6];
02833    fTsumwz  = stats[7];
02834    fTsumwz2 = stats[8];
02835    fTsumwxz = stats[9];
02836    fTsumwyz = stats[10];
02837 }
02838 
02839 //______________________________________________________________________________
02840 void TH3::Reset(Option_t *option)
02841 {
02842    //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
02843    //*-*            ===========================================
02844 
02845    TH1::Reset(option);
02846    TString opt = option;
02847    opt.ToUpper();
02848    if (opt.Contains("ICE")) return;
02849    fTsumwy  = 0;
02850    fTsumwy2 = 0;
02851    fTsumwxy = 0;
02852    fTsumwz  = 0;
02853    fTsumwz2 = 0;
02854    fTsumwxz = 0;
02855    fTsumwyz = 0;
02856 }
02857 
02858 //______________________________________________________________________________
02859 void TH3::Streamer(TBuffer &R__b)
02860 {
02861    // Stream an object of class TH3.
02862 
02863    if (R__b.IsReading()) {
02864       UInt_t R__s, R__c;
02865       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
02866       if (R__v > 2) {
02867          R__b.ReadClassBuffer(TH3::Class(), this, R__v, R__s, R__c);
02868          return;
02869       }
02870       //====process old versions before automatic schema evolution
02871       TH1::Streamer(R__b);
02872       TAtt3D::Streamer(R__b);
02873       R__b.CheckByteCount(R__s, R__c, TH3::IsA());
02874       //====end of old versions
02875 
02876    } else {
02877       R__b.WriteClassBuffer(TH3::Class(),this);
02878    }
02879 }
02880 
02881 
02882 
02883 //______________________________________________________________________________
02884 //                     TH3C methods
02885 //  TH3C a 3-D histogram with one byte per cell (char)
02886 //______________________________________________________________________________
02887 
02888 ClassImp(TH3C)
02889 
02890 //______________________________________________________________________________
02891 TH3C::TH3C(): TH3(), TArrayC()
02892 {
02893    // Constructor.
02894    SetBinsLength(27);
02895    if (fgDefaultSumw2) Sumw2();
02896 }
02897 
02898 //______________________________________________________________________________
02899 TH3C::~TH3C()
02900 {
02901    // Destructor.
02902 }
02903 
02904 //______________________________________________________________________________
02905 TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
02906            ,Int_t nbinsy,Double_t ylow,Double_t yup
02907            ,Int_t nbinsz,Double_t zlow,Double_t zup)
02908            :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
02909 {
02910    //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
02911    //*-*              ==================================================
02912 
02913    TArrayC::Set(fNcells);
02914    if (fgDefaultSumw2) Sumw2();
02915 
02916    if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
02917 }
02918 
02919 //______________________________________________________________________________
02920 TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
02921            ,Int_t nbinsy,const Float_t *ybins
02922            ,Int_t nbinsz,const Float_t *zbins)
02923            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
02924 {
02925    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
02926    //*-*            =======================================================
02927    TArrayC::Set(fNcells);
02928    if (fgDefaultSumw2) Sumw2();
02929 }
02930 
02931 //______________________________________________________________________________
02932 TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
02933            ,Int_t nbinsy,const Double_t *ybins
02934            ,Int_t nbinsz,const Double_t *zbins)
02935            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
02936 {
02937    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
02938    //*-*            =======================================================
02939    TArrayC::Set(fNcells);
02940    if (fgDefaultSumw2) Sumw2();
02941 }
02942 
02943 //______________________________________________________________________________
02944 TH3C::TH3C(const TH3C &h3c) : TH3(), TArrayC()
02945 {
02946    // Copy constructor.
02947 
02948    ((TH3C&)h3c).Copy(*this);
02949 }
02950 
02951 //______________________________________________________________________________
02952 void TH3C::AddBinContent(Int_t bin)
02953 {
02954    //*-*-*-*-*-*-*-*-*-*Increment bin content by 1*-*-*-*-*-*-*-*-*-*-*-*-*-*
02955    //*-*                ==========================
02956 
02957    if (fArray[bin] < 127) fArray[bin]++;
02958 }
02959 
02960 //______________________________________________________________________________
02961 void TH3C::AddBinContent(Int_t bin, Double_t w)
02962 {
02963    //*-*-*-*-*-*-*-*-*-*Increment bin content by w*-*-*-*-*-*-*-*-*-*-*-*-*-*
02964    //*-*                ==========================
02965 
02966    Int_t newval = fArray[bin] + Int_t(w);
02967    if (newval > -128 && newval < 128) {fArray[bin] = Char_t(newval); return;}
02968    if (newval < -127) fArray[bin] = -127;
02969    if (newval >  127) fArray[bin] =  127;
02970 }
02971 
02972 //______________________________________________________________________________
02973 void TH3C::Copy(TObject &newth3) const
02974 {
02975    //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
02976    //*-*          ===========================================
02977 
02978    TH3::Copy((TH3C&)newth3);
02979 }
02980 
02981 //______________________________________________________________________________
02982 TH1 *TH3C::DrawCopy(Option_t *option) const
02983 {
02984    // Draw copy.
02985 
02986    TString opt = option;
02987    opt.ToLower();
02988    if (gPad && !opt.Contains("same")) gPad->Clear();
02989    TH3C *newth3 = (TH3C*)Clone();
02990    newth3->SetDirectory(0);
02991    newth3->SetBit(kCanDelete);
02992    newth3->AppendPad(option);
02993    return newth3;
02994 }
02995 
02996 //______________________________________________________________________________
02997 Double_t TH3C::GetBinContent(Int_t bin) const
02998 {
02999    // Get bin content.
03000 
03001    if (fBuffer) ((TH3C*)this)->BufferEmpty();
03002    if (bin < 0) bin = 0;
03003    if (bin >= fNcells) bin = fNcells-1;
03004    if (!fArray) return 0;
03005    return Double_t (fArray[bin]);
03006 }
03007 
03008 //______________________________________________________________________________
03009 void TH3C::Reset(Option_t *option)
03010 {
03011    //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
03012    //*-*            ===========================================
03013 
03014    TH3::Reset(option);
03015    TArrayC::Reset();
03016    // should also reset statistics once statistics are implemented for TH3
03017 }
03018 
03019 //______________________________________________________________________________
03020 void TH3C::SetBinsLength(Int_t n)
03021 {
03022    // Set total number of bins including under/overflow
03023    // Reallocate bin contents array
03024 
03025    if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
03026    fNcells = n;
03027    TArrayC::Set(n);
03028 }
03029 
03030 //______________________________________________________________________________
03031 void TH3C::SetBinContent(Int_t bin, Double_t content)
03032 {
03033    // Set bin content
03034    fEntries++;
03035    fTsumw = 0;
03036    if (bin < 0) return;
03037    if (bin >= fNcells) return;
03038    fArray[bin] = Char_t (content);
03039 }
03040 
03041 
03042 //______________________________________________________________________________
03043 void TH3::SetShowProjection(const char *option,Int_t nbins)
03044 {
03045    // When the mouse is moved in a pad containing a 3-d view of this histogram
03046    // a second canvas shows a projection type given as option.
03047    // To stop the generation of the projections, delete the canvas
03048    // containing the projection.
03049    // option may contain a combination of the characters x,y,z,e
03050    // option = "x" return the x projection into a TH1D histogram
03051    // option = "y" return the y projection into a TH1D histogram
03052    // option = "z" return the z projection into a TH1D histogram
03053    // option = "xy" return the x versus y projection into a TH2D histogram
03054    // option = "yx" return the y versus x projection into a TH2D histogram
03055    // option = "xz" return the x versus z projection into a TH2D histogram
03056    // option = "zx" return the z versus x projection into a TH2D histogram
03057    // option = "yz" return the y versus z projection into a TH2D histogram
03058    // option = "zy" return the z versus y projection into a TH2D histogram
03059    // option can also include the drawing option for the projection, eg to draw
03060    // the xy projection using the draw option "box" do
03061    //   myhist.SetShowProjection("xy box");
03062    // This function is typically called from the context menu.
03063    // NB: the notation "a vs b" means "a" vertical and "b" horizontal
03064 
03065    GetPainter();
03066 
03067    if (fPainter) fPainter->SetShowProjection(option,nbins);
03068 }
03069 
03070 //______________________________________________________________________________
03071 void TH3C::Streamer(TBuffer &R__b)
03072 {
03073    // Stream an object of class TH3C.
03074 
03075    if (R__b.IsReading()) {
03076       UInt_t R__s, R__c;
03077       if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
03078       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
03079       if (R__v > 2) {
03080          R__b.ReadClassBuffer(TH3C::Class(), this, R__v, R__s, R__c);
03081          return;
03082       }
03083       //====process old versions before automatic schema evolution
03084       if (R__v < 2) {
03085          R__b.ReadVersion();
03086          TH1::Streamer(R__b);
03087          TArrayC::Streamer(R__b);
03088          R__b.ReadVersion(&R__s, &R__c);
03089          TAtt3D::Streamer(R__b);
03090       } else {
03091          TH3::Streamer(R__b);
03092          TArrayC::Streamer(R__b);
03093          R__b.CheckByteCount(R__s, R__c, TH3C::IsA());
03094       }
03095       //====end of old versions
03096 
03097    } else {
03098       R__b.WriteClassBuffer(TH3C::Class(),this);
03099    }
03100 }
03101 
03102 //______________________________________________________________________________
03103 TH3C& TH3C::operator=(const TH3C &h1)
03104 {
03105    // Operator =
03106 
03107    if (this != &h1)  ((TH3C&)h1).Copy(*this);
03108    return *this;
03109 }
03110 
03111 //______________________________________________________________________________
03112 TH3C operator*(Float_t c1, TH3C &h1)
03113 {
03114    // Operator *
03115 
03116    TH3C hnew = h1;
03117    hnew.Scale(c1);
03118    hnew.SetDirectory(0);
03119    return hnew;
03120 }
03121 
03122 //______________________________________________________________________________
03123 TH3C operator+(TH3C &h1, TH3C &h2)
03124 {
03125    // Operator +
03126 
03127    TH3C hnew = h1;
03128    hnew.Add(&h2,1);
03129    hnew.SetDirectory(0);
03130    return hnew;
03131 }
03132 
03133 //______________________________________________________________________________
03134 TH3C operator-(TH3C &h1, TH3C &h2)
03135 {
03136    // Operator -
03137 
03138    TH3C hnew = h1;
03139    hnew.Add(&h2,-1);
03140    hnew.SetDirectory(0);
03141    return hnew;
03142 }
03143 
03144 //______________________________________________________________________________
03145 TH3C operator*(TH3C &h1, TH3C &h2)
03146 {
03147    // Operator *
03148 
03149    TH3C hnew = h1;
03150    hnew.Multiply(&h2);
03151    hnew.SetDirectory(0);
03152    return hnew;
03153 }
03154 
03155 //______________________________________________________________________________
03156 TH3C operator/(TH3C &h1, TH3C &h2)
03157 {
03158    // Operator /
03159 
03160    TH3C hnew = h1;
03161    hnew.Divide(&h2);
03162    hnew.SetDirectory(0);
03163    return hnew;
03164 }
03165 
03166 
03167 //______________________________________________________________________________
03168 //                     TH3S methods
03169 //  TH3S a 3-D histogram with two bytes per cell (short integer)
03170 //______________________________________________________________________________
03171 
03172 ClassImp(TH3S)
03173 
03174 //______________________________________________________________________________
03175 TH3S::TH3S(): TH3(), TArrayS()
03176 {
03177    // Constructor.
03178    SetBinsLength(27);
03179    if (fgDefaultSumw2) Sumw2();
03180 }
03181 
03182 //______________________________________________________________________________
03183 TH3S::~TH3S()
03184 {
03185    // Destructor.
03186 }
03187 
03188 //______________________________________________________________________________
03189 TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
03190            ,Int_t nbinsy,Double_t ylow,Double_t yup
03191            ,Int_t nbinsz,Double_t zlow,Double_t zup)
03192            :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
03193 {
03194    //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
03195    //*-*              ==================================================
03196    TH3S::Set(fNcells);
03197    if (fgDefaultSumw2) Sumw2();
03198 
03199    if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
03200 }
03201 
03202 //______________________________________________________________________________
03203 TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
03204            ,Int_t nbinsy,const Float_t *ybins
03205            ,Int_t nbinsz,const Float_t *zbins)
03206            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03207 {
03208    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03209    //*-*            =======================================================
03210    TH3S::Set(fNcells);
03211    if (fgDefaultSumw2) Sumw2();
03212 }
03213 
03214 //______________________________________________________________________________
03215 TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
03216            ,Int_t nbinsy,const Double_t *ybins
03217            ,Int_t nbinsz,const Double_t *zbins)
03218            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03219 {
03220    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03221    //*-*            =======================================================
03222    TH3S::Set(fNcells);
03223    if (fgDefaultSumw2) Sumw2();
03224 }
03225 
03226 //______________________________________________________________________________
03227 TH3S::TH3S(const TH3S &h3s) : TH3(), TArrayS()
03228 {
03229    // Copy Constructor.
03230 
03231    ((TH3S&)h3s).Copy(*this);
03232 }
03233 
03234 //______________________________________________________________________________
03235 void TH3S::AddBinContent(Int_t bin)
03236 {
03237    //*-*-*-*-*-*-*-*-*-*Increment bin content by 1*-*-*-*-*-*-*-*-*-*-*-*-*-*
03238    //*-*                ==========================
03239 
03240    if (fArray[bin] < 32767) fArray[bin]++;
03241 }
03242 
03243 //______________________________________________________________________________
03244 void TH3S::AddBinContent(Int_t bin, Double_t w)
03245 {
03246    //*-*-*-*-*-*-*-*-*-*Increment bin content by w*-*-*-*-*-*-*-*-*-*-*-*-*-*
03247    //*-*                ==========================
03248 
03249    Int_t newval = fArray[bin] + Int_t(w);
03250    if (newval > -32768 && newval < 32768) {fArray[bin] = Short_t(newval); return;}
03251    if (newval < -32767) fArray[bin] = -32767;
03252    if (newval >  32767) fArray[bin] =  32767;
03253 }
03254 
03255 //______________________________________________________________________________
03256 void TH3S::Copy(TObject &newth3) const
03257 {
03258    //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
03259    //*-*          ===========================================
03260 
03261    TH3::Copy((TH3S&)newth3);
03262 }
03263 
03264 //______________________________________________________________________________
03265 TH1 *TH3S::DrawCopy(Option_t *option) const
03266 {
03267    // Draw copy.
03268 
03269    TString opt = option;
03270    opt.ToLower();
03271    if (gPad && !opt.Contains("same")) gPad->Clear();
03272    TH3S *newth3 = (TH3S*)Clone();
03273    newth3->SetDirectory(0);
03274    newth3->SetBit(kCanDelete);
03275    newth3->AppendPad(option);
03276    return newth3;
03277 }
03278 
03279 //______________________________________________________________________________
03280 Double_t TH3S::GetBinContent(Int_t bin) const
03281 {
03282    // Get bin content.
03283 
03284    if (fBuffer) ((TH3S*)this)->BufferEmpty();
03285    if (bin < 0) bin = 0;
03286    if (bin >= fNcells) bin = fNcells-1;
03287    if (!fArray) return 0;
03288    return Double_t (fArray[bin]);
03289 }
03290 
03291 //______________________________________________________________________________
03292 void TH3S::Reset(Option_t *option)
03293 {
03294    //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
03295    //*-*            ===========================================
03296 
03297    TH3::Reset(option);
03298    TArrayS::Reset();
03299    // should also reset statistics once statistics are implemented for TH3
03300 }
03301 
03302 //______________________________________________________________________________
03303 void TH3S::SetBinContent(Int_t bin, Double_t content)
03304 {
03305    // Set bin content
03306    fEntries++;
03307    fTsumw = 0;
03308    if (bin < 0) return;
03309    if (bin >= fNcells) return;
03310    fArray[bin] = Short_t (content);
03311 }
03312 
03313 //______________________________________________________________________________
03314 void TH3S::SetBinsLength(Int_t n)
03315 {
03316    // Set total number of bins including under/overflow
03317    // Reallocate bin contents array
03318 
03319    if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
03320    fNcells = n;
03321    TArrayS::Set(n);
03322 }
03323 
03324 //______________________________________________________________________________
03325 void TH3S::Streamer(TBuffer &R__b)
03326 {
03327    // Stream an object of class TH3S.
03328 
03329    if (R__b.IsReading()) {
03330       UInt_t R__s, R__c;
03331       if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
03332       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
03333       if (R__v > 2) {
03334          R__b.ReadClassBuffer(TH3S::Class(), this, R__v, R__s, R__c);
03335          return;
03336       }
03337       //====process old versions before automatic schema evolution
03338       if (R__v < 2) {
03339          R__b.ReadVersion();
03340          TH1::Streamer(R__b);
03341          TArrayS::Streamer(R__b);
03342          R__b.ReadVersion(&R__s, &R__c);
03343          TAtt3D::Streamer(R__b);
03344       } else {
03345          TH3::Streamer(R__b);
03346          TArrayS::Streamer(R__b);
03347          R__b.CheckByteCount(R__s, R__c, TH3S::IsA());
03348       }
03349       //====end of old versions
03350 
03351    } else {
03352       R__b.WriteClassBuffer(TH3S::Class(),this);
03353    }
03354 }
03355 
03356 //______________________________________________________________________________
03357 TH3S& TH3S::operator=(const TH3S &h1)
03358 {
03359    // Operator =
03360 
03361    if (this != &h1)  ((TH3S&)h1).Copy(*this);
03362    return *this;
03363 }
03364 
03365 //______________________________________________________________________________
03366 TH3S operator*(Float_t c1, TH3S &h1)
03367 {
03368    // Operator *
03369 
03370    TH3S hnew = h1;
03371    hnew.Scale(c1);
03372    hnew.SetDirectory(0);
03373    return hnew;
03374 }
03375 
03376 //______________________________________________________________________________
03377 TH3S operator+(TH3S &h1, TH3S &h2)
03378 {
03379    // Operator +
03380 
03381    TH3S hnew = h1;
03382    hnew.Add(&h2,1);
03383    hnew.SetDirectory(0);
03384    return hnew;
03385 }
03386 
03387 //______________________________________________________________________________
03388 TH3S operator-(TH3S &h1, TH3S &h2)
03389 {
03390    // Operator -
03391 
03392    TH3S hnew = h1;
03393    hnew.Add(&h2,-1);
03394    hnew.SetDirectory(0);
03395    return hnew;
03396 }
03397 
03398 //______________________________________________________________________________
03399 TH3S operator*(TH3S &h1, TH3S &h2)
03400 {
03401    // Operator *
03402 
03403    TH3S hnew = h1;
03404    hnew.Multiply(&h2);
03405    hnew.SetDirectory(0);
03406    return hnew;
03407 }
03408 
03409 //______________________________________________________________________________
03410 TH3S operator/(TH3S &h1, TH3S &h2)
03411 {
03412    // Operator /
03413 
03414    TH3S hnew = h1;
03415    hnew.Divide(&h2);
03416    hnew.SetDirectory(0);
03417    return hnew;
03418 }
03419 
03420 
03421 //______________________________________________________________________________
03422 //                     TH3I methods
03423 //  TH3I a 3-D histogram with four bytes per cell (32 bits integer)
03424 //______________________________________________________________________________
03425 
03426 ClassImp(TH3I)
03427 
03428 //______________________________________________________________________________
03429 TH3I::TH3I(): TH3(), TArrayI()
03430 {
03431    // Constructor.
03432    SetBinsLength(27);
03433    if (fgDefaultSumw2) Sumw2();
03434 }
03435 
03436 //______________________________________________________________________________
03437 TH3I::~TH3I()
03438 {
03439    // Destructor.
03440 }
03441 
03442 //______________________________________________________________________________
03443 TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
03444            ,Int_t nbinsy,Double_t ylow,Double_t yup
03445            ,Int_t nbinsz,Double_t zlow,Double_t zup)
03446            :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
03447 {
03448    //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
03449    //*-*              ==================================================
03450    TH3I::Set(fNcells);
03451    if (fgDefaultSumw2) Sumw2();
03452 
03453    if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
03454 }
03455 
03456 //______________________________________________________________________________
03457 TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
03458            ,Int_t nbinsy,const Float_t *ybins
03459            ,Int_t nbinsz,const Float_t *zbins)
03460            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03461 {
03462    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03463    //*-*            =======================================================
03464    TArrayI::Set(fNcells);
03465    if (fgDefaultSumw2) Sumw2();
03466 }
03467 
03468 //______________________________________________________________________________
03469 TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
03470            ,Int_t nbinsy,const Double_t *ybins
03471            ,Int_t nbinsz,const Double_t *zbins)
03472            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03473 {
03474    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03475    //*-*            =======================================================
03476    TArrayI::Set(fNcells);
03477    if (fgDefaultSumw2) Sumw2();
03478 }
03479 
03480 //______________________________________________________________________________
03481 TH3I::TH3I(const TH3I &h3i) : TH3(), TArrayI()
03482 {
03483    // Copy constructor.
03484 
03485    ((TH3I&)h3i).Copy(*this);
03486 }
03487 
03488 //______________________________________________________________________________
03489 void TH3I::AddBinContent(Int_t bin)
03490 {
03491    //*-*-*-*-*-*-*-*-*-*Increment bin content by 1*-*-*-*-*-*-*-*-*-*-*-*-*-*
03492    //*-*                ==========================
03493 
03494    if (fArray[bin] < 2147483647) fArray[bin]++;
03495 }
03496 
03497 //______________________________________________________________________________
03498 void TH3I::AddBinContent(Int_t bin, Double_t w)
03499 {
03500    //*-*-*-*-*-*-*-*-*-*Increment bin content by w*-*-*-*-*-*-*-*-*-*-*-*-*-*
03501    //*-*                ==========================
03502 
03503    Int_t newval = fArray[bin] + Int_t(w);
03504    if (newval > -2147483647 && newval < 2147483647) {fArray[bin] = Int_t(newval); return;}
03505    if (newval < -2147483647) fArray[bin] = -2147483647;
03506    if (newval >  2147483647) fArray[bin] =  2147483647;
03507 }
03508 
03509 //______________________________________________________________________________
03510 void TH3I::Copy(TObject &newth3) const
03511 {
03512    //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
03513    //*-*          ===========================================
03514 
03515    TH3::Copy((TH3I&)newth3);
03516 }
03517 
03518 //______________________________________________________________________________
03519 TH1 *TH3I::DrawCopy(Option_t *option) const
03520 {
03521    // Draw copy.
03522 
03523    TString opt = option;
03524    opt.ToLower();
03525    if (gPad && !opt.Contains("same")) gPad->Clear();
03526    TH3I *newth3 = (TH3I*)Clone();
03527    newth3->SetDirectory(0);
03528    newth3->SetBit(kCanDelete);
03529    newth3->AppendPad(option);
03530    return newth3;
03531 }
03532 
03533 //______________________________________________________________________________
03534 Double_t TH3I::GetBinContent(Int_t bin) const
03535 {
03536    // Get bin content.
03537 
03538    if (fBuffer) ((TH3I*)this)->BufferEmpty();
03539    if (bin < 0) bin = 0;
03540    if (bin >= fNcells) bin = fNcells-1;
03541    if (!fArray) return 0;
03542    return Double_t (fArray[bin]);
03543 }
03544 
03545 //______________________________________________________________________________
03546 void TH3I::Reset(Option_t *option)
03547 {
03548    //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
03549    //*-*            ===========================================
03550 
03551    TH3::Reset(option);
03552    TArrayI::Reset();
03553    // should also reset statistics once statistics are implemented for TH3
03554 }
03555 
03556 //______________________________________________________________________________
03557 void TH3I::SetBinContent(Int_t bin, Double_t content)
03558 {
03559    // Set bin content
03560    fEntries++;
03561    fTsumw = 0;
03562    if (bin < 0) return;
03563    if (bin >= fNcells) return;
03564    fArray[bin] = Int_t (content);
03565 }
03566 
03567 //______________________________________________________________________________
03568 void TH3I::SetBinsLength(Int_t n)
03569 {
03570    // Set total number of bins including under/overflow
03571    // Reallocate bin contents array
03572 
03573    if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
03574    fNcells = n;
03575    TArrayI::Set(n);
03576 }
03577 
03578 //______________________________________________________________________________
03579 TH3I& TH3I::operator=(const TH3I &h1)
03580 {
03581    // Operator =
03582 
03583    if (this != &h1)  ((TH3I&)h1).Copy(*this);
03584    return *this;
03585 }
03586 
03587 //______________________________________________________________________________
03588 TH3I operator*(Float_t c1, TH3I &h1)
03589 {
03590    // Operator *
03591 
03592    TH3I hnew = h1;
03593    hnew.Scale(c1);
03594    hnew.SetDirectory(0);
03595    return hnew;
03596 }
03597 
03598 //______________________________________________________________________________
03599 TH3I operator+(TH3I &h1, TH3I &h2)
03600 {
03601    // Operator +
03602 
03603    TH3I hnew = h1;
03604    hnew.Add(&h2,1);
03605    hnew.SetDirectory(0);
03606    return hnew;
03607 }
03608 
03609 //______________________________________________________________________________
03610 TH3I operator-(TH3I &h1, TH3I &h2)
03611 {
03612    // Operator _
03613 
03614    TH3I hnew = h1;
03615    hnew.Add(&h2,-1);
03616    hnew.SetDirectory(0);
03617    return hnew;
03618 }
03619 
03620 //______________________________________________________________________________
03621 TH3I operator*(TH3I &h1, TH3I &h2)
03622 {
03623    // Operator *
03624 
03625    TH3I hnew = h1;
03626    hnew.Multiply(&h2);
03627    hnew.SetDirectory(0);
03628    return hnew;
03629 }
03630 
03631 //______________________________________________________________________________
03632 TH3I operator/(TH3I &h1, TH3I &h2)
03633 {
03634    // Operator /
03635 
03636    TH3I hnew = h1;
03637    hnew.Divide(&h2);
03638    hnew.SetDirectory(0);
03639    return hnew;
03640 }
03641 
03642 
03643 //______________________________________________________________________________
03644 //                     TH3F methods
03645 //  TH3F a 3-D histogram with four bytes per cell (float)
03646 //______________________________________________________________________________
03647 
03648 ClassImp(TH3F)
03649 
03650 //______________________________________________________________________________
03651 TH3F::TH3F(): TH3(), TArrayF()
03652 {
03653    // Constructor.
03654    SetBinsLength(27);
03655    if (fgDefaultSumw2) Sumw2();
03656 }
03657 
03658 //______________________________________________________________________________
03659 TH3F::~TH3F()
03660 {
03661    // Destructor.
03662 }
03663 
03664 //______________________________________________________________________________
03665 TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
03666            ,Int_t nbinsy,Double_t ylow,Double_t yup
03667            ,Int_t nbinsz,Double_t zlow,Double_t zup)
03668            :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
03669 {
03670    //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
03671    //*-*              ==================================================
03672    TArrayF::Set(fNcells);
03673    if (fgDefaultSumw2) Sumw2();
03674 
03675    if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
03676 }
03677 
03678 //______________________________________________________________________________
03679 TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
03680            ,Int_t nbinsy,const Float_t *ybins
03681            ,Int_t nbinsz,const Float_t *zbins)
03682            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03683 {
03684    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03685    //*-*            =======================================================
03686    TArrayF::Set(fNcells);
03687    if (fgDefaultSumw2) Sumw2();
03688 }
03689 
03690 //______________________________________________________________________________
03691 TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
03692            ,Int_t nbinsy,const Double_t *ybins
03693            ,Int_t nbinsz,const Double_t *zbins)
03694            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03695 {
03696    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03697    //*-*            =======================================================
03698    TArrayF::Set(fNcells);
03699    if (fgDefaultSumw2) Sumw2();
03700 }
03701 
03702 //______________________________________________________________________________
03703 TH3F::TH3F(const TH3F &h3f) : TH3(), TArrayF()
03704 {
03705    // Copy constructor.
03706 
03707    ((TH3F&)h3f).Copy(*this);
03708 }
03709 
03710 //______________________________________________________________________________
03711 void TH3F::Copy(TObject &newth3) const
03712 {
03713    //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
03714    //*-*          ===========================================
03715 
03716    TH3::Copy((TH3F&)newth3);
03717 }
03718 
03719 //______________________________________________________________________________
03720 TH1 *TH3F::DrawCopy(Option_t *option) const
03721 {
03722    // Draw copy.
03723 
03724    TString opt = option;
03725    opt.ToLower();
03726    if (gPad && !opt.Contains("same")) gPad->Clear();
03727    TH3F *newth3 = (TH3F*)Clone();
03728    newth3->SetDirectory(0);
03729    newth3->SetBit(kCanDelete);
03730    newth3->AppendPad(option);
03731    return newth3;
03732 }
03733 
03734 //______________________________________________________________________________
03735 Double_t TH3F::GetBinContent(Int_t bin) const
03736 {
03737    // Get bin content.
03738 
03739    if (fBuffer) ((TH3F*)this)->BufferEmpty();
03740    if (bin < 0) bin = 0;
03741    if (bin >= fNcells) bin = fNcells-1;
03742    if (!fArray) return 0;
03743    return Double_t (fArray[bin]);
03744 }
03745 
03746 //______________________________________________________________________________
03747 void TH3F::Reset(Option_t *option)
03748 {
03749    //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
03750    //*-*            ===========================================
03751 
03752    TH3::Reset(option);
03753    TArrayF::Reset();
03754    // should also reset statistics once statistics are implemented for TH3
03755 }
03756 
03757 //______________________________________________________________________________
03758 void TH3F::SetBinContent(Int_t bin, Double_t content)
03759 {
03760    // Set bin content
03761    fEntries++;
03762    fTsumw = 0;
03763    if (bin < 0) return;
03764    if (bin >= fNcells) return;
03765    fArray[bin] = Float_t (content);
03766 }
03767 
03768 //______________________________________________________________________________
03769 void TH3F::SetBinsLength(Int_t n)
03770 {
03771    // Set total number of bins including under/overflow
03772    // Reallocate bin contents array
03773 
03774    if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
03775    fNcells = n;
03776    TArrayF::Set(n);
03777 }
03778 
03779 //______________________________________________________________________________
03780 void TH3F::Streamer(TBuffer &R__b)
03781 {
03782    // Stream an object of class TH3F.
03783 
03784    if (R__b.IsReading()) {
03785       UInt_t R__s, R__c;
03786       if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
03787       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
03788       if (R__v > 2) {
03789          R__b.ReadClassBuffer(TH3F::Class(), this, R__v, R__s, R__c);
03790          return;
03791       }
03792       //====process old versions before automatic schema evolution
03793       if (R__v < 2) {
03794          R__b.ReadVersion();
03795          TH1::Streamer(R__b);
03796          TArrayF::Streamer(R__b);
03797          R__b.ReadVersion(&R__s, &R__c);
03798          TAtt3D::Streamer(R__b);
03799       } else {
03800          TH3::Streamer(R__b);
03801          TArrayF::Streamer(R__b);
03802          R__b.CheckByteCount(R__s, R__c, TH3F::IsA());
03803       }
03804       //====end of old versions
03805 
03806    } else {
03807       R__b.WriteClassBuffer(TH3F::Class(),this);
03808    }
03809 }
03810 
03811 //______________________________________________________________________________
03812 TH3F& TH3F::operator=(const TH3F &h1)
03813 {
03814    // Operator =
03815 
03816    if (this != &h1)  ((TH3F&)h1).Copy(*this);
03817    return *this;
03818 }
03819 
03820 //______________________________________________________________________________
03821 TH3F operator*(Float_t c1, TH3F &h1)
03822 {
03823    // Operator *
03824 
03825    TH3F hnew = h1;
03826    hnew.Scale(c1);
03827    hnew.SetDirectory(0);
03828    return hnew;
03829 }
03830 
03831 //______________________________________________________________________________
03832 TH3F operator+(TH3F &h1, TH3F &h2)
03833 {
03834    // Operator +
03835 
03836    TH3F hnew = h1;
03837    hnew.Add(&h2,1);
03838    hnew.SetDirectory(0);
03839    return hnew;
03840 }
03841 
03842 //______________________________________________________________________________
03843 TH3F operator-(TH3F &h1, TH3F &h2)
03844 {
03845    // Operator -
03846 
03847    TH3F hnew = h1;
03848    hnew.Add(&h2,-1);
03849    hnew.SetDirectory(0);
03850    return hnew;
03851 }
03852 
03853 //______________________________________________________________________________
03854 TH3F operator*(TH3F &h1, TH3F &h2)
03855 {
03856    // Operator *
03857 
03858    TH3F hnew = h1;
03859    hnew.Multiply(&h2);
03860    hnew.SetDirectory(0);
03861    return hnew;
03862 }
03863 
03864 //______________________________________________________________________________
03865 TH3F operator/(TH3F &h1, TH3F &h2)
03866 {
03867    // Operator /
03868 
03869    TH3F hnew = h1;
03870    hnew.Divide(&h2);
03871    hnew.SetDirectory(0);
03872    return hnew;
03873 }
03874 
03875 
03876 //______________________________________________________________________________
03877 //                     TH3D methods
03878 //  TH3D a 3-D histogram with eight bytes per cell (double)
03879 //______________________________________________________________________________
03880 
03881 ClassImp(TH3D)
03882 
03883 //______________________________________________________________________________
03884 TH3D::TH3D(): TH3(), TArrayD()
03885 {
03886    // Constructor.
03887    SetBinsLength(27);
03888    if (fgDefaultSumw2) Sumw2();
03889 }
03890 
03891 //______________________________________________________________________________
03892 TH3D::~TH3D()
03893 {
03894    // Destructor.
03895 }
03896 
03897 //______________________________________________________________________________
03898 TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
03899            ,Int_t nbinsy,Double_t ylow,Double_t yup
03900            ,Int_t nbinsz,Double_t zlow,Double_t zup)
03901            :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
03902 {
03903    //*-*-*-*-*-*-*-*-*Normal constructor for fix bin size 3-D histograms*-*-*-*-*
03904    //*-*              ==================================================
03905    TArrayD::Set(fNcells);
03906    if (fgDefaultSumw2) Sumw2();
03907 
03908    if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
03909 }
03910 
03911 //______________________________________________________________________________
03912 TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
03913            ,Int_t nbinsy,const Float_t *ybins
03914            ,Int_t nbinsz,const Float_t *zbins)
03915            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03916 {
03917    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03918    //*-*            =======================================================
03919    TArrayD::Set(fNcells);
03920    if (fgDefaultSumw2) Sumw2();
03921 }
03922 
03923 //______________________________________________________________________________
03924 TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
03925            ,Int_t nbinsy,const Double_t *ybins
03926            ,Int_t nbinsz,const Double_t *zbins)
03927            :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
03928 {
03929    //*-*-*-*-*-*-*-*Normal constructor for variable bin size 3-D histograms*-*-*-*
03930    //*-*            =======================================================
03931    TArrayD::Set(fNcells);
03932    if (fgDefaultSumw2) Sumw2();
03933 }
03934 
03935 //______________________________________________________________________________
03936 TH3D::TH3D(const TH3D &h3d) : TH3(), TArrayD()
03937 {
03938    // Copy constructor.
03939 
03940    ((TH3D&)h3d).Copy(*this);
03941 }
03942 
03943 //______________________________________________________________________________
03944 void TH3D::Copy(TObject &newth3) const
03945 {
03946    //*-*-*-*-*-*-*Copy this 3-D histogram structure to newth3*-*-*-*-*-*-*-*-*-*
03947    //*-*          ===========================================
03948 
03949    TH3::Copy((TH3D&)newth3);
03950 }
03951 
03952 //______________________________________________________________________________
03953 TH1 *TH3D::DrawCopy(Option_t *option) const
03954 {
03955    // Draw copy.
03956 
03957    TString opt = option;
03958    opt.ToLower();
03959    if (gPad && !opt.Contains("same")) gPad->Clear();
03960    TH3D *newth3 = (TH3D*)Clone();
03961    newth3->SetDirectory(0);
03962    newth3->SetBit(kCanDelete);
03963    newth3->AppendPad(option);
03964    return newth3;
03965 }
03966 
03967 //______________________________________________________________________________
03968 Double_t TH3D::GetBinContent(Int_t bin) const
03969 {
03970    // Get bin content.
03971 
03972    if (fBuffer) ((TH3D*)this)->BufferEmpty();
03973    if (bin < 0) bin = 0;
03974    if (bin >= fNcells) bin = fNcells-1;
03975    if (!fArray) return 0;
03976    return Double_t (fArray[bin]);
03977 }
03978 
03979 //______________________________________________________________________________
03980 void TH3D::Reset(Option_t *option)
03981 {
03982    //*-*-*-*-*-*-*-*Reset this histogram: contents, errors, etc*-*-*-*-*-*-*-*
03983    //*-*            ===========================================
03984 
03985    TH3::Reset(option);
03986    TArrayD::Reset();
03987    // should also reset statistics once statistics are implemented for TH3
03988 }
03989 
03990 //______________________________________________________________________________
03991 void TH3D::SetBinContent(Int_t bin, Double_t content)
03992 {
03993    // Set bin content
03994    fEntries++;
03995    fTsumw = 0;
03996    if (bin < 0) return;
03997    if (bin >= fNcells) return;
03998    fArray[bin] = Double_t (content);
03999 }
04000 
04001 
04002 //______________________________________________________________________________
04003 void TH3D::SetBinsLength(Int_t n)
04004 {
04005    // Set total number of bins including under/overflow
04006    // Reallocate bin contents array
04007 
04008    if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
04009    fNcells = n;
04010    TArrayD::Set(n);
04011 }
04012 
04013 //______________________________________________________________________________
04014 void TH3D::Streamer(TBuffer &R__b)
04015 {
04016    // Stream an object of class TH3D.
04017 
04018    if (R__b.IsReading()) {
04019       UInt_t R__s, R__c;
04020       if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
04021       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
04022       if (R__v > 2) {
04023          R__b.ReadClassBuffer(TH3D::Class(), this, R__v, R__s, R__c);
04024          return;
04025       }
04026       //====process old versions before automatic schema evolution
04027       if (R__v < 2) {
04028          R__b.ReadVersion();
04029          TH1::Streamer(R__b);
04030          TArrayD::Streamer(R__b);
04031          R__b.ReadVersion(&R__s, &R__c);
04032          TAtt3D::Streamer(R__b);
04033       } else {
04034          TH3::Streamer(R__b);
04035          TArrayD::Streamer(R__b);
04036          R__b.CheckByteCount(R__s, R__c, TH3D::IsA());
04037       }
04038       //====end of old versions
04039 
04040    } else {
04041       R__b.WriteClassBuffer(TH3D::Class(),this);
04042    }
04043 }
04044 
04045 //______________________________________________________________________________
04046 TH3D& TH3D::operator=(const TH3D &h1)
04047 {
04048    // Operator =
04049 
04050    if (this != &h1)  ((TH3D&)h1).Copy(*this);
04051    return *this;
04052 }
04053 
04054 //______________________________________________________________________________
04055 TH3D operator*(Float_t c1, TH3D &h1)
04056 {
04057    // Operator *
04058 
04059    TH3D hnew = h1;
04060    hnew.Scale(c1);
04061    hnew.SetDirectory(0);
04062    return hnew;
04063 }
04064 
04065 //______________________________________________________________________________
04066 TH3D operator+(TH3D &h1, TH3D &h2)
04067 {
04068    // Operator +
04069 
04070    TH3D hnew = h1;
04071    hnew.Add(&h2,1);
04072    hnew.SetDirectory(0);
04073    return hnew;
04074 }
04075 
04076 //______________________________________________________________________________
04077 TH3D operator-(TH3D &h1, TH3D &h2)
04078 {
04079    // Operator -
04080 
04081    TH3D hnew = h1;
04082    hnew.Add(&h2,-1);
04083    hnew.SetDirectory(0);
04084    return hnew;
04085 }
04086 
04087 //______________________________________________________________________________
04088 TH3D operator*(TH3D &h1, TH3D &h2)
04089 {
04090    // Operator *
04091 
04092    TH3D hnew = h1;
04093    hnew.Multiply(&h2);
04094    hnew.SetDirectory(0);
04095    return hnew;
04096 }
04097 
04098 //______________________________________________________________________________
04099 TH3D operator/(TH3D &h1, TH3D &h2)
04100 {
04101    // Operator /
04102 
04103    TH3D hnew = h1;
04104    hnew.Divide(&h2);
04105    hnew.SetDirectory(0);
04106    return hnew;
04107 }

Generated on Tue Jul 5 14:24:20 2011 for ROOT_528-00b_version by  doxygen 1.5.1