TProfile2D.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TProfile2D.cxx 38022 2011-02-09 16:12:32Z moneta $
00002 // Author: Rene Brun   16/04/2000
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 "TProfile2D.h"
00013 #include "TMath.h"
00014 #include "THLimitsFinder.h"
00015 #include "Riostream.h"
00016 #include "TVirtualPad.h"
00017 #include "TError.h"
00018 #include "TClass.h"
00019 
00020 #include "TProfileHelper.h"
00021 
00022 Bool_t TProfile2D::fgApproximate = kFALSE;
00023 
00024 ClassImp(TProfile2D)
00025 
00026 //______________________________________________________________________________
00027 //
00028 //  Profile2D histograms are used to display the mean
00029 //  value of Z and its RMS for each cell in X,Y.
00030 //  Profile2D histograms are in many cases an
00031 //  elegant replacement of three-dimensional histograms : the inter-relation of three
00032 //  measured quantities X, Y and Z can always be visualized by a three-dimensional
00033 //  histogram or scatter-plot; its representation on the line-printer is not particularly
00034 //  satisfactory, except for sparse data. If Z is an unknown (but single-valued)
00035 //  approximate function of X,Y this function is displayed by a profile2D histogram with
00036 //  much better precision than by a scatter-plot.
00037 //
00038 //  The following formulae show the cumulated contents (capital letters) and the values
00039 //  displayed by the printing or plotting routines (small letters) of the elements for cell I, J.
00040 //
00041 //                                                        2
00042 //      H(I,J)  =  sum Z                  E(I,J)  =  sum Z
00043 //      l(I,J)  =  sum l                  L(I,J)  =  sum l
00044 //      h(I,J)  =  H(I,J)/L(I,J)          s(I,J)  =  sqrt(E(I,J)/L(I,J)- h(I,J)**2)
00045 //      e(I,J)  =  s(I,J)/sqrt(L(I,J))
00046 //
00047 //  In the special case where s(I,J) is zero (eg, case of 1 entry only in one cell)
00048 //  e(I,J) is computed from the average of the s(I,J) for all cells.
00049 //  This simple/crude approximation was suggested in order to keep the cell
00050 //  during a fit operation.
00051 //
00052 //           Example of a profile2D histogram
00053 //{
00054 //  TCanvas *c1 = new TCanvas("c1","Profile histogram example",200,10,700,500);
00055 //  hprof2d  = new TProfile2D("hprof2d","Profile of pz versus px and py",40,-4,4,40,-4,4,0,20);
00056 //  Float_t px, py, pz;
00057 //  for ( Int_t i=0; i<25000; i++) {
00058 //     gRandom->Rannor(px,py);
00059 //     pz = px*px + py*py;
00060 //     hprof2d->Fill(px,py,pz,1);
00061 //  }
00062 //  hprof2d->Draw();
00063 //}
00064 //
00065 
00066 //______________________________________________________________________________
00067 TProfile2D::TProfile2D() : TH2D()
00068 {
00069 //*-*-*-*-*-*Default constructor for Profile2D histograms*-*-*-*-*-*-*-*-*
00070 //*-*        ============================================
00071    fTsumwz = fTsumwz2 = 0;
00072    fScaling = kFALSE;
00073    BuildOptions(0,0,"");
00074 }
00075 
00076 //______________________________________________________________________________
00077 TProfile2D::~TProfile2D()
00078 {
00079 //*-*-*-*-*-*Default destructor for Profile2D histograms*-*-*-*-*-*-*-*-*
00080 //*-*        ===========================================
00081 
00082 }
00083 
00084 //______________________________________________________________________________
00085 TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,Double_t ylow,Double_t yup,Option_t *option)
00086     : TH2D(name,title,nx,xlow,xup,ny,ylow,yup)
00087 {
00088 //*-*-*-*-*-*Normal Constructor for Profile histograms*-*-*-*-*-*-*-*-*-*
00089 //*-*        ==========================================
00090 //
00091 //  The first eight parameters are similar to TH2D::TH2D.
00092 //  All values of z are accepted at filling time.
00093 //  To fill a profile2D histogram, one must use TProfile2D::Fill function.
00094 //
00095 //  Note that when filling the profile histogram the function Fill
00096 //  checks if the variable z is betyween fZmin and fZmax.
00097 //  If a minimum or maximum value is set for the Z scale before filling,
00098 //  then all values below zmin or above zmax will be discarded.
00099 //  Setting the minimum or maximum value for the Z scale before filling
00100 //  has the same effect as calling the special TProfile2D constructor below
00101 //  where zmin and zmax are specified.
00102 //
00103 //  H(I,J) is printed as the cell contents. The errors computed are s(I,J) if CHOPT='S'
00104 //  (spread option), or e(I,J) if CHOPT=' ' (error on mean).
00105 //
00106 //        See TProfile2D::BuildOptions for explanation of parameters
00107 //
00108 //   see other constructors below with all possible combinations of
00109 //   fix and variable bin size like in TH2D.
00110 
00111    BuildOptions(0,0,option);
00112    if (xlow >= xup || ylow >= yup) SetBuffer(fgBufferSize);
00113 }
00114 
00115 //______________________________________________________________________________
00116 TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,Double_t ylow,Double_t yup,Option_t *option)
00117     : TH2D(name,title,nx,xbins,ny,ylow,yup)
00118 {
00119 //  Create a 2-D Profile with variable bins in X and fix bins in Y
00120 
00121    BuildOptions(0,0,option);
00122 }
00123 
00124 //______________________________________________________________________________
00125 TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,const Double_t *ybins,Option_t *option)
00126     : TH2D(name,title,nx,xlow,xup,ny,ybins)
00127 {
00128 //  Create a 2-D Profile with fix bins in X and variable bins in Y
00129 
00130    BuildOptions(0,0,option);
00131 }
00132 
00133 //______________________________________________________________________________
00134 TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,const Double_t *ybins,Option_t *option)
00135     : TH2D(name,title,nx,xbins,ny,ybins)
00136 {
00137 //  Create a 2-D Profile with variable bins in X and variable bins in Y
00138 
00139    BuildOptions(0,0,option);
00140 }
00141 
00142 
00143 //______________________________________________________________________________
00144 TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny, Double_t ylow,Double_t yup,Double_t zlow,Double_t zup,Option_t *option)
00145     : TH2D(name,title,nx,xlow,xup,ny,ylow,yup)
00146 {
00147 //*-*-*-*-*-*Constructor for Profile2D histograms with range in z*-*-*-*-*-*
00148 //*-*        ====================================================
00149 //  The first eight parameters are similar to TH2D::TH2D.
00150 //  Only the values of Z between ZMIN and ZMAX will be considered at filling time.
00151 //  zmin and zmax will also be the maximum and minimum values
00152 //  on the z scale when drawing the profile2D.
00153 //
00154 //        See TProfile2D::BuildOptions for more explanations on errors
00155 //
00156 
00157    BuildOptions(zlow,zup,option);
00158    if (xlow >= xup || ylow >= yup) SetBuffer(fgBufferSize);
00159 }
00160 
00161 
00162 //______________________________________________________________________________
00163 void TProfile2D::BuildOptions(Double_t zmin, Double_t zmax, Option_t *option)
00164 {
00165 //*-*-*-*-*-*-*Set Profile2D histogram structure and options*-*-*-*-*-*-*-*-*
00166 //*-*          =============================================
00167 //
00168 //    If a cell has N data points all with the same value Z (especially
00169 //    possible when dealing with integers), the spread in Z for that cell
00170 //    is zero, and the uncertainty assigned is also zero, and the cell is
00171 //    ignored in making subsequent fits. If SQRT(Z) was the correct error
00172 //    in the case above, then SQRT(Z)/SQRT(N) would be the correct error here.
00173 //    In fact, any cell with non-zero number of entries N but with zero spread
00174 //    should have an uncertainty SQRT(Z)/SQRT(N).
00175 //
00176 //    Now, is SQRT(Z)/SQRT(N) really the correct uncertainty?
00177 //    that it is only in the case where the Z variable is some sort
00178 //    of counting statistics, following a Poisson distribution. This should
00179 //    probably be set as the default case. However, Z can be any variable
00180 //    from an original NTUPLE, not necessarily distributed "Poissonly".
00181 //    The computation of errors is based on the parameter option:
00182 //    option:
00183 //     ' '  (Default) Errors are Spread/SQRT(N) for Spread.ne.0. ,
00184 //                      "     "  SQRT(Z)/SQRT(N) for Spread.eq.0,N.gt.0 ,
00185 //                      "     "  0.  for N.eq.0
00186 //     's'            Errors are Spread  for Spread.ne.0. ,
00187 //                      "     "  SQRT(Z)  for Spread.eq.0,N.gt.0 ,
00188 //                      "     "  0.  for N.eq.0
00189 //     'i'            Errors are Spread/SQRT(N) for Spread.ne.0. ,
00190 //                      "     "  1./SQRT(12.*N) for Spread.eq.0,N.gt.0 ,
00191 //                      "     "  0.  for N.eq.0
00192 //
00193 //    The third case above corresponds to Integer Z values for which the
00194 //    uncertainty is +-0.5, with the assumption that the probability that Z
00195 //    takes any value between Z-0.5 and Z+0.5 is uniform (the same argument
00196 //    goes for Z uniformly distributed between Z and Z+1); this would be
00197 //    useful if Z is an ADC measurement, for example. Other, fancier options
00198 //    would be possible, at the cost of adding one more parameter to the PROFILE2D
00199 //    For example, if all Z variables are distributed according to some
00200 //    known Gaussian of standard deviation Sigma, then:
00201 //     'G'            Errors are Spread/SQRT(N) for Spread.ne.0. ,
00202 //                      "     "  Sigma/SQRT(N) for Spread.eq.0,N.gt.0 ,
00203 //                      "     "  0.  for N.eq.0
00204 //    For example, this would be useful when all Z's are experimental quantities
00205 //    measured with the same instrument with precision Sigma.
00206 //
00207 //
00208 
00209    SetErrorOption(option);
00210 
00211    fBinEntries.Set(fNcells);  //*-* create number of entries per cell array
00212 
00213    TH1::Sumw2();                   //*-* create sum of squares of weights array times y
00214    if (fgDefaultSumw2) Sumw2();    // optionally create sum of squares of weights
00215 
00216    fZmin = zmin;
00217    fZmax = zmax;
00218    fScaling = kFALSE;
00219    fTsumwz  = fTsumwz2 = 0;
00220 }
00221 
00222 //______________________________________________________________________________
00223 TProfile2D::TProfile2D(const TProfile2D &profile) : TH2D()
00224 {
00225    // Copy constructor.
00226 
00227    ((TProfile2D&)profile).Copy(*this);
00228 }
00229 
00230 
00231 //______________________________________________________________________________
00232 void TProfile2D::Add(TF1 *, Double_t , Option_t*)
00233 {
00234    // Performs the operation: this = this + c1*f1
00235 
00236    Error("Add","Function not implemented for TProfile2D");
00237    return;
00238 }
00239 
00240 
00241 //______________________________________________________________________________
00242 void TProfile2D::Add(const TH1 *h1, Double_t c1)
00243 {
00244    // Performs the operation: this = this + c1*h1
00245 
00246    if (!h1) {
00247       Error("Add","Attempt to add a non-existing profile");
00248       return;
00249    }
00250    if (!h1->InheritsFrom(TProfile2D::Class())) {
00251       Error("Add","Attempt to add a non-profile2D object");
00252       return;
00253    }
00254 
00255    TProfileHelper::Add(this, this, h1, 1, c1);
00256 }
00257 
00258 //______________________________________________________________________________
00259 void TProfile2D::Add(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2)
00260 {
00261 //*-*-*-*-*Replace contents of this profile2D by the addition of h1 and h2*-*-*
00262 //*-*      ===============================================================
00263 //
00264 //   this = c1*h1 + c2*h2
00265 //
00266 
00267    if (!h1 || !h2) {
00268       Error("Add","Attempt to add a non-existing profile");
00269       return;
00270    }
00271    if (!h1->InheritsFrom(TProfile2D::Class())) {
00272       Error("Add","Attempt to add a non-profile2D object");
00273       return;
00274    }
00275    if (!h2->InheritsFrom(TProfile2D::Class())) {
00276       Error("Add","Attempt to add a non-profile2D object");
00277       return;
00278    }
00279    TProfileHelper::Add(this, h1, h2, c1, c2);
00280 }
00281 
00282 
00283 //______________________________________________________________________________
00284 void TProfile2D::Approximate(Bool_t approx)
00285 {
00286 //     static function
00287 // set the fgApproximate flag. When the flag is true, the function GetBinError
00288 // will approximate the bin error with the average profile error on all bins
00289 // in the following situation only
00290 //  - the number of bins in the profile2D is less than 10404 (eg 100x100)
00291 //  - the bin number of entries is small ( <5)
00292 //  - the estimated bin error is extremely small compared to the bin content
00293 //  (see TProfile2D::GetBinError)
00294 
00295    fgApproximate = approx;
00296 }
00297 
00298 
00299 //______________________________________________________________________________
00300 Int_t TProfile2D::BufferEmpty(Int_t action)
00301 {
00302 // Fill histogram with all entries in the buffer.
00303 // action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
00304 // action =  0 histogram is filled from the buffer
00305 // action =  1 histogram is filled and buffer is deleted
00306 //             The buffer is automatically deleted when the number of entries
00307 //             in the buffer is greater than the number of entries in the histogram
00308 
00309    // do we need to compute the bin size?
00310    if (!fBuffer) return 0;
00311    Int_t nbentries = (Int_t)fBuffer[0];
00312    if (!nbentries) return 0;
00313    Double_t *buffer = fBuffer;
00314    if (nbentries < 0) {
00315       if (action == 0) return 0;
00316       nbentries  = -nbentries;
00317       fBuffer=0;
00318       Reset();
00319       fBuffer = buffer;
00320    }
00321    if (TestBit(kCanRebin) || fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
00322       //find min, max of entries in buffer
00323       Double_t xmin = fBuffer[2];
00324       Double_t xmax = xmin;
00325       Double_t ymin = fBuffer[3];
00326       Double_t ymax = ymin;
00327       for (Int_t i=1;i<nbentries;i++) {
00328          Double_t x = fBuffer[4*i+2];
00329          if (x < xmin) xmin = x;
00330          if (x > xmax) xmax = x;
00331          Double_t y = fBuffer[4*i+3];
00332          if (y < ymin) ymin = y;
00333          if (y > ymax) ymax = y;
00334       }
00335       if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
00336          THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax,ymin,ymax);
00337       } else {
00338          fBuffer = 0;
00339          Int_t keep = fBufferSize; fBufferSize = 0;
00340          if (xmin <  fXaxis.GetXmin()) RebinAxis(xmin,&fXaxis);
00341          if (xmax >= fXaxis.GetXmax()) RebinAxis(xmax,&fXaxis);
00342          if (ymin <  fYaxis.GetXmin()) RebinAxis(ymin,&fYaxis);
00343          if (ymax >= fYaxis.GetXmax()) RebinAxis(ymax,&fYaxis);
00344          fBuffer = buffer;
00345          fBufferSize = keep;
00346       }
00347    }
00348 
00349    fBuffer = 0;
00350    for (Int_t i=0;i<nbentries;i++) {
00351       Fill(buffer[4*i+2],buffer[4*i+3],buffer[4*i+4],buffer[4*i+1]);
00352    }
00353    fBuffer = buffer;
00354 
00355    if (action > 0) { delete [] fBuffer; fBuffer = 0; fBufferSize = 0;}
00356    else {
00357       if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
00358       else                              fBuffer[0] = 0;
00359    }
00360    return nbentries;
00361 }
00362 
00363 //______________________________________________________________________________
00364 Int_t TProfile2D::BufferFill(Double_t x, Double_t y, Double_t z, Double_t w)
00365 {
00366 // accumulate arguments in buffer. When buffer is full, empty the buffer
00367 // fBuffer[0] = number of entries in buffer
00368 // fBuffer[1] = w of first entry
00369 // fBuffer[2] = x of first entry
00370 // fBuffer[3] = y of first entry
00371 // fBuffer[4] = z of first entry
00372 
00373    if (!fBuffer) return -3;
00374    Int_t nbentries = (Int_t)fBuffer[0];
00375    if (nbentries < 0) {
00376       nbentries  = -nbentries;
00377       fBuffer[0] =  nbentries;
00378       if (fEntries > 0) {
00379          Double_t *buffer = fBuffer; fBuffer=0;
00380          Reset();
00381          fBuffer = buffer;
00382       }
00383    }
00384    if (4*nbentries+4 >= fBufferSize) {
00385       BufferEmpty(1);
00386       return Fill(x,y,z,w);
00387    }
00388    fBuffer[4*nbentries+1] = w;
00389    fBuffer[4*nbentries+2] = x;
00390    fBuffer[4*nbentries+3] = y;
00391    fBuffer[4*nbentries+4] = z;
00392    fBuffer[0] += 1;
00393    return -2;
00394 }
00395 
00396 //______________________________________________________________________________
00397 void TProfile2D::Copy(TObject &obj) const
00398 {
00399 //*-*-*-*-*-*-*-*Copy a Profile2D histogram to a new profile2D histogram*-*-*-*
00400 //*-*            =======================================================
00401 
00402    TH2D::Copy(((TProfile2D&)obj));
00403    fBinEntries.Copy(((TProfile2D&)obj).fBinEntries);
00404    fBinSumw2.Copy(((TProfile2D&)obj).fBinSumw2);
00405    for (int bin=0;bin<fNcells;bin++) {
00406       ((TProfile2D&)obj).fArray[bin]        = fArray[bin];
00407       ((TProfile2D&)obj).fSumw2.fArray[bin] = fSumw2.fArray[bin];
00408    }
00409    ((TProfile2D&)obj).fZmin = fZmin;
00410    ((TProfile2D&)obj).fZmax = fZmax;
00411    ((TProfile2D&)obj).fScaling   = fScaling;
00412    ((TProfile2D&)obj).fErrorMode = fErrorMode;
00413    ((TProfile2D&)obj).fTsumwz    = fTsumwz;
00414    ((TProfile2D&)obj).fTsumwz2   = fTsumwz2;
00415 }
00416 
00417 
00418 //______________________________________________________________________________
00419 void TProfile2D::Divide(TF1 *, Double_t )
00420 {
00421    // Performs the operation: this = this/(c1*f1)
00422 
00423    Error("Divide","Function not implemented for TProfile2D");
00424    return;
00425 }
00426 
00427 //______________________________________________________________________________
00428 void TProfile2D::Divide(const TH1 *h1)
00429 {
00430 //*-*-*-*-*-*-*-*-*-*-*Divide this profile2D by h1*-*-*-*-*-*-*-*-*-*-*-*-*
00431 //*-*                  ===========================
00432 //
00433 //   this = this/h1
00434 //
00435 
00436    if (!h1) {
00437       Error("Divide","Attempt to divide a non-existing profile2D");
00438       return;
00439    }
00440    if (!h1->InheritsFrom(TProfile2D::Class())) {
00441       Error("Divide","Attempt to divide a non-profile2D object");
00442       return;
00443    }
00444    TProfile2D *p1 = (TProfile2D*)h1;
00445 
00446 //*-*- Check profile compatibility
00447    Int_t nx = GetNbinsX();
00448    if (nx != p1->GetNbinsX()) {
00449       Error("Divide","Attempt to divide profiles with different number of bins");
00450       return;
00451    }
00452    Int_t ny = GetNbinsY();
00453    if (ny != p1->GetNbinsY()) {
00454       Error("Divide","Attempt to divide profiles with different number of bins");
00455       return;
00456    }
00457 
00458 //*-*- Reset statistics
00459    fEntries = fTsumw   = fTsumw2 = fTsumwx = fTsumwx2 = 0;
00460 
00461 //*-*- Loop on bins (including underflows/overflows)
00462    Int_t bin,binx,biny;
00463    Double_t *cu1 = p1->GetW();
00464    Double_t *er1 = p1->GetW2();
00465    Double_t *en1 = p1->GetB();
00466    Double_t c0,c1,w,z,x,y;
00467    for (binx =0;binx<=nx+1;binx++) {
00468       for (biny =0;biny<=ny+1;biny++) {
00469          bin   = biny*(fXaxis.GetNbins()+2) + binx;
00470          c0  = fArray[bin];
00471          c1  = cu1[bin];
00472          if (c1) w = c0/c1;
00473          else    w = 0;
00474          fArray[bin] = w;
00475          z = TMath::Abs(w);
00476          x = fXaxis.GetBinCenter(binx);
00477          y = fYaxis.GetBinCenter(biny);
00478          fEntries++;
00479          fTsumw   += z;
00480          fTsumw2  += z*z;
00481          fTsumwx  += z*x;
00482          fTsumwx2 += z*x*x;
00483          fTsumwy  += z*y;
00484          fTsumwy2 += z*y*y;
00485          fTsumwxy += z*x*y;
00486          fTsumwz  += z;
00487          fTsumwz2 += z*z;
00488          Double_t e0 = fSumw2.fArray[bin];
00489          Double_t e1 = er1[bin];
00490          Double_t c12= c1*c1;
00491          if (!c1) fSumw2.fArray[bin] = 0;
00492          else     fSumw2.fArray[bin] = (e0*c1*c1 + e1*c0*c0)/(c12*c12);
00493          if (!en1[bin]) fBinEntries.fArray[bin] = 0;
00494          else           fBinEntries.fArray[bin] /= en1[bin];
00495       }
00496    }
00497    // mantaining the correct sum of weights square is not supported when dividing
00498    // bin error resulting from division of profile needs to be checked 
00499    if (fBinSumw2.fN) { 
00500       Warning("Divide","Cannot preserve during the division of profiles the sum of bin weight square");
00501       fBinSumw2 = TArrayD();
00502    }
00503 }
00504 
00505 
00506 //______________________________________________________________________________
00507 void TProfile2D::Divide(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2, Option_t *option)
00508 {
00509 //*-*-*-*-*Replace contents of this profile2D by the division of h1 by h2*-*-*
00510 //*-*      ==============================================================
00511 //
00512 //   this = c1*h1/(c2*h2)
00513 //
00514 
00515    TString opt = option;
00516    opt.ToLower();
00517    Bool_t binomial = kFALSE;
00518    if (opt.Contains("b")) binomial = kTRUE;
00519    if (!h1 || !h2) {
00520       Error("Divide","Attempt to divide a non-existing profile2D");
00521       return;
00522    }
00523    if (!h1->InheritsFrom(TProfile2D::Class())) {
00524       Error("Divide","Attempt to divide a non-profile2D object");
00525       return;
00526    }
00527    TProfile2D *p1 = (TProfile2D*)h1;
00528    if (!h2->InheritsFrom(TProfile2D::Class())) {
00529       Error("Divide","Attempt to divide a non-profile2D object");
00530       return;
00531    }
00532    TProfile2D *p2 = (TProfile2D*)h2;
00533 
00534 //*-*- Check histogram compatibility
00535    Int_t nx = GetNbinsX();
00536    if (nx != p1->GetNbinsX() || nx != p2->GetNbinsX()) {
00537       Error("Divide","Attempt to divide profiles with different number of bins");
00538       return;
00539    }
00540    Int_t ny = GetNbinsY();
00541    if (ny != p1->GetNbinsY() || ny != p2->GetNbinsY()) {
00542       Error("Divide","Attempt to divide profiles with different number of bins");
00543       return;
00544    }
00545    if (!c2) {
00546       Error("Divide","Coefficient of dividing profile cannot be zero");
00547       return;
00548    }
00549 
00550 //*-*- Reset statistics
00551    fEntries = fTsumw   = fTsumw2 = fTsumwx = fTsumwx2 = 0;
00552 
00553 //*-*- Loop on bins (including underflows/overflows)
00554    Int_t bin,binx,biny;
00555    Double_t *cu1 = p1->GetW();
00556    Double_t *cu2 = p2->GetW();
00557    Double_t *er1 = p1->GetW2();
00558    Double_t *er2 = p2->GetW2();
00559    Double_t *en1 = p1->GetB();
00560    Double_t *en2 = p2->GetB();
00561    Double_t b1,b2,w,z,x,y,ac1,ac2;
00562    ac1 = TMath::Abs(c1);
00563    ac2 = TMath::Abs(c2);
00564    for (binx =0;binx<=nx+1;binx++) {
00565       for (biny =0;biny<=ny+1;biny++) {
00566          bin   = biny*(fXaxis.GetNbins()+2) + binx;
00567          b1  = cu1[bin];
00568          b2  = cu2[bin];
00569          if (b2) w = c1*b1/(c2*b2);
00570          else    w = 0;
00571          fArray[bin] = w;
00572          z = TMath::Abs(w);
00573          x = fXaxis.GetBinCenter(binx);
00574          y = fYaxis.GetBinCenter(biny);
00575          fEntries++;
00576          fTsumw   += z;
00577          fTsumw2  += z*z;
00578          fTsumwx  += z*x;
00579          fTsumwx2 += z*x*x;
00580          fTsumwy  += z*y;
00581          fTsumwy2 += z*y*y;
00582          fTsumwxy += z*x*y;
00583          fTsumwz  += z;
00584          fTsumwz2 += z*z;
00585          Double_t e1 = er1[bin];
00586          Double_t e2 = er2[bin];
00587        //Double_t b22= b2*b2*d2;
00588          Double_t b22= b2*b2*TMath::Abs(c2);
00589          if (!b2) fSumw2.fArray[bin] = 0;
00590          else {
00591             if (binomial) {
00592                fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/(c2*b2));
00593             } else {
00594                fSumw2.fArray[bin] = ac1*ac2*(e1*b2*b2 + e2*b1*b1)/(b22*b22);
00595             }
00596          }
00597          if (!en2[bin]) fBinEntries.fArray[bin] = 0;
00598          else           fBinEntries.fArray[bin] = en1[bin]/en2[bin];
00599       }
00600    }
00601 }
00602 
00603 //______________________________________________________________________________
00604 TH1 *TProfile2D::DrawCopy(Option_t *option) const
00605 {
00606 //*-*-*-*-*-*-*-*Draw a copy of this profile2D histogram*-*-*-*-*-*-*-*-*-*-*
00607 //*-*            =======================================
00608    TString opt = option;
00609    opt.ToLower();
00610    if (gPad && !opt.Contains("same")) gPad->Clear();
00611    TProfile2D *newpf = (TProfile2D*)Clone();
00612    newpf->SetDirectory(0);
00613    newpf->SetBit(kCanDelete);
00614    newpf->AppendPad(option);
00615    return newpf;
00616 }
00617 
00618 //______________________________________________________________________________
00619 Int_t TProfile2D::Fill(Double_t x, Double_t y, Double_t z)
00620 {
00621 //*-*-*-*-*-*-*-*-*-*-*Fill a Profile2D histogram (no weights)*-*-*-*-*-*-*-*
00622 //*-*                  =======================================
00623 
00624    if (fBuffer) return BufferFill(x,y,z,1);
00625 
00626    Int_t bin,binx,biny;
00627 
00628    if (fZmin != fZmax) {
00629       if (z <fZmin || z> fZmax) return -1;
00630    }
00631 
00632    fEntries++;
00633    binx =fXaxis.FindBin(x);
00634    biny =fYaxis.FindBin(y);
00635    if (binx <0 || biny <0) return -1;
00636    bin = GetBin(binx, biny); 
00637    fArray[bin] += z; 
00638    fSumw2.fArray[bin] += z*z;
00639    fBinEntries.fArray[bin] += 1;
00640    if (fBinSumw2.fN)  fBinSumw2.fArray[bin] += 1;
00641    if (binx == 0 || binx > fXaxis.GetNbins()) {
00642       if (!fgStatOverflows) return -1;
00643    }
00644    if (biny == 0 || biny > fYaxis.GetNbins()) {
00645       if (!fgStatOverflows) return -1;
00646    }
00647    ++fTsumw;
00648    ++fTsumw2;
00649    fTsumwx  += x;
00650    fTsumwx2 += x*x;
00651    fTsumwy  += y;
00652    fTsumwy2 += y*y;
00653    fTsumwxy += x*y;
00654    fTsumwz  += z;
00655    fTsumwz2 += z*z;
00656    return bin;
00657 }
00658 
00659 //______________________________________________________________________________
00660 Int_t TProfile2D::Fill(Double_t x, const char *namey, Double_t z)
00661 {
00662 // Fill a Profile2D histogram (no weights)
00663 //
00664    Int_t bin,binx,biny;
00665 
00666    if (fZmin != fZmax) {
00667       if (z <fZmin || z> fZmax) return -1;
00668    }
00669 
00670    fEntries++;
00671    binx =fXaxis.FindBin(x);
00672    biny =fYaxis.FindBin(namey);
00673    if (binx <0 || biny <0) return -1;
00674    bin  = biny*(fXaxis.GetNbins()+2) + binx;
00675    AddBinContent(bin, z);
00676    fSumw2.fArray[bin] += (Double_t)z*z;
00677    fBinEntries.fArray[bin] += 1;
00678    if (fBinSumw2.fN)  fBinSumw2.fArray[bin] += 1;
00679    if (binx == 0 || binx > fXaxis.GetNbins()) {
00680       if (!fgStatOverflows) return -1;
00681    }
00682    if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
00683    Double_t y = fYaxis.GetBinCenter(biny);
00684    ++fTsumw;
00685    ++fTsumw2;
00686    fTsumwx  += x;
00687    fTsumwx2 += x*x;
00688    fTsumwy  += y;
00689    fTsumwy2 += y*y;
00690    fTsumwxy += x*y;
00691    fTsumwz  += z;
00692    fTsumwz2 += z*z;
00693    return bin;
00694 }
00695 
00696 //______________________________________________________________________________
00697 Int_t TProfile2D::Fill(const char *namex, const char *namey, Double_t z)
00698 {
00699 // Fill a Profile2D histogram (no weights)
00700 //
00701    Int_t bin,binx,biny;
00702 
00703    if (fZmin != fZmax) {
00704       if (z <fZmin || z> fZmax) return -1;
00705    }
00706 
00707    fEntries++;
00708    binx =fXaxis.FindBin(namex);
00709    biny =fYaxis.FindBin(namey);
00710    if (binx <0 || biny <0) return -1;
00711    bin  = biny*(fXaxis.GetNbins()+2) + binx;
00712    AddBinContent(bin, z);
00713    fSumw2.fArray[bin] += (Double_t)z*z;
00714    fBinEntries.fArray[bin] += 1;
00715    if (fBinSumw2.fN)  fBinSumw2.fArray[bin] += 1;
00716    if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
00717    if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
00718    Double_t x = fYaxis.GetBinCenter(binx);
00719    Double_t y = fYaxis.GetBinCenter(biny);
00720    ++fTsumw;
00721    ++fTsumw2;
00722    fTsumwx  += x;
00723    fTsumwx2 += x*x;
00724    fTsumwy  += y;
00725    fTsumwy2 += y*y;
00726    fTsumwxy += x*y;
00727    fTsumwz  += z;
00728    fTsumwz2 += z*z;
00729    return bin;
00730 }
00731 
00732 //______________________________________________________________________________
00733 Int_t TProfile2D::Fill(const char *namex, Double_t y, Double_t z)
00734 {
00735 // Fill a Profile2D histogram (no weights)
00736 //
00737    Int_t bin,binx,biny;
00738 
00739    if (fZmin != fZmax) {
00740       if (z <fZmin || z> fZmax) return -1;
00741    }
00742 
00743    fEntries++;
00744    binx =fXaxis.FindBin(namex);
00745    biny =fYaxis.FindBin(y);
00746    if (binx <0 || biny <0) return -1;
00747    bin  = biny*(fXaxis.GetNbins()+2) + binx;
00748    AddBinContent(bin, z);
00749    fSumw2.fArray[bin] += (Double_t)z*z;
00750    fBinEntries.fArray[bin] += 1;
00751    if (fBinSumw2.fN)  fBinSumw2.fArray[bin] += 1;
00752    if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
00753    if (biny == 0 || biny > fYaxis.GetNbins()) {
00754       if (!fgStatOverflows) return -1;
00755    }
00756    Double_t x = fYaxis.GetBinCenter(binx);
00757    ++fTsumw;
00758    ++fTsumw2;
00759    fTsumwx  += x;
00760    fTsumwx2 += x*x;
00761    fTsumwy  += y;
00762    fTsumwy2 += y*y;
00763    fTsumwxy += x*y;
00764    fTsumwz  += z;
00765    fTsumwz2 += z*z;
00766    return bin;
00767 }
00768 
00769 //______________________________________________________________________________
00770 Int_t TProfile2D::Fill(Double_t x, Double_t y, Double_t z, Double_t w)
00771 {
00772 //*-*-*-*-*-*-*-*-*-*-*Fill a Profile2D histogram with weights*-*-*-*-*-*-*-*
00773 //*-*                  =======================================
00774 
00775    if (fBuffer) return BufferFill(x,y,z,w);
00776 
00777    Int_t bin,binx,biny;
00778 
00779    if (fZmin != fZmax) {
00780       if (z <fZmin || z> fZmax) return -1;
00781    }
00782 
00783    Double_t u= (w > 0 ? w : -w);
00784    fEntries++;
00785    binx =fXaxis.FindBin(x);
00786    biny =fYaxis.FindBin(y);
00787    if (binx <0 || biny <0) return -1;
00788    bin  = biny*(fXaxis.GetNbins()+2) + binx;
00789    AddBinContent(bin, u*z);
00790    fSumw2.fArray[bin] += u*z*z;
00791    fBinEntries.fArray[bin] += u;
00792    if (fBinSumw2.fN)  fBinSumw2.fArray[bin] += u*u;
00793    if (binx == 0 || binx > fXaxis.GetNbins()) {
00794       if (!fgStatOverflows) return -1;
00795    }
00796    if (biny == 0 || biny > fYaxis.GetNbins()) {
00797       if (!fgStatOverflows) return -1;
00798    }
00799    fTsumw   += u;
00800    fTsumw2  += u*u;
00801    fTsumwx  += u*x;
00802    fTsumwx2 += u*x*x;
00803    fTsumwy  += u*y;
00804    fTsumwy2 += u*y*y;
00805    fTsumwxy += u*x*y;
00806    fTsumwz  += u*z;
00807    fTsumwz2 += u*z*z;
00808    return bin;
00809 }
00810 
00811 //______________________________________________________________________________
00812 Double_t TProfile2D::GetBinContent(Int_t bin) const
00813 {
00814 //*-*-*-*-*-*-*Return bin content of a Profile2D histogram*-*-*-*-*-*-*-*-*
00815 //*-*          ===========================================
00816 
00817    if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
00818 
00819    if (bin < 0 || bin >= fNcells) return 0;
00820    if (fBinEntries.fArray[bin] == 0) return 0;
00821    if (!fArray) return 0;
00822    return fArray[bin]/fBinEntries.fArray[bin];
00823 }
00824 
00825 //______________________________________________________________________________
00826 Double_t TProfile2D::GetBinEntries(Int_t bin) const
00827 {
00828 //*-*-*-*-*-*-*Return bin entries of a Profile2D histogram*-*-*-*-*-*-*-*-*
00829 //*-*          ===========================================
00830 
00831    if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
00832 
00833    if (bin < 0 || bin >= fNcells) return 0;
00834    return fBinEntries.fArray[bin];
00835 }
00836 
00837 //______________________________________________________________________________
00838 Double_t TProfile2D::GetBinEffectiveEntries(Int_t bin)
00839 {
00840 //            Return bin effective entries for a weighted filled Profile histogram. 
00841 //            In case of an unweighted profile, it is equivalent to the number of entries per bin   
00842 //            The effective entries is defined as the square of the sum of the weights divided by the 
00843 //            sum of the weights square. 
00844 //            TProfile::Sumw2() must be called before filling the profile with weights. 
00845 //            Only by calling this method the  sum of the square of the weights per bin is stored. 
00846 //  
00847 //*-*          =========================================
00848 
00849    return TProfileHelper::GetBinEffectiveEntries(this, bin);
00850 }
00851 
00852 //______________________________________________________________________________
00853 Double_t TProfile2D::GetBinError(Int_t bin) const
00854 {
00855 // *-*-*-*-*-*-*Return bin error of a Profile2D histogram*-*-*-*-*-*-*-*-*
00856 //
00857 // Computing errors: A moving field
00858 // =================================
00859 // The computation of errors for a TProfile2D has evolved with the versions
00860 // of ROOT. The difficulty is in computing errors for bins with low statistics.
00861 // - prior to version 3.10, we had no special treatment of low statistic bins.
00862 //   As a result, these bins had huge errors. The reason is that the
00863 //   expression eprim2 is very close to 0 (rounding problems) or 0.
00864 // - The algorithm is modified/protected for the case
00865 //   when a TProfile2D is projected (ProjectionX). The previous algorithm
00866 //   generated a N^2 problem when projecting a TProfile2D with a large number of
00867 //   bins (eg 100000).
00868 // - in version 3.10/02, a new static function TProfile::Approximate
00869 //   is introduced to enable or disable (default) the approximation.
00870 //   (see also comments in TProfile::GetBinError)
00871 
00872    return TProfileHelper::GetBinError((TProfile2D*)this, bin);
00873 }
00874 
00875 //______________________________________________________________________________
00876 Option_t *TProfile2D::GetErrorOption() const
00877 {
00878 //*-*-*-*-*-*-*-*-*-*Return option to compute profile2D errors*-*-*-*-*-*-*-*
00879 //*-*                =========================================
00880 
00881    if (fErrorMode == kERRORSPREAD)  return "s";
00882    if (fErrorMode == kERRORSPREADI) return "i";
00883    if (fErrorMode == kERRORSPREADG) return "g";
00884    return "";
00885 }
00886 
00887 //______________________________________________________________________________
00888 void TProfile2D::GetStats(Double_t *stats) const
00889 {
00890    // fill the array stats from the contents of this profile
00891    // The array stats must be correctly dimensionned in the calling program.
00892    // stats[0] = sumw
00893    // stats[1] = sumw2
00894    // stats[2] = sumwx
00895    // stats[3] = sumwx2
00896    // stats[4] = sumwy
00897    // stats[5] = sumwy2
00898    // stats[6] = sumwxy
00899    // stats[7] = sumwz
00900    // stats[8] = sumwz2
00901    //
00902    // If no axis-subrange is specified (via TAxis::SetRange), the array stats
00903    // is simply a copy of the statistics quantities computed at filling time.
00904    // If a sub-range is specified, the function recomputes these quantities
00905    // from the bin contents in the current axis range.
00906 
00907    if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
00908 
00909    // Loop on bins
00910    if (fTsumw == 0 || fXaxis.TestBit(TAxis::kAxisRange) || fYaxis.TestBit(TAxis::kAxisRange)) {
00911       Int_t bin, binx, biny;
00912       Double_t w, w2;
00913       Double_t x,y;
00914       for (bin=0;bin<9;bin++) stats[bin] = 0;
00915       if (!fBinEntries.fArray) return;
00916       Int_t firstBinX = fXaxis.GetFirst();
00917       Int_t lastBinX  = fXaxis.GetLast();
00918       Int_t firstBinY = fYaxis.GetFirst();
00919       Int_t lastBinY  = fYaxis.GetLast();
00920       // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
00921       if (fgStatOverflows) {
00922         if ( !fXaxis.TestBit(TAxis::kAxisRange) ) {
00923             if (firstBinX == 1) firstBinX = 0;
00924             if (lastBinX ==  fXaxis.GetNbins() ) lastBinX += 1;
00925          }
00926          if ( !fYaxis.TestBit(TAxis::kAxisRange) ) {
00927             if (firstBinY == 1) firstBinY = 0;
00928             if (lastBinY ==  fYaxis.GetNbins() ) lastBinY += 1;
00929          }
00930       }
00931       for (biny = firstBinY; biny <= lastBinY; biny++) {
00932          y = fYaxis.GetBinCenter(biny);
00933          for (binx = firstBinX; binx <= lastBinX; binx++) {
00934             bin = GetBin(binx,biny);
00935             w         = fBinEntries.fArray[bin];
00936             w2        = (fBinSumw2.fN ? fBinSumw2.fArray[bin] : w );  
00937             x         = fXaxis.GetBinCenter(binx);
00938             stats[0] += w;
00939             stats[1] += w2;
00940             stats[2] += w*x;
00941             stats[3] += w*x*x;
00942             stats[4] += w*y;
00943             stats[5] += w*y*y;
00944             stats[6] += w*x*y;
00945             stats[7] += fArray[bin];
00946             stats[8] += fSumw2.fArray[bin];
00947          }
00948       }
00949    } else {
00950       stats[0] = fTsumw;
00951       stats[1] = fTsumw2;
00952       stats[2] = fTsumwx;
00953       stats[3] = fTsumwx2;
00954       stats[4] = fTsumwy;
00955       stats[5] = fTsumwy2;
00956       stats[6] = fTsumwxy;
00957       stats[7] = fTsumwz;
00958       stats[8] = fTsumwz2;
00959    }
00960 }
00961 
00962 //___________________________________________________________________________
00963 void TProfile2D::LabelsDeflate(Option_t *ax)
00964 {
00965 // Reduce the number of bins for this axis to the number of bins having a label.
00966 
00967    TProfileHelper::LabelsDeflate(this, ax);
00968 }
00969 
00970 //___________________________________________________________________________
00971 void TProfile2D::LabelsInflate(Option_t *ax)
00972 {
00973 // Double the number of bins for axis.
00974 // Refill histogram
00975 // This function is called by TAxis::FindBin(const char *label)
00976 
00977    TProfileHelper::LabelsInflate(this, ax);
00978 }
00979 
00980 //___________________________________________________________________________
00981 void TProfile2D::LabelsOption(Option_t *option, Option_t *ax)
00982 {
00983 //  Set option(s) to draw axis with labels
00984 //  option = "a" sort by alphabetic order
00985 //         = ">" sort by decreasing values
00986 //         = "<" sort by increasing values
00987 //         = "h" draw labels horizonthal
00988 //         = "v" draw labels vertical
00989 //         = "u" draw labels up (end of label right adjusted)
00990 //         = "d" draw labels down (start of label left adjusted)
00991 
00992 
00993    TAxis *axis = GetXaxis();
00994    if (ax[0] == 'y' || ax[0] == 'Y') axis = GetYaxis();
00995    THashList *labels = axis->GetLabels();
00996    if (!labels) {
00997       Warning("LabelsOption","Cannot sort. No labels");
00998       return;
00999    }
01000    TString opt = option;
01001    opt.ToLower();
01002    if (opt.Contains("h")) {
01003       axis->SetBit(TAxis::kLabelsHori);
01004       axis->ResetBit(TAxis::kLabelsVert);
01005       axis->ResetBit(TAxis::kLabelsDown);
01006       axis->ResetBit(TAxis::kLabelsUp);
01007    }
01008    if (opt.Contains("v")) {
01009       axis->SetBit(TAxis::kLabelsVert);
01010       axis->ResetBit(TAxis::kLabelsHori);
01011       axis->ResetBit(TAxis::kLabelsDown);
01012       axis->ResetBit(TAxis::kLabelsUp);
01013    }
01014    if (opt.Contains("u")) {
01015       axis->SetBit(TAxis::kLabelsUp);
01016       axis->ResetBit(TAxis::kLabelsVert);
01017       axis->ResetBit(TAxis::kLabelsDown);
01018       axis->ResetBit(TAxis::kLabelsHori);
01019    }
01020    if (opt.Contains("d")) {
01021       axis->SetBit(TAxis::kLabelsDown);
01022       axis->ResetBit(TAxis::kLabelsVert);
01023       axis->ResetBit(TAxis::kLabelsHori);
01024       axis->ResetBit(TAxis::kLabelsUp);
01025    }
01026    Int_t sort = -1;
01027    if (opt.Contains("a")) sort = 0;
01028    if (opt.Contains(">")) sort = 1;
01029    if (opt.Contains("<")) sort = 2;
01030    if (sort < 0) return;
01031 
01032    Int_t nx = fXaxis.GetNbins()+2;
01033    Int_t ny = fYaxis.GetNbins()+2;
01034    Int_t n = TMath::Min(axis->GetNbins(), labels->GetSize());
01035    Int_t *a = new Int_t[n+2];
01036    Int_t i,j,k,bin;
01037    Double_t *sumw   = new Double_t[nx*ny];
01038    Double_t *errors = new Double_t[nx*ny];
01039    Double_t *ent    = new Double_t[nx*ny];
01040    THashList *labold = new THashList(labels->GetSize(),1);
01041    TIter nextold(labels);
01042    TObject *obj;
01043    while ((obj=nextold())) {
01044       labold->Add(obj);
01045    }
01046    labels->Clear();
01047    if (sort > 0) {
01048       //---sort by values of bins
01049       Double_t *pcont = new Double_t[n+2];
01050       for (i=0;i<=n;i++) pcont[i] = 0;
01051       for (i=1;i<nx;i++) {
01052          for (j=1;j<ny;j++) {
01053             bin = i+nx*j;
01054             sumw[bin]   = fArray[bin];
01055             errors[bin] = fSumw2.fArray[bin];
01056             ent[bin]    = fBinEntries.fArray[bin];
01057             if (axis == GetXaxis()) k = i;
01058             else                    k = j;
01059             if (fBinEntries.fArray[bin] != 0) pcont[k-1] += fArray[bin]/fBinEntries.fArray[bin];
01060          }
01061       }
01062       if (sort ==1) TMath::Sort(n,pcont,a,kTRUE);  //sort by decreasing values
01063       else          TMath::Sort(n,pcont,a,kFALSE); //sort by increasing values
01064       delete [] pcont;
01065       for (i=0;i<n;i++) {
01066          obj = labold->At(a[i]);
01067          labels->Add(obj);
01068          obj->SetUniqueID(i+1);
01069       }
01070       for (i=1;i<nx;i++) {
01071          for (j=1;j<ny;j++) {
01072             bin = i+nx*j;
01073             if (axis == GetXaxis()) {
01074                fArray[bin] = sumw[a[i-1]+1+nx*j];
01075                fSumw2.fArray[bin] = errors[a[i-1]+1+nx*j];
01076                fBinEntries.fArray[bin] = ent[a[i-1]+1+nx*j];
01077             } else {
01078                fArray[bin] = sumw[i+nx*(a[j-1]+1)];
01079                fSumw2.fArray[bin] = errors[i+nx*(a[j-1]+1)];
01080                fBinEntries.fArray[bin] = ent[i+nx*(a[j-1]+1)];
01081             }
01082          }
01083       }
01084    } else {
01085       //---alphabetic sort
01086       const UInt_t kUsed = 1<<18;
01087       TObject *objk=0;
01088       a[0] = 0;
01089       a[n+1] = n+1;
01090       for (i=1;i<=n;i++) {
01091          const char *label = "zzzzzzzzzzzz";
01092          for (j=1;j<=n;j++) {
01093             obj = labold->At(j-1);
01094             if (!obj) continue;
01095             if (obj->TestBit(kUsed)) continue;
01096             //use strcasecmp for case non-sensitive sort (may be an option)
01097             if (strcmp(label,obj->GetName()) < 0) continue;
01098             objk = obj;
01099             a[i] = j;
01100             label = obj->GetName();
01101          }
01102          if (objk) {
01103             objk->SetUniqueID(i);
01104             labels->Add(objk);
01105             objk->SetBit(kUsed);
01106          }
01107       }
01108       for (i=1;i<=n;i++) {
01109          obj = labels->At(i-1);
01110          if (!obj) continue;
01111          obj->ResetBit(kUsed);
01112       }
01113       for (i=0;i<nx;i++) {
01114          for (j=0;j<ny;j++) {
01115             bin = i+nx*j;
01116             sumw[bin]   = fArray[bin];
01117             errors[bin] = fSumw2.fArray[bin];
01118             ent[bin]    = fBinEntries.fArray[bin];
01119          }
01120       }
01121       for (i=0;i<nx;i++) {
01122          for (j=0;j<ny;j++) {
01123             bin = i+nx*j;
01124             if (axis == GetXaxis()) {
01125                fArray[bin] = sumw[a[i]+nx*j];
01126                fSumw2.fArray[bin] = errors[a[i]+nx*j];
01127                fBinEntries.fArray[bin] = ent[a[i]+nx*j];
01128             } else {
01129                fArray[bin] = sumw[i+nx*a[j]];
01130                fSumw2.fArray[bin] = errors[i+nx*a[j]];
01131                fBinEntries.fArray[bin] = ent[i+nx*a[j]];
01132             }
01133          }
01134       }
01135    }
01136    delete labold;
01137    if (a)      delete [] a;
01138    if (sumw)   delete [] sumw;
01139    if (errors) delete [] errors;
01140    if (ent)    delete [] ent;
01141 }
01142 
01143 //______________________________________________________________________________
01144 Long64_t TProfile2D::Merge(TCollection *li)
01145 {
01146    //Merge all histograms in the collection in this histogram.
01147    //This function computes the min/max for the axes,
01148    //compute a new number of bins, if necessary,
01149    //add bin contents, errors and statistics.
01150    //If overflows are present and limits are different the function will fail.
01151    //The function returns the total number of entries in the result histogram
01152    //if the merge is successfull, -1 otherwise.
01153    //
01154    //IMPORTANT remark. The 2 axis x and y may have different number
01155    //of bins and different limits, BUT the largest bin width must be
01156    //a multiple of the smallest bin width and the upper limit must also
01157    //be a multiple of the bin width.
01158 
01159    return TProfileHelper::Merge(this, li);
01160 }
01161 
01162 //______________________________________________________________________________
01163 void TProfile2D::Multiply(TF1 *, Double_t )
01164 {
01165    // Performs the operation: this = this*c1*f1
01166 
01167    Error("Multiply","Function not implemented for TProfile2D");
01168    return;
01169 }
01170 
01171 //______________________________________________________________________________
01172 void TProfile2D::Multiply(const TH1 *)
01173 {
01174 //*-*-*-*-*-*-*-*-*-*-*Multiply this profile2D by h1*-*-*-*-*-*-*-*-*-*-*-*
01175 //*-*                  =============================
01176 //
01177 //   this = this*h1
01178 //
01179    Error("Multiply","Multiplication of profile2D histograms not implemented");
01180 }
01181 
01182 
01183 //______________________________________________________________________________
01184 void TProfile2D::Multiply(const TH1 *, const TH1 *, Double_t, Double_t, Option_t *)
01185 {
01186 //*-*-*-*-*Replace contents of this profile2D by multiplication of h1 by h2*-*
01187 //*-*      ================================================================
01188 //
01189 //   this = (c1*h1)*(c2*h2)
01190 //
01191 
01192    Error("Multiply","Multiplication of profile2D histograms not implemented");
01193 }
01194 
01195 //______________________________________________________________________________
01196 TH2D *TProfile2D::ProjectionXY(const char *name, Option_t *option) const
01197 {
01198 //*-*-*-*-*Project this profile2D into a 2-D histogram along X,Y*-*-*-*-*-*-*
01199 //*-*      =====================================================
01200 //
01201 //   The projection is always of the type TH2D.
01202 //
01203 //   if option "E" is specified  the errors of the projected histogram are computed and set 
01204 //      to be equal to the errors of the profile.
01205 //      Option "E" is defined as the default one in the header file. 
01206 //   if option "" is specified the histogram errors are simply the sqrt of its content
01207 //   if option "B" is specified, the content of bin of the returned histogram
01208 //      will be equal to the GetBinEntries(bin) of the profile,
01209 //   if option "C=E" the bin contents of the projection are set to the
01210 //       bin errors of the profile
01211 //   if option "W" is specified the bin content of the projected histogram  is set to the 
01212 //       product of the bin content of the profile and the entries. 
01213 //       With this option the returned histogram will be equivalent to the one obtained by 
01214 //       filling directly a TH2D using the 3-rd value as a weight. 
01215 //       This option makes sense only for profile filled with all weights =1. 
01216 //       When the profile is weighted (filled with weights different than 1) the  
01217 //       bin error of the projected histogram (obtained using this option "W") cannot be 
01218 //       correctly computed from the information stored in the profile. 
01219 
01220 
01221    TString opt = option;
01222    opt.ToLower();
01223    
01224 
01225    Int_t nx = fXaxis.GetNbins();
01226    Int_t ny = fYaxis.GetNbins();
01227 
01228    // Create the projection histogram
01229    char *pname = (char*)name;
01230    if (strcmp(name,"_px") == 0) {
01231       Int_t nch = strlen(GetName()) + 4;
01232       pname = new char[nch];
01233       snprintf(pname,nch,"%s%s",GetName(),name);
01234    }
01235    TH2D *h1 = new TH2D(pname,GetTitle(),nx,fXaxis.GetXmin(),fXaxis.GetXmax(),ny,fYaxis.GetXmin(),fYaxis.GetXmax());
01236    Bool_t computeErrors = kFALSE;
01237    Bool_t cequalErrors  = kFALSE;
01238    Bool_t binEntries    = kFALSE;
01239    Bool_t binWeight     = kFALSE;
01240    if (opt.Contains("b")) binEntries = kTRUE;
01241    if (opt.Contains("e")) computeErrors = kTRUE;
01242    if (opt.Contains("w")) binWeight = kTRUE;
01243    if (opt.Contains("c=e")) {cequalErrors = kTRUE; computeErrors=kFALSE;}
01244    if (computeErrors || binWeight ) h1->Sumw2();
01245    if (pname != name)  delete [] pname;
01246 
01247    // Fill the projected histogram
01248    Int_t bin,binx, biny;
01249    Double_t cont;
01250    for (binx =0;binx<=nx+1;binx++) {
01251       for (biny =0;biny<=ny+1;biny++) {
01252          bin = GetBin(binx,biny);
01253          
01254          if (binEntries)         cont = GetBinEntries(bin);
01255          else if (cequalErrors)  cont = GetBinError(bin);
01256          else if (binWeight)     cont = GetBinContent(bin) * GetBinEntries(bin);
01257          else                    cont = GetBinContent(bin);    // default case
01258 
01259          h1->SetBinContent(bin ,cont);
01260 
01261          // if option E projected histogram errors are same as profile
01262          if (computeErrors ) h1->SetBinError(bin , GetBinError(bin) );
01263          // in case of option W bin error is deduced from bin sum of z**2 values of profile
01264          // this is correct only if the profile is unweighted 
01265          if (binWeight)      h1->SetBinError(bin , TMath::Sqrt(fSumw2.fArray[bin] ) );
01266          // in case of bin entries and h1 has sumw2 set set, we need to set the also bin error
01267          if (binEntries && h1->GetSumw2() ) {
01268             Double_t err2;
01269             if (fBinSumw2.fN) 
01270                err2 = fBinSumw2.fArray[bin]; 
01271             else 
01272                err2 = cont;  // this is fBinEntries.fArray[bin]
01273             h1->SetBinError(bin, TMath::Sqrt(err2 ) ); 
01274          }
01275       }
01276    }
01277    h1->SetEntries(fEntries);
01278    return h1;
01279 }
01280 
01281 //______________________________________________________________________________
01282 void TProfile2D::PutStats(Double_t *stats)
01283 {
01284    // Replace current statistics with the values in array stats
01285 
01286    fTsumw   = stats[0];
01287    fTsumw2  = stats[1];
01288    fTsumwx  = stats[2];
01289    fTsumwx2 = stats[3];
01290    fTsumwy  = stats[4];
01291    fTsumwy2 = stats[5];
01292    fTsumwxy = stats[6];
01293    fTsumwz  = stats[7];
01294    fTsumwz2 = stats[8];
01295 }
01296 
01297 //______________________________________________________________________________
01298 void TProfile2D::Reset(Option_t *option)
01299 {
01300 //*-*-*-*-*-*-*-*-*-*Reset contents of a Profile2D histogram*-*-*-*-*-*-*-*
01301 //*-*                =======================================
01302    TH2D::Reset(option);
01303    fBinEntries.Reset();
01304    fBinSumw2.Reset();
01305    TString opt = option;
01306    opt.ToUpper();
01307    if (opt.Contains("ICE")) return;
01308    fTsumwz = fTsumwz2 = 0;
01309 }
01310 
01311 
01312 //______________________________________________________________________________
01313 void TProfile2D::RebinAxis(Double_t x, TAxis *axis)
01314 {
01315 // Profile histogram is resized along axis such that x is in the axis range.
01316 // The new axis limits are recomputed by doubling iteratively
01317 // the current axis range until the specified value x is within the limits.
01318 // The algorithm makes a copy of the histogram, then loops on all bins
01319 // of the old histogram to fill the rebinned histogram.
01320 // Takes into account errors (Sumw2) if any.
01321 // The bit kCanRebin must be set before invoking this function.
01322 //  Ex:  h->SetBit(TH1::kCanRebin);
01323 
01324    TProfile2D* hold = TProfileHelper::RebinAxis(this, x, axis);
01325    if ( hold ) {
01326       fTsumwz  = hold->fTsumwz;
01327       fTsumwz2 = hold->fTsumwz2;
01328       delete hold;
01329    }
01330 }
01331 
01332 //______________________________________________________________________________
01333 TProfile2D * TProfile2D::Rebin2D(Int_t nxgroup ,Int_t nygroup,const char * newname ) {
01334    //   -*-*-*Rebin this histogram grouping nxgroup/nygroup bins along the xaxis/yaxis together*-*-*-*-
01335    //         =================================================================================
01336    //   if newname is not blank a new profile hnew is created.
01337    //   else the current histogram is modified (default)
01338    //   The parameter nxgroup/nygroup indicate how many bins along the xaxis/yaxis of this
01339    //   have to be merged into one bin of hnew
01340    //   If the original profile has errors stored (via Sumw2), the resulting
01341    //   profile has new errors correctly calculated.
01342    //
01343    //   examples: if hpxpy is an existing TProfile2D profile with 40 x 40 bins
01344    //     hpxpy->Rebin2D();  // merges two bins along the xaxis and yaxis in one
01345    //                        // Carefull: previous contents of hpxpy are lost
01346    //     hpxpy->Rebin2D(3,5);  // merges 3 bins along the xaxis and 5 bins along the yaxis in one
01347    //                           // Carefull: previous contents of hpxpy are lost
01348    //     hpxpy->RebinX(5); //merges five bins along the xaxis in one in hpxpy
01349    //     TProfile2D *hnew = hpxpy->RebinY(5,"hnew"); // creates a new profile hnew
01350    //                                                 // merging 5 bins of hpxpy along the yaxis in one bin
01351    //
01352    //   NOTE : If nxgroup/nygroup is not an exact divider of the number of bins,
01353    //          along the xaxis/yaxis the top limit(s) of the rebinned profile
01354    //          is changed to the upper edge of the xbin=newxbins*nxgroup resp.
01355    //          ybin=newybins*nygroup and the remaining bins are added to
01356    //          the overflow bin.
01357    //          Statistics will be recomputed from the new bin contents.
01358 
01359    //something to do?
01360    if((nxgroup != 1) || (nygroup != 1)){
01361       Int_t nxbins  = fXaxis.GetNbins();
01362       Int_t nybins  = fYaxis.GetNbins();
01363       Double_t xmin  = fXaxis.GetXmin();
01364       Double_t xmax  = fXaxis.GetXmax();
01365       Double_t ymin  = fYaxis.GetXmin();
01366       Double_t ymax  = fYaxis.GetXmax();
01367       if ((nxgroup <= 0) || (nxgroup > nxbins)) {
01368          Error("Rebin", "Illegal value of nxgroup=%d",nxgroup);
01369          return 0;
01370       }
01371       if ((nygroup <= 0) || (nygroup > nybins)) {
01372          Error("Rebin", "Illegal value of nygroup=%d",nygroup);
01373          return 0;
01374       }
01375 
01376       Int_t newxbins = nxbins/nxgroup;
01377       Int_t newybins = nybins/nygroup;
01378 
01379       //warning if bins are added to the overflow bin
01380       if(newxbins*nxgroup != nxbins) {
01381          Warning("Rebin", "nxgroup=%d should be an exact divider of nxbins=%d",nxgroup,nxbins);
01382       }
01383       if(newybins*nygroup != nybins) {
01384          Warning("Rebin", "nygroup=%d should be an exact divider of nybins=%d",nygroup,nybins);
01385       }
01386 
01387       //save old bin contents in new arrays
01388       Double_t *oldBins   = new Double_t[(nxbins+2)*(nybins+2)];
01389       Double_t *oldCount  = new Double_t[(nxbins+2)*(nybins+2)];
01390       Double_t *oldErrors = new Double_t[(nxbins+2)*(nybins+2)];
01391       Double_t *oldBinw2  = (fBinSumw2.fN ? new Double_t[(nxbins+2)*(nybins+2)] : 0  );
01392       Double_t *cu1 = GetW();
01393       Double_t *er1 = GetW2();
01394       Double_t *en1 = GetB();
01395       Double_t *ew1 = GetB2();
01396       for(Int_t ibin=0; ibin < (nxbins+2)*(nybins+2); ibin++){
01397          oldBins[ibin]   = cu1[ibin];
01398          oldCount[ibin]  = en1[ibin];
01399          oldErrors[ibin] = er1[ibin];
01400          if (ew1 && fBinSumw2.fN) oldBinw2[ibin]  = ew1[ibin];
01401       }
01402 
01403       // create a clone of the old profile if newname is specified
01404       TProfile2D *hnew = this;
01405       if(newname && strlen(newname) > 0) {
01406          hnew = (TProfile2D*)Clone(newname);
01407       }
01408 
01409       // in case of nxgroup/nygroup not an exact divider of nxbins/nybins, 
01410       // top limit is changed (see NOTE in method comment) 
01411       if(newxbins*nxgroup != nxbins) {
01412          xmax = fXaxis.GetBinUpEdge(newxbins*nxgroup);
01413          hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
01414       }
01415       if(newybins*nygroup != nybins) {
01416          ymax = fYaxis.GetBinUpEdge(newybins*nygroup);
01417          hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
01418       }
01419 
01420       //rebin the axis
01421       if((fXaxis.GetXbins()->GetSize() > 0) || (fYaxis.GetXbins()->GetSize() > 0)){
01422          Double_t* xbins = new Double_t[newxbins+1];
01423          Double_t* ybins = new Double_t[newybins+1];
01424          for(Int_t i=0; i < newxbins+1; i++)
01425             xbins[i] = fXaxis.GetBinLowEdge(1+i*nxgroup);
01426          for(Int_t j=0; j < newybins+1; j++)
01427             ybins[j] = fYaxis.GetBinLowEdge(1+j*nygroup);
01428          hnew->SetBins(newxbins,xbins,newybins,ybins);
01429          delete [] xbins;
01430          delete [] ybins;
01431       }
01432       //fixed bin size
01433       else{
01434          hnew->SetBins(newxbins,xmin,xmax,newybins,ymin,ymax);
01435       }
01436 
01437       //merge bins
01438       Double_t *cu2 = hnew->GetW();
01439       Double_t *er2 = hnew->GetW2();
01440       Double_t *en2 = hnew->GetB();
01441       Double_t *ew2 = hnew->GetB2();
01442       Double_t binContent, binCount, binError, binSumw2;
01443       //connection between x and y bin number and linear global bin number:
01444       //global bin = xbin + (nxbins+2) * ybin
01445       Int_t oldxbin = 1;
01446       Int_t oldybin = 1;
01447       //global bin number
01448       Int_t bin;
01449       for(Int_t xbin = 1; xbin <= newxbins; xbin++){
01450          oldybin = 1;
01451          for(Int_t ybin = 1; ybin <= newybins; ybin++){
01452             binContent = 0;
01453             binCount   = 0;
01454             binError   = 0;
01455             binSumw2   = 0;
01456             for(Int_t i=0; i < nxgroup; i++){
01457                if(oldxbin + i > nxbins) break;
01458                for(Int_t j=0; j < nygroup; j++){
01459                   if(oldybin + j > nybins) break;
01460                   bin = oldxbin + i + (nxbins+2)*(oldybin+j);
01461                   binContent += oldBins[bin];
01462                   binCount += oldCount[bin];
01463                   binError += oldErrors[bin];
01464                   if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
01465                }
01466             }
01467             bin = xbin + (newxbins + 2)*ybin;
01468             cu2[bin] = binContent;
01469             er2[bin] = binError;
01470             en2[bin] = binCount;
01471             if(fBinSumw2.fN) ew2[bin] = binSumw2;
01472             oldybin += nygroup;
01473          }
01474          oldxbin += nxgroup;
01475       }
01476 
01477       //copy the underflow bin in x and y (0,0)
01478       cu2[0] = oldBins[0];
01479       er2[0] = oldErrors[0];
01480       en2[0] = oldCount[0];
01481       if(fBinSumw2.fN) ew2[0] = oldBinw2[0];
01482       //calculate overflow bin in x and y (newxbins+1,newybins+1)
01483       //therefore the oldxbin and oldybin from above are needed!
01484       binContent = 0;
01485       binCount   = 0;
01486       binError   = 0;
01487       binSumw2   = 0;
01488       for(Int_t i=oldxbin; i <= nxbins+1; i++){
01489          for(Int_t j=oldybin; j <= nybins+1; j++){
01490             //global bin number
01491             bin = i + (nxbins+2)*j;
01492             binContent += oldBins[bin];
01493             binCount += oldCount[bin];
01494             binError += oldErrors[bin];
01495             if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
01496          }
01497       }
01498       bin = (newxbins+2)*(newybins+2)-1;
01499       cu2[bin] = binContent;
01500       er2[bin] = binError;
01501       en2[bin] = binCount;
01502       if(fBinSumw2.fN) ew2[bin] = binSumw2;
01503       //calculate overflow bin in x and underflow bin in y (newxbins+1,0)
01504       binContent = 0;
01505       binCount   = 0;
01506       binError   = 0;
01507       binSumw2   = 0;
01508       for(Int_t i=oldxbin; i <= nxbins+1; i++){
01509          bin = i;
01510          binContent += oldBins[bin];
01511          binCount += oldCount[bin];
01512          binError += oldErrors[bin];
01513          if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
01514       }
01515       bin = newxbins + 1;
01516       cu2[bin] = binContent;
01517       er2[bin] = binError;
01518       en2[bin] = binCount;
01519       if(fBinSumw2.fN) ew2[bin] = binSumw2;
01520       //calculate underflow bin in x and overflow bin in y (0,newybins+1)
01521       binContent = 0;
01522       binCount   = 0;
01523       binError   = 0;
01524       binSumw2   = 0;
01525       for(Int_t i=oldybin; i <= nybins+1; i++){
01526          bin = i*(nxbins + 2);
01527          binContent += oldBins[bin];
01528          binCount += oldCount[bin];
01529          binError += oldErrors[bin];
01530          if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
01531       }
01532       bin = (newxbins + 2)*(newybins + 1);
01533       cu2[bin] = binContent;
01534       er2[bin] = binError;
01535       en2[bin] = binCount;
01536       if(fBinSumw2.fN) ew2[bin] = binSumw2;
01537       //calculate under/overflow contents in y for the new x bins
01538       Double_t binContentuf, binCountuf, binErroruf, binSumw2uf;
01539       Double_t binContentof, binCountof, binErrorof, binSumw2of;
01540       Int_t ufbin, ofbin;
01541       Int_t oldxbin2 = 1;
01542       for(Int_t xbin = 1; xbin <= newxbins; xbin++){
01543          binContentuf = 0;
01544          binCountuf   = 0;
01545          binErroruf   = 0;
01546          binSumw2uf   = 0;
01547          binContentof = 0;
01548          binCountof   = 0;
01549          binErrorof   = 0;
01550          binSumw2of   = 0;
01551          for(Int_t i = 0; i < nxgroup; i++){
01552             //index of under/overflow bin for y in old binning
01553             ufbin = (oldxbin2 + i);
01554             binContentuf += oldBins[ufbin];
01555             binCountuf   += oldCount[ufbin];
01556             binErroruf   += oldErrors[ufbin];
01557             if(fBinSumw2.fN) binSumw2uf   += oldBinw2[ufbin];
01558             for(Int_t j = oldybin; j <= nybins+1; j++)
01559             {
01560                ofbin = ufbin + j*(nxbins + 2);
01561                binContentof += oldBins[ofbin];
01562                binCountof   += oldCount[ofbin];
01563                binErrorof   += oldErrors[ofbin];
01564                if(fBinSumw2.fN) binSumw2of   += oldBinw2[ofbin];
01565             }
01566          }
01567          //index of under/overflow bin for y in new binning
01568          ufbin = xbin;
01569          ofbin = ufbin + (newybins + 1)*(newxbins + 2);
01570          cu2[ufbin] = binContentuf;
01571          er2[ufbin] = binErroruf;
01572          en2[ufbin] = binCountuf;
01573          if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
01574          cu2[ofbin] = binContentof;
01575          er2[ofbin] = binErrorof;
01576          en2[ofbin] = binCountof;
01577          if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
01578          
01579          oldxbin2 += nxgroup;
01580       }
01581       //calculate under/overflow contents in x for the new y bins
01582       Int_t oldybin2 = 1;
01583       for(Int_t ybin = 1; ybin <= newybins; ybin++){
01584          binContentuf = 0;
01585          binCountuf   = 0;
01586          binErroruf   = 0;
01587          binSumw2uf   = 0;
01588          binContentof = 0;
01589          binCountof   = 0;
01590          binErrorof   = 0;
01591          binSumw2of   = 0;
01592          for(Int_t i = 0; i < nygroup; i++){
01593             //index of under/overflow bin for x in old binning
01594             ufbin = (oldybin2 + i)*(nxbins+2);
01595             binContentuf += oldBins[ufbin];
01596             binCountuf   += oldCount[ufbin];
01597             binErroruf   += oldErrors[ufbin];
01598             if(fBinSumw2.fN) binSumw2uf   += oldBinw2[ufbin];
01599             for(Int_t j = oldxbin; j <= nxbins+1; j++)
01600             {
01601                ofbin = j + ufbin;
01602                binContentof += oldBins[ofbin];
01603                binCountof   += oldCount[ofbin];
01604                binErrorof   += oldErrors[ofbin];
01605                if(fBinSumw2.fN) binSumw2of   += oldBinw2[ofbin];
01606             }
01607          }
01608          //index of under/overflow bin for x in new binning
01609          ufbin = ybin * (newxbins + 2);
01610          ofbin = newxbins + 1 + ufbin;
01611          cu2[ufbin] = binContentuf;
01612          er2[ufbin] = binErroruf;
01613          en2[ufbin] = binCountuf;
01614          if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
01615          cu2[ofbin] = binContentof;
01616          er2[ofbin] = binErrorof;
01617          en2[ofbin] = binCountof;
01618          if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
01619 
01620          oldybin2 += nygroup;
01621          }
01622 
01623       delete [] oldBins;
01624       delete [] oldCount;
01625       delete [] oldErrors;
01626       if (oldBinw2) delete [] oldBinw2;
01627 
01628       return hnew;
01629    }
01630    //nxgroup == nygroup == 1
01631    else{
01632       if((newname) && (strlen(newname) > 0))
01633          return (TProfile2D*)Clone(newname);
01634       else
01635          return this;
01636    }   
01637 }
01638 
01639 //______________________________________________________________________________
01640 TProfile2D * TProfile2D::RebinX(Int_t ngroup,const char * newname ) {
01641 // Rebin only the X axis
01642 // see Rebin2D
01643 
01644    return Rebin2D(ngroup,1,newname);
01645 }
01646 
01647 //______________________________________________________________________________
01648 TProfile2D * TProfile2D::RebinY(Int_t ngroup,const char * newname ) {
01649 // Rebin only the Y axis
01650 // see Rebin2D
01651 
01652    return Rebin2D(1,ngroup,newname);
01653 }
01654 
01655 //______________________________________________________________________________
01656 void TProfile2D::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
01657 {
01658    // Save primitive as a C++ statement(s) on output stream out
01659 
01660    //Note the following restrictions in the code generated:
01661    // - variable bin size not implemented
01662    // - SetErrorOption not implemented
01663 
01664 
01665    char quote = '"';
01666    out <<"   "<<endl;
01667    out <<"   "<<ClassName()<<" *";
01668 
01669    out << GetName() << " = new " << ClassName() << "(" << quote
01670        << GetName() << quote << "," << quote<< GetTitle() << quote
01671        << "," << GetXaxis()->GetNbins();
01672    out << "," << GetXaxis()->GetXmin()
01673        << "," << GetXaxis()->GetXmax();
01674    out << "," << GetYaxis()->GetNbins();
01675    out << "," << GetYaxis()->GetXmin()
01676        << "," << GetYaxis()->GetXmax();
01677    out << "," << fZmin
01678        << "," << fZmax;
01679    out << ");" << endl;
01680 
01681 
01682    // save bin entries
01683    Int_t bin;
01684    for (bin=0;bin<fNcells;bin++) {
01685       Double_t bi = GetBinEntries(bin);
01686       if (bi) {
01687          out<<"   "<<GetName()<<"->SetBinEntries("<<bin<<","<<bi<<");"<<endl;
01688       }
01689    }
01690    //save bin contents
01691    for (bin=0;bin<fNcells;bin++) {
01692       Double_t bc = fArray[bin];
01693       if (bc) {
01694          out<<"   "<<GetName()<<"->SetBinContent("<<bin<<","<<bc<<");"<<endl;
01695       }
01696    }
01697    // save bin errors
01698    if (fSumw2.fN) {
01699       for (bin=0;bin<fNcells;bin++) {
01700          Double_t be = TMath::Sqrt(fSumw2.fArray[bin]);
01701          if (be) {
01702             out<<"   "<<GetName()<<"->SetBinError("<<bin<<","<<be<<");"<<endl;
01703          }
01704       }
01705    }
01706 
01707    TH1::SavePrimitiveHelp(out, GetName(), option);
01708 }
01709 
01710 //______________________________________________________________________________
01711 void TProfile2D::Scale(Double_t c1, Option_t * option)
01712 {
01713 // *-*-*-*-*Multiply this profile2D by a constant c1*-*-*-*-*-*-*-*-*
01714 // *-*      ========================================
01715 //
01716 //   this = c1*this
01717 //
01718 // This function uses the services of TProfile2D::Add
01719 //
01720 
01721    TProfileHelper::Scale(this, c1, option);
01722 }
01723 
01724 //______________________________________________________________________________
01725 void TProfile2D::SetBinEntries(Int_t bin, Double_t w)
01726 {
01727 //*-*-*-*-*-*-*-*-*Set the number of entries in bin*-*-*-*-*-*-*-*-*-*-*-*
01728 //*-*              ================================
01729 
01730    if (bin < 0 || bin >= fNcells) return;
01731    fBinEntries.fArray[bin] = w;
01732 }
01733 
01734 //______________________________________________________________________________
01735 void TProfile2D::SetBins(Int_t nx, Double_t xmin, Double_t xmax, Int_t ny, Double_t ymin, Double_t ymax)
01736 {
01737 //*-*-*-*-*-*-*-*-*Redefine  x axis parameters*-*-*-*-*-*-*-*-*-*-*-*
01738 //*-*              ===========================
01739 
01740    fXaxis.Set(nx,xmin,xmax);
01741    fYaxis.Set(ny,ymin,ymax);
01742    fNcells = (nx+2)*(ny+2);
01743    SetBinsLength(fNcells);
01744    fBinEntries.Set(fNcells);
01745    fSumw2.Set(fNcells);
01746    if (fBinSumw2.fN) fBinSumw2.Set(fNcells);
01747 }
01748 
01749 
01750 //______________________________________________________________________________
01751 void TProfile2D::SetBuffer(Int_t buffersize, Option_t *)
01752 {
01753 // set the buffer size in units of 8 bytes (double)
01754 
01755    if (fBuffer) {
01756       BufferEmpty();
01757       delete [] fBuffer;
01758       fBuffer = 0;
01759    }
01760    if (buffersize <= 0) {
01761       fBufferSize = 0;
01762       return;
01763    }
01764    if (buffersize < 100) buffersize = 100;
01765    fBufferSize = 1 + 4*buffersize;
01766    fBuffer = new Double_t[fBufferSize];
01767    memset(fBuffer,0,8*fBufferSize);
01768 }
01769 
01770 //______________________________________________________________________________
01771 void TProfile2D::SetErrorOption(Option_t *option)
01772 {
01773 //*-*-*-*-*-*-*-*-*-*Set option to compute profile2D errors*-*-*-*-*-*-*-*
01774 //*-*                =======================================
01775 //
01776 //    The computation of errors is based on the parameter option:
01777 //    option:
01778 //     ' '  (Default) Errors are Spread/SQRT(N) for Spread.ne.0. ,
01779 //                      "     "  SQRT(Z)/SQRT(N) for Spread.eq.0,N.gt.0 ,
01780 //                      "     "  0.  for N.eq.0
01781 //     's'            Errors are Spread  for Spread.ne.0. ,
01782 //                      "     "  SQRT(Z)  for Spread.eq.0,N.gt.0 ,
01783 //                      "     "  0.  for N.eq.0
01784 //     'i'            Errors are Spread/SQRT(N) for Spread.ne.0. ,
01785 //                      "     "  1./SQRT(12.*N) for Spread.eq.0,N.gt.0 ,
01786 //                      "     "  0.  for N.eq.0
01787 //   See TProfile2D::BuildOptions for explanation of all options
01788 
01789    TString opt = option;
01790    opt.ToLower();
01791    fErrorMode = kERRORMEAN;
01792    if (opt.Contains("s")) fErrorMode = kERRORSPREAD;
01793    if (opt.Contains("i")) fErrorMode = kERRORSPREADI;
01794    if (opt.Contains("g")) fErrorMode = kERRORSPREADG;
01795 }
01796 
01797 //______________________________________________________________________________
01798 void TProfile2D::Streamer(TBuffer &R__b)
01799 {
01800    // Stream an object of class TProfile2D.
01801 
01802    if (R__b.IsReading()) {
01803       UInt_t R__s, R__c;
01804       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
01805       if (R__v > 2) {
01806          R__b.ReadClassBuffer(TProfile2D::Class(), this, R__v, R__s, R__c);
01807          return;
01808       }
01809       //====process old versions before automatic schema evolution
01810       TH2D::Streamer(R__b);
01811       fBinEntries.Streamer(R__b);
01812       Int_t errorMode;
01813       R__b >> errorMode;
01814       fErrorMode = (EErrorType)errorMode;
01815       if (R__v < 2) {
01816          Float_t zmin,zmax;
01817          R__b >> zmin; fZmin = zmin;
01818          R__b >> zmax; fZmax = zmax;
01819       } else {
01820          R__b >> fZmin;
01821          R__b >> fZmax;
01822       }
01823       R__b.CheckByteCount(R__s, R__c, TProfile2D::IsA());
01824       //====end of old versions
01825 
01826    } else {
01827       R__b.WriteClassBuffer(TProfile2D::Class(),this);
01828    }
01829 }
01830 
01831 //______________________________________________________________________________
01832 void TProfile2D::Sumw2()
01833 {
01834    // Create structure to store sum of squares of weights per bin  *-*-*-*-*-*-*-*
01835    //   This is needed to compute  the correct statistical quantities  
01836    //    of a profile filled with weights 
01837    //  
01838    //
01839    //  This function is automatically called when the histogram is created
01840    //  if the static function TH1::SetDefaultSumw2 has been called before.
01841 
01842    TProfileHelper::Sumw2(this);
01843 }

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