TProfileHelper.h

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TProfileHelper.h 37933 2011-02-02 08:24:49Z moneta $
00002 // Author: David Gonzalez Maline   18/01/2008
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 #ifndef ROOT_TProfileHelper
00013 #define ROOT_TProfileHelper
00014 
00015 
00016 //////////////////////////////////////////////////////////////////////////
00017 //                                                                      //
00018 // TProfileHelper                                                       //
00019 //                                                                      //
00020 // Profile helper class.                                                //
00021 //                                                                      //
00022 //////////////////////////////////////////////////////////////////////////
00023 
00024 #include "TH1.h"
00025 #include "TError.h"
00026 #include "TCollection.h"
00027 #include "THashList.h"
00028 #include "TMath.h"
00029 
00030 class TProfileHelper {
00031 
00032 public:
00033    template <typename T>
00034    static void Add(T* p, const TH1 *h1,  const TH1 *h2, Double_t c1, Double_t c2=1);
00035 
00036    template <typename T>
00037    static Double_t GetBinEffectiveEntries(T* p, Int_t bin);
00038 
00039    template <typename T>
00040    static Long64_t Merge(T* p, TCollection *list);
00041 
00042    template <typename T>
00043    static T* RebinAxis(T* p, Double_t x, TAxis *axis);
00044 
00045    template <typename T>
00046    static void Scale(T* p, Double_t c1, Option_t * option);
00047 
00048    template <typename T> 
00049    static void Sumw2(T* p);
00050 
00051    template <typename T>
00052    static void LabelsDeflate(T* p, Option_t *);
00053 
00054    template <typename T>
00055    static void LabelsInflate(T* p, Option_t *);
00056 
00057    template <typename T>
00058    static Double_t GetBinError(T* p, Int_t bin);
00059 };
00060 
00061 template <typename T>
00062 void TProfileHelper::Add(T* p, const TH1 *h1,  const TH1 *h2, Double_t c1, Double_t c2)
00063 {
00064    // Performs the operation: this = c1*h1 + c2*h2
00065 
00066    T *p1 = (T*)h1;
00067    T *p2 = (T*)h2;
00068 
00069 // Check profile compatibility
00070    Int_t nx = p->GetNbinsX();
00071    Int_t ny = p->GetNbinsY();
00072    Int_t nz = p->GetNbinsZ();
00073 
00074    if ( nx != p1->GetNbinsX() ||  nx != p2->GetNbinsX() ||
00075         ny != p1->GetNbinsY() ||  ny != p2->GetNbinsY() ||
00076         nz != p1->GetNbinsZ() ||  nz != p2->GetNbinsZ() ) {
00077       Error("Add","Attempt to add profiles with different number of bins");
00078       return;
00079    }
00080 
00081 // Add statistics
00082    Double_t ac1 = TMath::Abs(c1);
00083    Double_t ac2 = TMath::Abs(c2);
00084    p->fEntries = ac1*p1->GetEntries() + ac2*p2->GetEntries();
00085    Double_t s0[TH1::kNstat], s1[TH1::kNstat], s2[TH1::kNstat];
00086    Int_t i;
00087    for (i=0;i<TH1::kNstat;i++) {s0[i] = s1[i] = s2[i] = 0;}
00088    p->GetStats(s0);
00089    p1->GetStats(s1);
00090    p2->GetStats(s2);
00091    for (i=0;i<TH1::kNstat;i++) {
00092       if (i == 1) s0[i] = c1*c1*s1[i] + c2*c2*s2[i]; 
00093       else        s0[i] = ac1*s1[i] + ac2*s2[i];
00094    }
00095    p->PutStats(s0);
00096 
00097 // Make the loop over the bins to calculate the Addition
00098    Int_t bin;
00099    Double_t *cu1 = p1->GetW();    Double_t *cu2 = p2->GetW();
00100    Double_t *er1 = p1->GetW2();   Double_t *er2 = p2->GetW2();
00101    Double_t *en1 = p1->GetB();    Double_t *en2 = p2->GetB();
00102    Double_t *ew1 = p1->GetB2();   Double_t *ew2 = p2->GetB2();
00103    // create sumw2 per bin if not set 
00104    if (p->fBinSumw2.fN == 0 && (p1->fBinSumw2.fN != 0 || p2->fBinSumw2.fN != 0) ) p->Sumw2();
00105    // if p1 has not the sum of weight squared/bin stored use just the sum of weights  
00106    if (ew1 == 0) ew1 = en1;
00107    if (ew2 == 0) ew2 = en2; 
00108    for (bin =0;bin< p->fN;bin++) {
00109       p->fArray[bin]             = c1*cu1[bin] + c2*cu2[bin];
00110       p->fSumw2.fArray[bin]      = ac1*er1[bin] + ac2*er2[bin];
00111       p->fBinEntries.fArray[bin] = ac1*en1[bin] + ac2*en2[bin];
00112       if (p->fBinSumw2.fN ) p->fBinSumw2.fArray[bin]  = ac1*ac1*ew1[bin] + ac2*ac2*ew2[bin];
00113    }
00114 }
00115 
00116 template <typename T>
00117 Double_t TProfileHelper::GetBinEffectiveEntries(T* p, Int_t bin) 
00118 {
00119 //            Return bin effective entries for a weighted filled Profile histogram. 
00120 //            In case of an unweighted profile, it is equivalent to the number of entries per bin   
00121 //            The effective entries is defined as the square of the sum of the weights divided by the 
00122 //            sum of the weights square. 
00123 //            TProfile::Sumw2() must be called before filling the profile with weights. 
00124 //            Only by calling this method the  sum of the square of the weights per bin is stored. 
00125 //  
00126 
00127    if (p->fBuffer) p->BufferEmpty();
00128 
00129    if (bin < 0 || bin >= p->fNcells) return 0;
00130    double sumOfWeights = p->fBinEntries.fArray[bin];
00131    if ( p->fBinSumw2.fN == 0 || p->fBinSumw2.fN != p->fNcells) { 
00132       // this can happen  when reading an old file 
00133       p->fBinSumw2.Set(0);
00134       return sumOfWeights;
00135    }
00136    double sumOfWeightsSquare = p->fBinSumw2.fArray[bin]; 
00137    return ( sumOfWeightsSquare > 0 ?  sumOfWeights * sumOfWeights /   sumOfWeightsSquare : 0 ); 
00138 }
00139 
00140 template <typename T>
00141 Long64_t TProfileHelper::Merge(T* p, TCollection *li) {
00142    //Merge all histograms in the collection in this histogram.
00143    //This function computes the min/max for the axes,
00144    //compute a new number of bins, if necessary,
00145    //add bin contents, errors and statistics.
00146    //If overflows are present and limits are different the function will fail.
00147    //The function returns the total number of entries in the result histogram
00148    //if the merge is successfull, -1 otherwise.
00149    //
00150    //IMPORTANT remark. The 2 axis x and y may have different number
00151    //of bins and different limits, BUT the largest bin width must be
00152    //a multiple of the smallest bin width and the upper limit must also
00153    //be a multiple of the bin width.
00154 
00155    if (!li) return 0;
00156    if (li->IsEmpty()) return (Int_t) p->GetEntries();
00157 
00158    TList inlist;
00159    TH1* hclone = (TH1*)p->Clone("FirstClone");
00160    R__ASSERT(hclone);
00161    p->BufferEmpty(1);         // To remove buffer.
00162    p->Reset();                // BufferEmpty sets limits so we can't use it later.
00163    p->SetEntries(0);
00164    inlist.Add(hclone);
00165    inlist.AddAll(li);
00166 
00167    TAxis newXAxis;
00168    TAxis newYAxis;
00169    TAxis newZAxis;
00170    Bool_t initialLimitsFound = kFALSE;
00171    Bool_t same = kTRUE;
00172    Bool_t allHaveLimits = kTRUE;
00173 
00174    TIter next(&inlist);
00175    while (TObject *o = next()) {
00176       T* h = dynamic_cast<T*> (o);
00177       if (!h) {
00178          Error("Add","Attempt to add object of class: %s to a %s",
00179                o->ClassName(),p->ClassName());
00180          return -1;
00181       }
00182       Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
00183       allHaveLimits = allHaveLimits && hasLimits;
00184 
00185       if (hasLimits) {
00186          h->BufferEmpty();
00187          if (!initialLimitsFound) {
00188             initialLimitsFound = kTRUE;
00189             newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
00190                      h->GetXaxis()->GetXmax());
00191             if ( p->GetDimension() >= 2 )
00192             newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
00193                      h->GetYaxis()->GetXmax());
00194             if ( p->GetDimension() >= 3 )
00195             newZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
00196                      h->GetZaxis()->GetXmax());
00197          }
00198          else {
00199             if (!p->RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
00200                Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
00201                      "first: (%d, %f, %f), second: (%d, %f, %f)",
00202                      newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
00203                      h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
00204                      h->GetXaxis()->GetXmax());
00205             }
00206             if (p->GetDimension() >= 2 && !p->RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
00207                Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
00208                      "first: (%d, %f, %f), second: (%d, %f, %f)",
00209                      newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
00210                      h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
00211                      h->GetYaxis()->GetXmax());
00212             }
00213             if (p->GetDimension() >= 3 && !p->RecomputeAxisLimits(newZAxis, *(h->GetZaxis()))) {
00214                Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
00215                      "first: (%d, %f, %f), second: (%d, %f, %f)",
00216                      newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax(),
00217                      h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
00218                      h->GetZaxis()->GetXmax());
00219             }
00220          }
00221       }
00222    }
00223    next.Reset();
00224 
00225    same = same && p->SameLimitsAndNBins(newXAxis, *(p->GetXaxis()));
00226    if ( p->GetDimension() >= 2 )
00227       same = same && p->SameLimitsAndNBins(newYAxis, *(p->GetYaxis()));
00228    if ( p->GetDimension() >= 3 )
00229       same = same && p->SameLimitsAndNBins(newZAxis, *(p->GetZaxis()));
00230    if (!same && initialLimitsFound) {
00231       Int_t b[] = { newXAxis.GetNbins(), newYAxis.GetNbins(), newZAxis.GetNbins() };
00232       Double_t v[] = { newXAxis.GetXmin(), newXAxis.GetXmax(),
00233                        newYAxis.GetXmin(), newYAxis.GetXmax(),
00234                        newZAxis.GetXmin(), newZAxis.GetXmax() };
00235       p->SetBins(b, v);
00236    }
00237 
00238    if (!allHaveLimits) {
00239       // fill this histogram with all the data from buffers of histograms without limits
00240       while (T* h = dynamic_cast<T*> (next())) {
00241          if (h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && h->fBuffer) {
00242              // no limits
00243             Int_t nbentries = (Int_t)h->fBuffer[0];
00244             Double_t v[5];
00245             for (Int_t i = 0; i < nbentries; i++)
00246                if ( p->GetDimension() == 3 ) {
00247                   v[0] = h->fBuffer[5*i + 2];
00248                   v[1] = h->fBuffer[5*i + 3];
00249                   v[2] = h->fBuffer[5*i + 4];
00250                   v[3] = h->fBuffer[5*i + 5];
00251                   v[4] = h->fBuffer[5*i + 1];
00252                   p->Fill(v);
00253                } else if ( p->GetDimension() == 2 ) {
00254                   v[0] = h->fBuffer[4*i + 2];
00255                   v[1] = h->fBuffer[4*i + 3];
00256                   v[2] = h->fBuffer[4*i + 4];
00257                   v[3] = h->fBuffer[4*i + 1];
00258                   v[4] = 0;
00259                   p->Fill(v);
00260                }
00261                else if ( p->GetDimension() == 1 ) {
00262                   v[0] = h->fBuffer[3*i + 2];
00263                   v[1] = h->fBuffer[3*i + 3];
00264                   v[2] = h->fBuffer[3*i + 1];
00265                   v[3] = v[4] = 0;
00266                   p->Fill(v);
00267                }
00268          }
00269       }
00270       if (!initialLimitsFound)
00271          return (Int_t) p->GetEntries();  // all histograms have been processed
00272       next.Reset();
00273    }
00274 
00275    //merge bin contents and errors
00276    Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
00277    for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
00278    p->GetStats(totstats);
00279    Double_t nentries = p->GetEntries();
00280    Bool_t canRebin=p->TestBit(TH1::kCanRebin);
00281    p->ResetBit(TH1::kCanRebin); // reset, otherwise setting the under/overflow will rebin
00282 
00283    while ( T* h=static_cast<T*>(next()) ) {
00284       // process only if the histogram has limits; otherwise it was processed before
00285       if (h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
00286          // import statistics
00287          h->GetStats(stats);
00288          for (Int_t i = 0; i < TH1::kNstat; i++)
00289             totstats[i] += stats[i];
00290          nentries += h->GetEntries();
00291 
00292          for ( Int_t hbin = 0; hbin < h->fN; ++hbin ) {
00293             if ((!same) && (h->IsBinUnderflow(hbin) || h->IsBinOverflow(hbin)) ) {
00294                if (h->GetW()[hbin] != 0) {
00295                   Error("Merge", "Cannot merge histograms - the histograms have"
00296                         " different limits and undeflows/overflows are present."
00297                         " The initial histogram is now broken!");
00298                   return -1;
00299                }
00300             }
00301             Int_t hbinx, hbiny, hbinz;
00302             h->GetBinXYZ(hbin, hbinx, hbiny, hbinz);
00303             Int_t pbin = p->GetBin( h->fXaxis.FindBin( h->GetXaxis()->GetBinCenter(hbinx) ),
00304                                     h->fYaxis.FindBin( h->GetYaxis()->GetBinCenter(hbiny) ),
00305                                     h->fZaxis.FindBin( h->GetZaxis()->GetBinCenter(hbinz) ) );
00306             if ( p->GetDimension() == 1 )
00307                // This is because the method p->GetBin is not giving
00308                // the proper bin number when the profiles are
00309                // different! This hack is made to make the behaviour
00310                // consistent with the previous implementation.
00311                pbin = p->fXaxis.FindBin(h->GetBinCenter(hbin));
00312             p->fArray[pbin]             += h->GetW()[hbin];
00313             p->fSumw2.fArray[pbin]      += h->GetW2()[hbin];
00314             p->fBinEntries.fArray[pbin] += h->GetB()[hbin];
00315             if (p->fBinSumw2.fN) { 
00316                if ( h->GetB2() ) p->fBinSumw2.fArray[pbin] += h->GetB2()[hbin];
00317                else p->fBinSumw2.fArray[pbin] += h->GetB()[hbin];
00318             }
00319          }
00320       }
00321    }
00322    if (canRebin) p->SetBit(TH1::kCanRebin);
00323 
00324    //copy merged stats
00325    p->PutStats(totstats);
00326    p->SetEntries(nentries);
00327    inlist.Remove(hclone);
00328    delete hclone;
00329    return (Long64_t)nentries;
00330 }
00331 
00332 template <typename T>
00333 T* TProfileHelper::RebinAxis(T* p, Double_t x, TAxis *axis)
00334 {
00335 // Profile histogram is resized along axis such that x is in the axis range.
00336 // The new axis limits are recomputed by doubling iteratively
00337 // the current axis range until the specified value x is within the limits.
00338 // The algorithm makes a copy of the histogram, then loops on all bins
00339 // of the old histogram to fill the rebinned histogram.
00340 // Takes into account errors (Sumw2) if any.
00341 // The bit kCanRebin must be set before invoking this function.
00342 //  Ex:  h->SetBit(TH1::kCanRebin);
00343 
00344    if (!p->TestBit(TH1::kCanRebin)) return 0;
00345    if (axis->GetXmin() >= axis->GetXmax()) return 0;
00346    if (axis->GetNbins() <= 0) return 0;
00347 
00348    Double_t xmin, xmax;
00349    if (!p->FindNewAxisLimits(axis, x, xmin, xmax))
00350       return 0;
00351 
00352    //save a copy of this histogram
00353    T *hold = (T*)p->Clone();
00354    hold->SetDirectory(0);
00355    //set new axis limits
00356    axis->SetLimits(xmin,xmax);
00357    if (p->fBinSumw2.fN) hold->Sumw2();
00358 
00359    Int_t  nbinsx = p->fXaxis.GetNbins();
00360    Int_t  nbinsy = p->fYaxis.GetNbins();
00361    Int_t  nbinsz = p->fZaxis.GetNbins();
00362 
00363    //now loop on all bins and refill
00364    p->Reset("ICE"); //reset only Integral, contents and Errors
00365 
00366    Double_t bx,by,bz;
00367    Int_t ix, iy, iz, binx, biny, binz;
00368    for (binz=1;binz<=nbinsz;binz++) {
00369       bz  = hold->GetZaxis()->GetBinCenter(binz);
00370       iz  = p->fZaxis.FindFixBin(bz);
00371       for (biny=1;biny<=nbinsy;biny++) {
00372          by  = hold->GetYaxis()->GetBinCenter(biny);
00373          iy  = p->fYaxis.FindFixBin(by);
00374          for (binx=1;binx<=nbinsx;binx++) {
00375             bx = hold->GetXaxis()->GetBinCenter(binx);
00376             ix  = p->fXaxis.FindFixBin(bx);
00377 
00378             Int_t sourceBin = hold->GetBin(binx,biny,binz);
00379             Int_t destinationBin = p->GetBin(ix,iy,iz);
00380             p->AddBinContent(destinationBin, hold->fArray[sourceBin]);
00381             p->fBinEntries.fArray[destinationBin] += hold->fBinEntries.fArray[sourceBin];
00382             p->fSumw2.fArray[destinationBin] += hold->fSumw2.fArray[sourceBin];
00383             if (p->fBinSumw2.fN) p->fBinSumw2.fArray[destinationBin] += hold->fBinSumw2.fArray[sourceBin];
00384          }
00385       }
00386    }
00387    return hold;
00388 }
00389 
00390 template <typename T>
00391 void TProfileHelper::Scale(T* p, Double_t c1, Option_t *)
00392 {
00393    Double_t ac1 = TMath::Abs(c1);
00394 
00395    // Make the loop over the bins to calculate the Addition
00396    Int_t bin;
00397    Double_t *cu1 = p->GetW();
00398    Double_t *er1 = p->GetW2();
00399    Double_t *en1 = p->GetB();
00400    for (bin=0;bin<p->fN;bin++) {
00401       p->fArray[bin]             = c1*cu1[bin];
00402       p->fSumw2.fArray[bin]      = ac1*ac1*er1[bin];
00403       p->fBinEntries.fArray[bin] = en1[bin];
00404    }
00405 }
00406 
00407 template <typename T>
00408 void TProfileHelper::Sumw2(T* p)
00409 {
00410    // Create structure to store sum of squares of weights per bin  *-*-*-*-*-*-*-*
00411    //   This is needed to compute  the correct statistical quantities  
00412    //    of a profile filled with weights 
00413    //  
00414    //
00415    //  This function is automatically called when the histogram is created
00416    //  if the static function TH1::SetDefaultSumw2 has been called before.
00417 
00418    if ( p->fBinSumw2.fN == p->fNcells) {
00419       if (!p->fgDefaultSumw2) 
00420          Warning("Sumw2","Sum of squares of profile bin weights structure already created");
00421       return;
00422    }
00423 
00424    p->fBinSumw2.Set(p->fNcells);
00425 
00426    // by default fill with the sum of weights which are stored in fBinEntries
00427    for (Int_t bin=0; bin<p->fNcells; bin++) {
00428       p->fBinSumw2.fArray[bin] = p->fBinEntries.fArray[bin]; 
00429    }
00430 }
00431 
00432 template <typename T>
00433 void TProfileHelper::LabelsDeflate(T* p, Option_t *ax)
00434 {
00435    // Reduce the number of bins for this axis to the number of bins having a label.
00436    // Works only for the given axis passed in the option
00437    // The method will remove only the extra bins existing after the last "labeled" bin.
00438    // Note that if there are "un-labeled" bins present between "labeled" bins they will not be removed 
00439 
00440 
00441    TAxis *axis = p->GetXaxis();
00442    if (ax[0] == 'y' || ax[0] == 'Y') axis = p->GetYaxis();
00443    if (ax[0] == 'z' || ax[0] == 'Z') axis = p->GetZaxis();
00444    if (!axis) {
00445       Error("LabelsDeflate","Invalid axis option %s",ax);
00446       return;
00447    }
00448    if (!axis->GetLabels()) return;
00449 
00450    // find bin with last labels 
00451    // bin number is object ID in list of labels 
00452    // therefore max bin number is number of bins of the deflated histograms
00453    TIter next(axis->GetLabels());
00454    TObject *obj;
00455    Int_t nbins = 0;
00456    while ((obj = next())) {
00457       Int_t ibin = obj->GetUniqueID();
00458       if (ibin > nbins) nbins = ibin; 
00459    }
00460    if (nbins < 1) nbins = 1;
00461    T *hold = (T*)p->Clone();
00462    hold->SetDirectory(0);
00463 
00464 
00465    Double_t xmin = axis->GetXmin();
00466    Double_t xmax = axis->GetBinUpEdge(nbins);
00467    axis->SetRange(0,0);
00468    // set the new bins and range
00469    axis->Set(nbins,xmin,xmax);
00470    p->SetBinsLength(-1); // reset the number of cells
00471    p->fBinEntries.Set(p->fN);
00472    p->fSumw2.Set(p->fN);
00473    if (p->fBinSumw2.fN)  p->fBinSumw2.Set(p->fN);
00474 
00475    // reset the content
00476    p->Reset("ICE");
00477 
00478    //now loop on all bins and refill
00479    Int_t bin,binx,biny,binz;
00480    for (bin =0; bin < hold->fN; ++bin)
00481    {
00482       hold->GetBinXYZ(bin, binx, biny, binz);
00483       Int_t ibin = p->GetBin(binx, biny, binz);
00484       p->fArray[ibin] += hold->fArray[bin];
00485       p->fBinEntries.fArray[ibin] += hold->fBinEntries.fArray[bin];
00486       p->fSumw2.fArray[ibin] += hold->fSumw2.fArray[bin];
00487       if (p->fBinSumw2.fN) p->fBinSumw2.fArray[ibin] += hold->fBinSumw2.fArray[bin];
00488    }
00489 
00490    delete hold;
00491 }
00492 
00493 template <typename T>
00494 void TProfileHelper::LabelsInflate(T* p, Option_t *ax)
00495 {
00496 // Double the number of bins for axis.
00497 // Refill histogram
00498 // This function is called by TAxis::FindBin(const char *label)
00499 // Works only for the given axis
00500 
00501    TAxis *axis = p->GetXaxis();
00502    if (ax[0] == 'y' || ax[0] == 'Y') axis = p->GetYaxis();
00503    T *hold = (T*)p->Clone();
00504    hold->SetDirectory(0);
00505 
00506    Int_t  nbxold = p->fXaxis.GetNbins();
00507    Int_t  nbyold = p->fYaxis.GetNbins();
00508    Int_t  nbins  = axis->GetNbins();
00509    Double_t xmin = axis->GetXmin();
00510    Double_t xmax = axis->GetXmax();
00511    xmax = xmin + 2*(xmax-xmin);
00512    axis->SetRange(0,0);
00513    // double the number of bins
00514    nbins *= 2;
00515    axis->Set(nbins,xmin,xmax);
00516    // reset the array of content according to the axis
00517    p->SetBinsLength(-1);  
00518    Int_t ncells = p->fN;
00519    p->fBinEntries.Set(ncells);
00520    p->fSumw2.Set(ncells);
00521    if (p->fBinSumw2.fN)  p->fBinSumw2.Set(ncells);
00522 
00523    //now loop on all bins and refill
00524    for (Int_t ibin =0; ibin < p->fN; ibin++)
00525    {
00526       Int_t binx, biny, binz;
00527       p->GetBinXYZ(ibin, binx, biny, binz);
00528       if (binx <= nbxold && biny <= nbyold) {
00529          Int_t bin = hold->GetBin(binx, biny, binz);
00530          p->fArray[ibin] = hold->fArray[bin];
00531          p->fBinEntries.fArray[ibin] = hold->fBinEntries.fArray[bin];
00532          p->fSumw2.fArray[ibin] = hold->fSumw2.fArray[bin];
00533          if (p->fBinSumw2.fN) p->fBinSumw2.fArray[ibin] = hold->fBinSumw2.fArray[bin];
00534       } else {
00535          p->fArray[ibin] = 0;
00536          p->fBinEntries.fArray[ibin] = 0;
00537          p->fSumw2.fArray[ibin] = 0;
00538          if (p->fBinSumw2.fN) p->fBinSumw2.fArray[ibin] = 0;
00539       }
00540    }
00541    delete hold;
00542 }
00543 
00544 template <typename T>
00545 Double_t TProfileHelper::GetBinError(T* p, Int_t bin)
00546 {
00547 
00548    if (p->fBuffer) p->BufferEmpty();
00549 
00550    if (bin < 0 || bin >= p->fNcells) return 0;
00551    Double_t cont = p->fArray[bin];
00552    Double_t sum  = p->fBinEntries.fArray[bin];
00553    Double_t err2 = p->fSumw2.fArray[bin];
00554    Double_t neff = p->GetBinEffectiveEntries(bin);
00555    if (sum == 0) return 0;
00556    Double_t contsum = cont/sum;
00557    Double_t eprim2  = TMath::Abs(err2/sum - contsum*contsum);
00558    Double_t eprim   = TMath::Sqrt(eprim2);
00559    Double_t test = 1;
00560    if (err2 != 0 && neff < 5) test = eprim2*sum/err2;
00561    //Int_t cellLimit = (p->GetDimension() == 3)?1000404:10404;
00562    if (p->fgApproximate && p->fNcells <=1000404 && (test < 1.e-4 || eprim2 < 1e-6)) { //3.04
00563       Double_t scont, ssum, serr2;
00564       scont = ssum = serr2 = 0;
00565       for (Int_t i=1;i<p->fNcells;i++) {
00566          if (p->fSumw2.fArray[i] <= 0) continue; //added in 3.10/02
00567          scont += p->fArray[i];
00568          ssum  += p->fBinEntries.fArray[i];
00569          serr2 += p->fSumw2.fArray[i];
00570       }
00571       Double_t scontsum = scont/ssum;
00572       Double_t seprim2  = TMath::Abs(serr2/ssum - scontsum*scontsum);
00573       eprim           = 2*TMath::Sqrt(seprim2);
00574       sum = ssum;
00575    }
00576    sum = TMath::Abs(sum);
00577    if (p->fErrorMode == kERRORMEAN) return eprim/TMath::Sqrt(neff);
00578    else if (p->fErrorMode == kERRORSPREAD) return eprim;
00579    else if (p->fErrorMode == kERRORSPREADI) {
00580       if (eprim != 0) return eprim/TMath::Sqrt(neff);
00581       return 1/TMath::Sqrt(12*neff);
00582    }
00583    else if (p->fErrorMode == kERRORSPREADG) {
00584       // it is supposed the values y are gaussian distributed y +/- dy
00585       return 1./TMath::Sqrt(sum);
00586    }
00587    else return eprim;
00588 }
00589 
00590 #endif

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