THStack.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: THStack.cxx 35994 2010-10-01 12:31:26Z couet $
00002 // Author: Rene Brun   10/12/2001
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TROOT.h"
00013 #include "TClassRef.h"
00014 #include "THStack.h"
00015 #include "TVirtualPad.h"
00016 #include "TVirtualHistPainter.h"
00017 #include "THashList.h"
00018 #include "TH2.h"
00019 #include "TH3.h"
00020 #include "TList.h"
00021 #include "TStyle.h"
00022 #include "Riostream.h"
00023 #include "TBrowser.h"
00024 #include "TMath.h"
00025 #include "TObjString.h"
00026 
00027 ClassImp(THStack)
00028 
00029 //______________________________________________________________________________
00030 //
00031 //   A THStack is a collection of TH1 (or derived) objects
00032 //   Use THStack::Add to add a new histogram to the list.
00033 //   The THStack does not own the objects in the list.
00034 //   By default (if option "nostack" is not specified), histograms will be paint
00035 //   stacked on top of each other.
00036 //   Example;
00037 //      THStack hs("hs","test stacked histograms");
00038 //      TH1F *h1 = new TH1F("h1","test hstack",100,-4,4);
00039 //      h1->FillRandom("gaus",20000);
00040 //      h1->SetFillColor(kRed);
00041 //      hs.Add(h1);
00042 //      TH1F *h2 = new TH1F("h2","test hstack",100,-4,4);
00043 //      h2->FillRandom("gaus",15000);
00044 //      h2->SetFillColor(kBlue);
00045 //      hs.Add(h2);
00046 //      TH1F *h3 = new TH1F("h3","test hstack",100,-4,4);
00047 //      h3->FillRandom("gaus",10000);
00048 //      h3->SetFillColor(kGreen);
00049 //      hs.Add(h3);
00050 //      TCanvas c1("c1","stacked hists",10,10,700,900);
00051 //      c1.Divide(1,2);
00052 //      c1.cd(1);
00053 //      hs.Draw();
00054 //      c1.cd(2);
00055 //      hs->Draw("nostack");
00056 //
00057 //  See a more complex example in $ROOTSYS/tutorials/hist/hstack.C
00058 //
00059 //  Note that picking is supported for all drawing modes.
00060 
00061 //______________________________________________________________________________
00062 THStack::THStack(): TNamed()
00063 {
00064 // THStack default constructor
00065 
00066    fHists     = 0;
00067    fStack     = 0;
00068    fHistogram = 0;
00069    fMaximum   = -1111;
00070    fMinimum   = -1111;
00071 }
00072 
00073 //______________________________________________________________________________
00074 THStack::THStack(const char *name, const char *title)
00075        : TNamed(name,title)
00076 {
00077 // constructor with name and title
00078    fHists     = 0;
00079    fStack     = 0;
00080    fHistogram = 0;
00081    fMaximum   = -1111;
00082    fMinimum   = -1111;
00083    gROOT->GetListOfCleanups()->Add(this);
00084 }
00085 
00086 
00087 //______________________________________________________________________________
00088 THStack::THStack(const TH1* hist, Option_t *axis /*="x"*/,
00089                  const char *name /*=0*/, const char *title /*=0*/,
00090                  Int_t firstbin /*=1*/, Int_t lastbin /*=-1*/,
00091                  Int_t firstbin2 /*=1*/, Int_t lastbin2 /*=-1*/,
00092                  Option_t* proj_option /*=""*/, Option_t* draw_option /*=""*/): TNamed(name, title) {
00093 // Creates a new THStack from a TH2 or TH3
00094 // It is filled with the 1D histograms from GetProjectionX or GetProjectionY
00095 // for each bin of the histogram. It illustrates the differences and total
00096 // sum along an axis.
00097 //
00098 // Parameters:
00099 // - hist:  the histogram used for the projections. Can be an object deriving
00100 //          from TH2 or TH3.
00101 // - axis:  for TH2: "x" for ProjectionX, "y" for ProjectionY.
00102 //          for TH3: see TH3::Project3D.
00103 // - name:  fName is set to name if given, otherwise to histo's name with
00104 //          "_stack_<axis>" appended, where <axis> is the value of the
00105 //          parameter axis.
00106 // - title: fTitle is set to title if given, otherwise to histo's title
00107 //          with ", stack of <axis> projections" appended.
00108 // - firstbin, lastbin:
00109 //          for each bin within [firstbin,lastbin] a stack entry is created.
00110 //          See TH2::ProjectionX/Y for use overflow bins.
00111 //          Defaults to "all bins but under- / overflow"
00112 // - firstbin2, lastbin2:
00113 //          Other axis range for TH3::Project3D, defaults to "all bins but
00114 //          under- / overflow". Ignored for TH2s
00115 // - proj_option:
00116 //          option passed to TH2::ProjectionX/Y and TH3::Project3D (along
00117 //          with axis)
00118 // - draw_option:
00119 //          option passed to THStack::Add.
00120    fHists     = 0;
00121    fStack     = 0;
00122    fHistogram = 0;
00123    fMaximum   = -1111;
00124    fMinimum   = -1111;
00125    gROOT->GetListOfCleanups()->Add(this);
00126 
00127    if (!axis) {
00128       Warning("THStack", "Need an axis.");
00129       return;
00130    }
00131    if (!hist) {
00132       Warning("THStack", "Need a histogram.");
00133       return;
00134    }
00135    Bool_t isTH2=hist->IsA()->InheritsFrom(TH2::Class());
00136    Bool_t isTH3=hist->IsA()->InheritsFrom(TH3::Class());
00137    if (!isTH2 && !isTH3) {
00138       Warning("THStack", "Need a histogram deriving from TH2 or TH3.");
00139       return;
00140    }
00141 
00142    if (!fName.Length())
00143       fName=Form("%s_stack%s", hist->GetName(), axis);
00144    if (!fTitle.Length()) {
00145       if (hist->GetTitle() && strlen(hist->GetTitle()))
00146          fTitle=Form("%s, stack of %s projections", hist->GetTitle(), axis);
00147       else
00148          fTitle=Form("stack of %s projections", axis);
00149    }
00150 
00151    if (isTH2) {
00152       TH2* hist2=(TH2*) hist;
00153       Bool_t useX=(strchr(axis,'x')) || (strchr(axis,'X'));
00154       Bool_t useY=(strchr(axis,'y')) || (strchr(axis,'Y'));
00155       if ((!useX && !useY) || (useX && useY)) {
00156          Warning("THStack", "Need parameter axis=\"x\" or \"y\" for a TH2, not none or both.");
00157          return;
00158       }
00159       TAxis* haxis= useX ? hist->GetYaxis() : hist->GetXaxis();
00160       if (!haxis) {
00161          Warning("HStack","Histogram axis is NULL");
00162          return;
00163       }
00164       Int_t nbins = haxis->GetNbins();
00165       if (firstbin < 0) firstbin = 1;
00166       if (lastbin  < 0) lastbin  = nbins;
00167       if (lastbin  > nbins+1) lastbin = nbins;
00168       for (Int_t iBin=firstbin; iBin<=lastbin; iBin++) {
00169          TH1* hProj=0;
00170          if (useX) hProj=hist2->ProjectionX(Form("%s_px%d",hist2->GetName(), iBin),
00171                                             iBin, iBin, proj_option);
00172          else hProj=hist2->ProjectionY(Form("%s_py%d",hist2->GetName(), iBin),
00173                                        iBin, iBin, proj_option);
00174          Add(hProj, draw_option);
00175       }
00176    } else {
00177       // hist is a TH3
00178       TH3* hist3=(TH3*) hist;
00179       TString sAxis(axis);
00180       sAxis.ToLower();
00181       Int_t dim=3-sAxis.Length();
00182       if (dim<1 || dim>2) {
00183          Warning("THStack", "Invalid length for parameter axis.");
00184          return;
00185       }
00186 
00187       if (dim==1) {
00188          TAxis* haxis = 0;
00189          // look for the haxis _not_ in axis
00190          if (sAxis.First('x')==kNPOS)
00191             haxis=hist->GetXaxis();
00192          else if (sAxis.First('y')==kNPOS)
00193             haxis=hist->GetYaxis();
00194          else if (sAxis.First('z')==kNPOS)
00195             haxis=hist->GetZaxis();
00196          if (!haxis) {
00197             Warning("HStack","Histogram axis is NULL");
00198             return;
00199          }
00200 
00201          Int_t nbins = haxis->GetNbins();
00202          if (firstbin < 0) firstbin = 1;
00203          if (lastbin  < 0) lastbin  = nbins;
00204          if (lastbin  > nbins+1) lastbin = nbins;
00205          Int_t iFirstOld=haxis->GetFirst();
00206          Int_t iLastOld=haxis->GetLast();
00207          for (Int_t iBin=firstbin; iBin<=lastbin; iBin++) {
00208             haxis->SetRange(iBin, iBin);
00209             // build projection named axis_iBin (passed through "option")
00210             TH1* hProj=hist3->Project3D(Form("%s_%s%s_%d", hist3->GetName(),
00211                                              axis, proj_option, iBin));
00212             Add(hProj, draw_option);
00213          }
00214          haxis->SetRange(iFirstOld, iLastOld);
00215       }  else {
00216          // if dim==2
00217          TAxis* haxis1 = 0;
00218          TAxis* haxis2 = 0;
00219          // look for the haxis _not_ in axis
00220          if (sAxis.First('x')!=kNPOS) {
00221             haxis1=hist->GetYaxis();
00222             haxis2=hist->GetZaxis();
00223          } else if (sAxis.First('y')!=kNPOS) {
00224             haxis1=hist->GetXaxis();
00225             haxis2=hist->GetZaxis();
00226          } else if (sAxis.First('z')!=kNPOS) {
00227             haxis1=hist->GetXaxis();
00228             haxis2=hist->GetYaxis();
00229          }
00230          if (!haxis1 || !haxis2) {
00231             Warning("HStack","Histogram axis is NULL");
00232             return;
00233          }
00234 
00235          Int_t nbins1 = haxis1->GetNbins();
00236          Int_t nbins2 = haxis2->GetNbins();
00237          if (firstbin < 0) firstbin = 1;
00238          if (lastbin  < 0) lastbin  = nbins1;
00239          if (lastbin  > nbins1+1) lastbin = nbins1;
00240          if (firstbin2 < 0) firstbin2 = 1;
00241          if (lastbin2  < 0) lastbin2  = nbins2;
00242          if (lastbin2  > nbins2+1) lastbin2 = nbins2;
00243          Int_t iFirstOld1=haxis1->GetFirst();
00244          Int_t iLastOld1=haxis1->GetLast();
00245          Int_t iFirstOld2=haxis2->GetFirst();
00246          Int_t iLastOld2=haxis2->GetLast();
00247          for (Int_t iBin=firstbin; iBin<=lastbin; iBin++) {
00248             haxis1->SetRange(iBin, iBin);
00249             for (Int_t jBin=firstbin2; jBin<=lastbin2; jBin++) {
00250                haxis2->SetRange(jBin, jBin);
00251                // build projection named axis_iBin (passed through "option")
00252                TH1* hProj=hist3->Project3D(Form("%s_%s%s_%d", hist3->GetName(),
00253                                                 axis, proj_option, iBin));
00254                Add(hProj, draw_option);
00255             }
00256          }
00257          haxis1->SetRange(iFirstOld1, iLastOld1);
00258          haxis2->SetRange(iFirstOld2, iLastOld2);
00259       }
00260    } // if hist is TH2 or TH3
00261 }
00262 
00263 //______________________________________________________________________________
00264 THStack::~THStack()
00265 {
00266 // THStack destructor
00267 
00268 
00269    gROOT->GetListOfCleanups()->Remove(this);
00270    if (!fHists) return;
00271    fHists->Clear("nodelete");
00272    delete fHists;
00273    fHists = 0;
00274    if (fStack) {fStack->Delete(); delete fStack;}
00275    delete fHistogram;
00276    fHistogram = 0;
00277 }
00278 
00279 //______________________________________________________________________________
00280 THStack::THStack(const THStack &hstack) :
00281    TNamed(hstack),
00282    fHists(0),
00283    fStack(0),
00284    fHistogram(0),
00285    fMaximum(hstack.fMaximum),
00286    fMinimum(hstack.fMinimum)
00287 {
00288    // THStack copy constructor
00289 
00290    if (hstack.GetHists()) {
00291       TIter next(hstack.GetHists());
00292       TH1 *h;
00293       while ((h=(TH1*)next())) Add(h);
00294    }
00295 }
00296 
00297 //______________________________________________________________________________
00298 void THStack::Add(TH1 *h1, Option_t *option)
00299 {
00300    // add a new histogram to the list
00301    // Only 1-d and 2-d histograms currently supported.
00302    // A drawing option may be specified
00303 
00304    if (!h1) return;
00305    if (h1->GetDimension() > 2) {
00306       Error("Add","THStack supports only 1-d and 2-d histograms");
00307       return;
00308    }
00309    if (!fHists) fHists = new TList();
00310    fHists->Add(h1,option);
00311    Modified(); //invalidate stack
00312 }
00313 
00314 //______________________________________________________________________________
00315 void THStack::Browse(TBrowser *b)
00316 {
00317    // Browse.
00318 
00319    Draw(b ? b->GetDrawOption() : "");
00320    gPad->Update();
00321 }
00322 
00323 //______________________________________________________________________________
00324 void THStack::BuildStack()
00325 {
00326    //  build sum of all histograms
00327    //  Build a separate list fStack containing the running sum of all histograms
00328 
00329    if (fStack) return;
00330    if (!fHists) return;
00331    Int_t nhists = fHists->GetSize();
00332    if (!nhists) return;
00333    fStack = new TObjArray(nhists);
00334    Bool_t add = TH1::AddDirectoryStatus();
00335    TH1::AddDirectory(kFALSE);
00336    TH1 *h = (TH1*)fHists->At(0)->Clone();
00337    fStack->Add(h);
00338    for (Int_t i=1;i<nhists;i++) {
00339       h = (TH1*)fHists->At(i)->Clone();
00340       h->Add((TH1*)fStack->At(i-1));
00341       fStack->AddAt(h,i);
00342    }
00343    TH1::AddDirectory(add);
00344 }
00345 
00346 //______________________________________________________________________________
00347 Int_t THStack::DistancetoPrimitive(Int_t px, Int_t py)
00348 {
00349    // Compute distance from point px,py to each graph
00350    //
00351 
00352    //*-*- Are we on the axis?
00353    const Int_t kMaxDiff = 10;
00354    Int_t distance = 9999;
00355    if (fHistogram) {
00356       distance = fHistogram->DistancetoPrimitive(px,py);
00357       if (distance <= 0) {return distance;}
00358       if (distance <= 1) {gPad->SetSelected(fHistogram);return distance;}
00359    }
00360 
00361 
00362    //*-*- Loop on the list of histograms
00363    if (!fHists) return distance;
00364    TH1 *h = 0;
00365    const char *doption = GetDrawOption();
00366    Int_t nhists = fHists->GetSize();
00367    for (Int_t i=0;i<nhists;i++) {
00368       h = (TH1*)fHists->At(i);
00369       if (fStack && !strstr(doption,"nostack")) h = (TH1*)fStack->At(i);
00370       Int_t dist = h->DistancetoPrimitive(px,py);
00371       if (dist <= 0) return 0;
00372       if (dist < kMaxDiff) {
00373          gPad->SetSelected(fHists->At(i));
00374          gPad->SetCursor(kPointer);
00375          return dist;
00376       }
00377    }
00378    return distance;
00379 }
00380 
00381 //______________________________________________________________________________
00382 void THStack::Draw(Option_t *option)
00383 {
00384    // Draw this multihist with its current attributes.
00385    //
00386    //   Options to draw histograms  are described in THistPainter::Paint
00387    // By default (if option "nostack" is not specified), histograms will be paint
00388    // stacked on top of each other.
00389 
00390    TString opt = option;
00391    opt.ToLower();
00392    if (gPad) {
00393       if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
00394       if (!opt.Contains("same")) {
00395          //the following statement is necessary in case one attempts to draw
00396          //a temporary histogram already in the current pad
00397          if (TestBit(kCanDelete)) gPad->GetListOfPrimitives()->Remove(this);
00398          gPad->Clear();
00399       }
00400    }
00401    AppendPad(opt.Data());
00402 }
00403 
00404 //______________________________________________________________________________
00405 TH1 *THStack::GetHistogram() const
00406 {
00407    //    Returns a pointer to the histogram used to draw the axis
00408    //    Takes into account the two following cases.
00409    //       1- option 'A' was specified in THStack::Draw. Return fHistogram
00410    //       2- user had called TPad::DrawFrame. return pointer to hframe histogram
00411    //
00412    // IMPORTANT NOTE
00413    //  You must call Draw before calling this function. The returned histogram
00414    //  depends on the selected Draw options.
00415 
00416    if (fHistogram) return fHistogram;
00417    if (!gPad) return 0;
00418    gPad->Modified();
00419    gPad->Update();
00420    if (fHistogram) return fHistogram;
00421    TH1 *h1 = (TH1*)gPad->FindObject("hframe");
00422    return h1;
00423 }
00424 
00425 //______________________________________________________________________________
00426 Double_t THStack::GetMaximum(Option_t *option)
00427 {
00428    //  returns the maximum of all added histograms
00429    //  returns the maximum of all histograms if option "nostack".
00430 
00431    TString opt = option;
00432    opt.ToLower();
00433    Bool_t lerr = kFALSE;
00434    if (opt.Contains("e")) lerr = kTRUE;
00435    Double_t them=0, themax = -1e300, c1, e1;
00436    if (!fHists) return 0;
00437    Int_t nhists = fHists->GetSize();
00438    TH1 *h;
00439    Int_t first,last;
00440 
00441    if (!opt.Contains("nostack")) {
00442       BuildStack();
00443       h = (TH1*)fStack->At(nhists-1);
00444       themax = h->GetMaximum();
00445    } else {
00446       for (Int_t i=0;i<nhists;i++) {
00447          h = (TH1*)fHists->At(i);
00448          them = h->GetMaximum();
00449          if (them > themax) themax = them;
00450       }
00451    }
00452 
00453    if (lerr) {
00454       for (Int_t i=0;i<nhists;i++) {
00455          h = (TH1*)fHists->At(i);
00456          first = h->GetXaxis()->GetFirst();
00457          last  = h->GetXaxis()->GetLast();
00458          for (Int_t j=first; j<=last;j++) {
00459             e1     = h->GetBinError(j);
00460             c1     = h->GetBinContent(j);
00461             themax = TMath::Max(themax,c1+e1);
00462          }
00463       }
00464    }
00465 
00466    return themax;
00467 }
00468 
00469 //______________________________________________________________________________
00470 Double_t THStack::GetMinimum(Option_t *option)
00471 {
00472    //  returns the minimum of all added histograms
00473    //  returns the minimum of all histograms if option "nostack".
00474 
00475    TString opt = option;
00476    opt.ToLower();
00477    Bool_t lerr = kFALSE;
00478    if (opt.Contains("e")) lerr = kTRUE;
00479    Double_t them=0, themin = 1e300, c1, e1;
00480    if (!fHists) return 0;
00481    Int_t nhists = fHists->GetSize();
00482    Int_t first,last;
00483    TH1 *h;
00484 
00485    if (!opt.Contains("nostack")) {
00486       BuildStack();
00487       h = (TH1*)fStack->At(nhists-1);
00488       themin = h->GetMinimum();
00489    } else {
00490       for (Int_t i=0;i<nhists;i++) {
00491          h = (TH1*)fHists->At(i);
00492          them = h->GetMinimum();
00493          if (them <= 0 && gPad && gPad->GetLogy()) them = h->GetMinimum(0);
00494          if (them < themin) themin = them;
00495       }
00496    }
00497 
00498    if (lerr) {
00499       for (Int_t i=0;i<nhists;i++) {
00500          h = (TH1*)fHists->At(i);
00501          first = h->GetXaxis()->GetFirst();
00502          last  = h->GetXaxis()->GetLast();
00503          for (Int_t j=first; j<=last;j++) {
00504              e1     = h->GetBinError(j);
00505              c1     = h->GetBinContent(j);
00506              themin = TMath::Min(themin,c1-e1);
00507          }
00508       }
00509    }
00510 
00511    return themin;
00512 }
00513 
00514 //______________________________________________________________________________
00515 TObjArray *THStack::GetStack()
00516 {
00517    // Return pointer to Stack. Build it if not yet done
00518 
00519    BuildStack();
00520    return fStack;
00521 }
00522 
00523 //______________________________________________________________________________
00524 TAxis *THStack::GetXaxis() const
00525 {
00526    // Get x axis of the histogram used to draw the stack.
00527    //
00528    // IMPORTANT NOTE
00529    //  You must call Draw before calling this function. The returned histogram
00530    //  depends on the selected Draw options.
00531 
00532    if (!gPad) return 0;
00533    TH1 *h = GetHistogram();
00534    if (!h) return 0;
00535    return h->GetXaxis();
00536 }
00537 
00538 //______________________________________________________________________________
00539 TAxis *THStack::GetYaxis() const
00540 {
00541    // Get x axis of the histogram used to draw the stack.
00542    //
00543    // IMPORTANT NOTE
00544    //  You must call Draw before calling this function. The returned histogram
00545    //  depends on the selected Draw options.
00546 
00547    if (!gPad) return 0;
00548    TH1 *h = GetHistogram();
00549    if (!h) return 0;
00550    return h->GetYaxis();
00551 }
00552 
00553 //______________________________________________________________________________
00554 void THStack::ls(Option_t *option) const
00555 {
00556    // List histograms in the stack
00557 
00558    TROOT::IndentLevel();
00559    cout <<IsA()->GetName()
00560       <<" Name= "<<GetName()<<" Title= "<<GetTitle()<<" Option="<<option<<endl;
00561    TROOT::IncreaseDirLevel();
00562    if (fHists) fHists->ls(option);
00563    TROOT::DecreaseDirLevel();
00564 }
00565 
00566 //______________________________________________________________________________
00567 void THStack::Modified()
00568 {
00569    // invalidate sum of histograms
00570 
00571    if (!fStack) return;
00572    fStack->Delete();
00573    delete fStack;
00574    fStack = 0;
00575    delete fHistogram;
00576    fHistogram = 0;
00577 }
00578 
00579 //______________________________________________________________________________
00580 void THStack::Paint(Option_t *option)
00581 {
00582    // paint the list of histograms
00583    // By default, histograms are shown stacked.
00584    //    -the first histogram is paint
00585    //    -then the sum of the first and second, etc
00586    //
00587    // If option "nostack" is specified, histograms are all paint in the same pad
00588    // as if the option "same" had been specified.
00589    //
00590    // if option "pads" is specified, the current pad/canvas is subdivided into
00591    // a number of pads equal to the number of histograms and each histogram
00592    // is paint into a separate pad.
00593    //
00594    // See THistPainter::Paint for a list of valid options.
00595 
00596    if (!fHists) return;
00597    if (!fHists->GetSize()) return;
00598 
00599    TString opt = option;
00600    opt.ToLower();
00601    Bool_t lsame = kFALSE;
00602    if (opt.Contains("same")) {
00603       lsame = kTRUE;
00604       opt.ReplaceAll("same","");
00605    }
00606    if (opt.Contains("pads")) {
00607       Int_t npads = fHists->GetSize();
00608       TVirtualPad *padsav = gPad;
00609       //if pad is not already divided into subpads, divide it
00610       Int_t nps = 0;
00611       TObject *obj;
00612       TIter nextp(padsav->GetListOfPrimitives());
00613       while ((obj = nextp())) {
00614          if (obj->InheritsFrom(TVirtualPad::Class())) nps++;
00615       }
00616       if (nps < npads) {
00617          padsav->Clear();
00618          Int_t nx = (Int_t)TMath::Sqrt((Double_t)npads);
00619          if (nx*nx < npads) nx++;
00620          Int_t ny = nx;
00621          if (((nx*ny)-nx) >= npads) ny--;
00622          padsav->Divide(nx,ny);
00623       }
00624       TH1 *h;
00625       Int_t i = 0;
00626       TObjOptLink *lnk = (TObjOptLink*)fHists->FirstLink();
00627       while (lnk) {
00628          i++;
00629          padsav->cd(i);
00630          h = (TH1*)lnk->GetObject();
00631          h->Draw(lnk->GetOption());
00632          lnk = (TObjOptLink*)lnk->Next();
00633       }
00634       padsav->cd();
00635       return;
00636    }
00637 
00638    // compute the min/max of each axis
00639    TH1 *h;
00640    TIter next(fHists);
00641    Double_t xmin = 1e100;
00642    Double_t xmax = -xmin;
00643    Double_t ymin = 1e100;
00644    Double_t ymax = -xmin;
00645    while ((h=(TH1*)next())) {
00646       if (h->GetXaxis()->GetXmin() < xmin) xmin = h->GetXaxis()->GetXmin();
00647       if (h->GetXaxis()->GetXmax() > xmax) xmax = h->GetXaxis()->GetXmax();
00648       if (h->GetYaxis()->GetXmin() < ymin) ymin = h->GetYaxis()->GetXmin();
00649       if (h->GetYaxis()->GetXmax() > ymax) ymax = h->GetYaxis()->GetXmax();
00650    }
00651 
00652    char loption[32];
00653    snprintf(loption,31,"%s",opt.Data());
00654    char *nostack = strstr(loption,"nostack");
00655    // do not delete the stack. Another pad may contain the same object
00656    // drawn in stack mode!
00657    //if (nostack && fStack) {fStack->Delete(); delete fStack; fStack = 0;}
00658 
00659    if (!opt.Contains("nostack")) BuildStack();
00660 
00661    Double_t themax,themin;
00662    if (fMaximum == -1111) themax = GetMaximum(option);
00663    else                   themax = fMaximum;
00664    if (fMinimum == -1111) {
00665       themin = GetMinimum(option);
00666       if (gPad->GetLogy()){
00667          if (themin>0)  themin *= .9;
00668          else           themin = themax*1.e-3;
00669       }
00670       else if (themin > 0)
00671          themin = 0;
00672    }
00673    else                   themin = fMinimum;
00674    if (!fHistogram) {
00675       Bool_t add = TH1::AddDirectoryStatus();
00676       TH1::AddDirectory(kFALSE);
00677       h = (TH1*)fHists->At(0);
00678       TAxis *xaxis = h->GetXaxis();
00679       TAxis *yaxis = h->GetYaxis();
00680       if (h->GetDimension() > 1) {
00681          if (strlen(option) == 0) strlcpy(loption,"lego1",32);
00682          const TArrayD *xbins = xaxis->GetXbins();
00683          const TArrayD *ybins = yaxis->GetXbins();
00684          if (xbins->fN != 0 && ybins->fN != 0) {
00685             fHistogram = new TH2F(GetName(),GetTitle(),
00686                xaxis->GetNbins(), xbins->GetArray(),
00687                yaxis->GetNbins(), ybins->GetArray());
00688          } else if (xbins->fN != 0 && ybins->fN == 0) {
00689             fHistogram = new TH2F(GetName(),GetTitle(),
00690                xaxis->GetNbins(), xbins->GetArray(),
00691                yaxis->GetNbins(), ymin, ymax);
00692          } else if (xbins->fN == 0 && ybins->fN != 0) {
00693             fHistogram = new TH2F(GetName(),GetTitle(),
00694                xaxis->GetNbins(), xmin, xmax,
00695                yaxis->GetNbins(), ybins->GetArray());
00696          } else {
00697             fHistogram = new TH2F(GetName(),GetTitle(),
00698                xaxis->GetNbins(), xmin, xmax,
00699                yaxis->GetNbins(), ymin, ymax);
00700          }
00701       } else {
00702          fHistogram = new TH1F(GetName(),GetTitle(),xaxis->GetNbins(),xmin, xmax);
00703       }
00704       fHistogram->SetStats(0);
00705       TH1::AddDirectory(add);
00706    } else {
00707       fHistogram->SetTitle(GetTitle());
00708    }
00709 
00710    if (nostack) {*nostack = 0; strncat(nostack,nostack+7,7);}
00711    //if (nostack) {strlcpy(nostack,"       ",7);}
00712    else fHistogram->GetPainter()->SetStack(fHists);
00713 
00714    if (!fHistogram->TestBit(TH1::kIsZoomed)) {
00715       if (nostack && fMaximum != -1111) fHistogram->SetMaximum(fMaximum);
00716       else {
00717          if (gPad->GetLogy())           fHistogram->SetMaximum(themax*(1+0.2*TMath::Log10(themax/themin)));
00718          else                           fHistogram->SetMaximum((1+gStyle->GetHistTopMargin())*themax);
00719       }
00720       if (nostack && fMinimum != -1111) fHistogram->SetMinimum(fMinimum);
00721       else {
00722          if (gPad->GetLogy())           fHistogram->SetMinimum(themin/(1+0.5*TMath::Log10(themax/themin)));
00723          else                           fHistogram->SetMinimum(themin);
00724       }
00725    }
00726 
00727    // Copy the axis labels if needed.
00728    TH1 *hfirst;
00729    TObjOptLink *lnk = (TObjOptLink*)fHists->FirstLink();
00730    hfirst = (TH1*)lnk->GetObject();
00731    THashList* labels = hfirst->GetXaxis()->GetLabels();
00732    if (labels) {
00733       TIter iL(labels);
00734       TObjString* lb;
00735       Int_t ilab = 1;
00736       while ((lb=(TObjString*)iL())) {
00737          fHistogram->GetXaxis()->SetBinLabel(ilab,lb->String().Data());
00738          ilab++;
00739       }
00740    }
00741 
00742    if (!lsame) fHistogram->Paint(loption);
00743 
00744    if (fHistogram->GetDimension() > 1) SetDrawOption(loption);
00745    if (strstr(loption,"lego")) return;
00746 
00747    char noption[32];
00748    strlcpy(noption,loption,32);
00749    Int_t nhists = fHists->GetSize();
00750    if (nostack) {
00751       lnk = (TObjOptLink*)fHists->FirstLink();
00752       for (Int_t i=0;i<nhists;i++) {
00753          if (strstr(lnk->GetOption(),"same")) {
00754             snprintf(loption,31,"%s%s",noption,lnk->GetOption());
00755          } else {
00756             snprintf(loption,31,"%ssame%s",noption,lnk->GetOption());
00757          }
00758          fHists->At(i)->Paint(loption);
00759          lnk = (TObjOptLink*)lnk->Next();
00760       }
00761    } else {
00762       lnk = (TObjOptLink*)fHists->LastLink();
00763       TH1 *h1;
00764       Int_t h1col, h1fill;
00765       for (Int_t i=0;i<nhists;i++) {
00766          if (strstr(lnk->GetOption(),"same")) {
00767             snprintf(loption,31,"%s%s",noption,lnk->GetOption());
00768          } else {
00769             snprintf(loption,31,"%ssame%s",noption,lnk->GetOption());
00770          }
00771          h1 = (TH1*)fStack->At(nhists-i-1);
00772          if (i>0) {
00773             // Erase before drawing the histogram
00774             h1col  = h1->GetFillColor();
00775             h1fill = h1->GetFillStyle();
00776             h1->SetFillColor(0);
00777             h1->SetFillStyle(1001);
00778             h1->Paint(loption);
00779             static TClassRef clTFrame = TClass::GetClass("TFrame",kFALSE);
00780             TAttFill *frameFill = (TAttFill*)clTFrame->DynamicCast(TAttFill::Class(),gPad->GetFrame());
00781             h1->SetFillColor(frameFill->GetFillColor());
00782             h1->SetFillStyle(frameFill->GetFillStyle());
00783             h1->Paint(loption);
00784             h1->SetFillColor(h1col);
00785             h1->SetFillStyle(h1fill);
00786          }
00787          h1->Paint(loption);
00788          lnk = (TObjOptLink*)lnk->Prev();
00789       }
00790    }
00791    if (!lsame) fHistogram->Paint("axissame");
00792 }
00793 
00794 //______________________________________________________________________________
00795 void THStack::Print(Option_t *option) const
00796 {
00797    // Print the list of histograms
00798 
00799    TH1 *h;
00800    if (fHists) {
00801       TIter   next(fHists);
00802       while ((h = (TH1*) next())) {
00803          h->Print(option);
00804       }
00805    }
00806 }
00807 
00808 //______________________________________________________________________________
00809 void THStack::RecursiveRemove(TObject *obj)
00810 {
00811    // Recursively remove object from the list of histograms
00812 
00813    if (!fHists) return;
00814    fHists->RecursiveRemove(obj);
00815    while (fHists->IndexOf(obj) >= 0) fHists->Remove(obj);
00816 }
00817 
00818 //______________________________________________________________________________
00819 void THStack::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
00820 {
00821    // Save primitive as a C++ statement(s) on output stream out
00822 
00823    char quote = '"';
00824    out<<"   "<<endl;
00825    if (gROOT->ClassSaved(THStack::Class())) {
00826       out<<"   ";
00827    } else {
00828       out<<"   THStack *";
00829    }
00830    out<<GetName()<<" = new THStack();"<<endl;
00831    out<<"   "<<GetName()<<"->SetName("<<quote<<GetName()<<quote<<");"<<endl;
00832    out<<"   "<<GetName()<<"->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
00833 
00834    if (fMinimum != -1111) {
00835       out<<"   "<<GetName()<<"->SetMinimum("<<fMinimum<<");"<<endl;
00836    }
00837    if (fMaximum != -1111) {
00838       out<<"   "<<GetName()<<"->SetMaximum("<<fMaximum<<");"<<endl;
00839    }
00840 
00841    static Int_t frameNumber = 0;
00842    if (fHistogram) {
00843       frameNumber++;
00844       TString hname = fHistogram->GetName();
00845       hname += frameNumber;
00846       fHistogram->SetName(hname.Data());
00847       fHistogram->SavePrimitive(out,"nodraw");
00848       out<<"   "<<GetName()<<"->SetHistogram("<<fHistogram->GetName()<<");"<<endl;
00849       out<<"   "<<endl;
00850    }
00851 
00852    TH1 *h;
00853    if (fHists) {
00854       TObjOptLink *lnk = (TObjOptLink*)fHists->FirstLink();
00855       while (lnk) {
00856          h = (TH1*)lnk->GetObject();
00857          h->SavePrimitive(out,"nodraw");
00858          out<<"   "<<GetName()<<"->Add("<<h->GetName()<<","<<quote<<lnk->GetOption()<<quote<<");"<<endl;
00859          lnk = (TObjOptLink*)lnk->Next();
00860       }
00861    }
00862    out<<"   "<<GetName()<<"->Draw("
00863       <<quote<<option<<quote<<");"<<endl;
00864 }
00865 
00866 //______________________________________________________________________________
00867 void THStack::SetMaximum(Double_t maximum)
00868 {
00869    // Set maximum.
00870 
00871    fMaximum = maximum;
00872    if (fHistogram)  fHistogram->SetMaximum(maximum);
00873 }
00874 
00875 //______________________________________________________________________________
00876 void THStack::SetMinimum(Double_t minimum)
00877 {
00878    // Set minimum.
00879 
00880    fMinimum = minimum;
00881    if (fHistogram) fHistogram->SetMinimum(minimum);
00882 }

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