TH2.cxx

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

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