#include "Riostream.h"
#include "TROOT.h"
#include "TMath.h"
#include "TH2.h"
#include "TF2.h"
#include "TList.h"
#include "TGraph2D.h"
#include "TGraphDelaunay.h"
#include "TVirtualPad.h"
#include "TVirtualFitter.h"
#include "TClass.h"
ClassImp(TGraph2D)
/*
<img src="gif/graph2d.gif">
*/
//End_Html
/*
<img src="gif/graph2dfit.gif">
*/
//End_Html
/*
<img src="gif/dtvd.gif">
<br>
<a href="http://www.cs.cornell.edu/Info/People/chew/Delaunay.html">This applet</a>
gives a nice practical view of Delaunay triangulation and Voronoi diagram.
*/
//End_Html
TGraph2D::TGraph2D()
         : TNamed("Graph2D","Graph2D"), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(0)
{
   
   fSize      = 0;
   fMargin    = 0.;
   fNpx       = 40;
   fNpy       = 40;
   fDirectory = 0;
   fHistogram = 0;
   fMaximum   = -1111;
   fMinimum   = -1111;
   fX         = 0;
   fY         = 0;
   fZ         = 0;
   fZout      = 0;
   fMaxIter   = 100000;
   fPainter   = 0;
   fFunctions = new TList;
   fUserHisto = kFALSE;
}
TGraph2D::TGraph2D(Int_t n, Int_t *x, Int_t *y, Int_t *z)
         : TNamed("Graph2D","Graph2D"), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(n)
{
   
   Build(n);
   
   for (Int_t i=0; i<fNpoints; ++i) {
      fX[i] = (Double_t)x[i];
      fY[i] = (Double_t)y[i];
      fZ[i] = (Double_t)z[i];
   }
}
TGraph2D::TGraph2D(Int_t n, Float_t *x, Float_t *y, Float_t *z)
         : TNamed("Graph2D","Graph2D"), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(n)
{
   
   Build(n);
   
   for (Int_t i=0; i<fNpoints; ++i) {
      fX[i] = x[i];
      fY[i] = y[i];
      fZ[i] = z[i];
   }
}
TGraph2D::TGraph2D(Int_t n, Double_t *x, Double_t *y, Double_t *z)
         : TNamed("Graph2D","Graph2D"), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(n)
{
   
   Build(n);
   
   for (Int_t i=0; i<fNpoints; ++i) {
      fX[i] = x[i];
      fY[i] = y[i];
      fZ[i] = z[i];
   }
}
TGraph2D::TGraph2D(TH2 *h2)
         : TNamed("Graph2D","Graph2D"), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(0)
{
   
   
   Build(10);
   SetName(h2->GetName());
   SetTitle(h2->GetTitle());
   TAxis *xaxis = h2->GetXaxis();
   TAxis *yaxis = h2->GetYaxis();
   Int_t xfirst = xaxis->GetFirst();
   Int_t xlast  = xaxis->GetLast();
   Int_t yfirst = yaxis->GetFirst();
   Int_t ylast  = yaxis->GetLast();
   Double_t hmin = h2->GetMinimum();
   Double_t hmax = h2->GetMaximum();
   Double_t x, y, z;
   Int_t k=0;
   for (Int_t i=xfirst; i<= xlast; i++) {
      for (Int_t j=yfirst; j<= ylast; j++) {
         x = xaxis->GetBinCenter(i);
         y = yaxis->GetBinCenter(j);
         z = h2->GetBinContent(i,j);
         if (z>hmin && z<hmax) {
            SetPoint(k, x, y, z);
            k++;
         }
      }
   }
}
TGraph2D::TGraph2D(const char *name,const char *title,
                   Int_t n, Double_t *x, Double_t *y, Double_t *z)
         : TNamed(name,title), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(n)
{
   
   
   
   
   
   
   Build(n);
   
   for (Int_t i=0; i<fNpoints; ++i) {
      fX[i] = x[i];
      fY[i] = y[i];
      fZ[i] = z[i];
   }
}
TGraph2D::TGraph2D(Int_t n)
         : TNamed("Graph2D","Graph2D"), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(0)
{
   
   
   Build(n);
}
TGraph2D::TGraph2D(const char *filename, const char *format, Option_t *)
         : TNamed("Graph2D",filename), TAttLine(1,1,1), TAttFill(0,1001),
           TAttMarker(), fNpoints(0)
{
   
   
   Build(100);
   Double_t x,y,z;
   FILE *fp = fopen(filename,"r");
   if (!fp) {
      MakeZombie();
      Error("TGraph2D", "Cannot open file: %s, TGraph2D is Zombie",filename);
      return;
   }
   char line[80];
   Int_t np = 0;
   while (fgets(line,80,fp)) {
      sscanf(&line[0],format,&x, &y, &z);
      SetPoint(np,x,y,z);
      np++;
   }
   fclose(fp);
}
TGraph2D::TGraph2D(const TGraph2D &g)
         : TNamed(g), TAttLine(g), TAttFill(g), TAttMarker(g)
{
   
   fNpoints = g.fNpoints;
   Build(fNpoints);
   for (Int_t n=0; n<fNpoints; n++) {
      fX[n] = g.fX[n];
      fY[n] = g.fY[n];
      fZ[n] = g.fZ[n];
   }
}
TGraph2D::~TGraph2D()
{
   
   if (fX)          delete [] fX;
   if (fY)          delete [] fY;
   if (fZ)          delete [] fZ;
   if (fHistogram)  delete fHistogram;
   if (fFunctions) {
      fFunctions->SetBit(kInvalidObject);
      fFunctions->Delete();
      delete fFunctions;
   }
   if (fDirectory) {
      fDirectory->GetList()->Remove(this);
   }
   if (fPainter)  delete fPainter;
   fX         = 0;
   fY         = 0;
   fZ         = 0;
   fHistogram = 0;
   fDirectory = 0;
   fFunctions = 0;
}
TGraph2D TGraph2D::operator=(const TGraph2D &g)
{
   
   if (this == &g) return *this;
   fNpoints = g.fNpoints;
   Build(fNpoints);
   for (Int_t n=0; n<fNpoints; n++) {
      fX[n] = g.fX[n];
      fY[n] = g.fY[n];
      fZ[n] = g.fZ[n];
   }
   return g;
}
void TGraph2D::Build(Int_t n)
{
   
   if (n <= 0) {
      Error("TGraph2D", "Invalid number of points (%d)", n);
      return;
   }
   fSize      = n;
   fMargin    = 0.;
   fNpx       = 40;
   fNpy       = 40;
   fDirectory = 0;
   fHistogram = 0;
   fMaximum   = -1111;
   fMinimum   = -1111;
   fX         = new Double_t[fSize];
   fY         = new Double_t[fSize];
   fZ         = new Double_t[fSize];
   fZout      = 0;
   fMaxIter   = 100000;
   fFunctions = new TList;
   fPainter   = 0;
   fUserHisto = kFALSE;
   Bool_t add = TH1::AddDirectoryStatus();
   if (add && gDirectory) {
      TObject *old = (TObject*)gDirectory->GetList()->FindObject(GetName());
      if (old) {
         Warning("Build","Replacing existing 2D graph: %s (Potential memory leak).",GetName());
         gDirectory->GetList()->Remove(old);
      }
      gDirectory->Append(this);
      fDirectory = gDirectory;
   }
}
Int_t TGraph2D::DistancetoPrimitive(Int_t px, Int_t py)
{
   
   Int_t distance = 9999;
   if (fHistogram) distance = fHistogram->DistancetoPrimitive(px,py);
   return distance;
}
void TGraph2D::Draw(Option_t *option)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   TString opt = option;
   opt.ToLower();
   if (gPad) {
      if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
      if (!opt.Contains("same")) {
         
         
         if (TestBit(kCanDelete)) gPad->GetListOfPrimitives()->Remove(this);
         gPad->Clear();
      }
   }
   AppendPad(opt.Data());
}
void TGraph2D::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
   
   if (fHistogram) fHistogram->ExecuteEvent(event, px, py);
}
TObject *TGraph2D::FindObject(const char *name) const
{
   
   if (fFunctions) return fFunctions->FindObject(name);
   return 0;
}
TObject *TGraph2D::FindObject(const TObject *obj) const
{
   
   if (fFunctions) return fFunctions->FindObject(obj);
   return 0;
}
Int_t TGraph2D::Fit(const char *fname, Option_t *option, Option_t *)
{
   
   
   
   
   
   char *linear;
   linear= (char*)strstr(fname, "++");
   TF2 *f2=0;
   if (linear)
      f2=new TF2(fname, fname);
   else{
      f2 = (TF2*)gROOT->GetFunction(fname);
      if (!f2) { Printf("Unknown function: %s",fname); return -1; }
   }
   return Fit(f2,option,"");
}
Int_t TGraph2D::Fit(TF2 *f2, Option_t *option, Option_t *)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   Int_t fitResult = 0;
   Double_t xmin=0, xmax=0;
   Int_t i, npar,nvpar,nparx;
   Double_t par, we, al, bl;
   Double_t eplus,eminus,eparab,globcc,amin,edm,errdef,werr;
   TF2 *fnew2;
   
   if (!f2) {
      Error("Fit", "function may not be null pointer");
      return 0;
   }
   if (f2->IsZombie()) {
      Error("Fit", "function is zombie");
      return 0;
   }
   npar = f2->GetNpar();
   if (npar <= 0) {
      Error("Fit", "function %s has illegal number of parameters = %d", f2->GetName(), npar);
      return 0;
   }
   
   if (f2->GetNdim() != 2) {
      Error("Fit","function %s is not 2-D", f2->GetName());
      return 0;
   }
   
   Double_t *arglist = new Double_t[100];
   
   Foption_t fitOption;
   TString opt = option;
   opt.ToUpper();
   Double_t h=0;
   opt.ReplaceAll("ROB", "H");
   
   if (opt.Contains("H=0.")) {
      int start = opt.Index("H=0.");
      int numpos = start + strlen("H=0.");
      int numlen = 0;
      int len = opt.Length();
      while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
      TString num = opt(numpos,numlen);
      opt.Remove(start+strlen("H"),strlen("=0.")+numlen);
      h = atof(num.Data());
      h*=TMath::Power(10, -numlen);
   }
   if (opt.Contains("U")) fitOption.User    = 1;
   if (opt.Contains("Q")) fitOption.Quiet   = 1;
   if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet   = 0;}
   if (opt.Contains("W")) fitOption.W1      = 1;
   if (opt.Contains("E")) fitOption.Errors  = 1;
   if (opt.Contains("R")) fitOption.Range   = 1;
   if (opt.Contains("N")) fitOption.Nostore = 1;
   if (opt.Contains("0")) fitOption.Nograph = 1;
   if (opt.Contains("+")) fitOption.Plus    = 1;
   if (opt.Contains("B")) fitOption.Bound   = 1;
   if (opt.Contains("C")) fitOption.Nochisq = 1;
   if (opt.Contains("H")) fitOption.Robust  = 1;
 
   
   Bool_t linear = f2->IsLinear();
   if (fitOption.Bound || fitOption.User || fitOption.Errors)
      linear = kFALSE;
   char l[]="TLinearFitter";
   Int_t strdiff = 0;
   Bool_t isSet = kFALSE;
   if (TVirtualFitter::GetFitter()){
      
      isSet=kTRUE;
      strdiff = strcmp(TVirtualFitter::GetFitter()->IsA()->GetName(), l);
   }
   if (linear){
      
      TClass *cl = TClass::GetClass("TLinearFitter");
      if (isSet && strdiff!=0) {
         delete TVirtualFitter::GetFitter();
         isSet=kFALSE;
      }
      if (!isSet) {
        
         TVirtualFitter::SetFitter((TVirtualFitter *)cl->New());
      }
   } else {
      if (isSet && strdiff==0){
         delete TVirtualFitter::GetFitter();
         isSet=kFALSE;
      }
      if (!isSet)
         TVirtualFitter::SetFitter(0);
   }
   TVirtualFitter *grFitter = TVirtualFitter::Fitter(this, f2->GetNpar());
   grFitter->Clear();
   
   grFitter->SetUserFunc(f2);
   grFitter->SetFitOption(fitOption);
   Int_t gxfirst, gxlast;
      gxfirst = 0;
      gxlast  = fNpoints-1;
      if (linear){
         if (fitOption.Robust)
            fitResult = grFitter->ExecuteCommand("FitGraph2D", &h, 0);
         else
            fitResult = grFitter->ExecuteCommand("FitGraph2D", 0, 0);
      } else {
         
         if (!fitOption.Verbose) {
            arglist[0] = -1;
            grFitter->ExecuteCommand("SET PRINT", arglist,1);
            arglist[0] = 0;
            grFitter->ExecuteCommand("SET NOW",   arglist,0);
         }
         
         arglist[0] = 1;
         if (!fitOption.User) grFitter->SetFitMethod("Graph2DFitChisquare");
         fitResult = grFitter->ExecuteCommand("SET ERR",arglist,1);
         if (fitResult != 0) {
            
            if (!fitOption.Quiet) {
               Warning("Fit","Abnormal termination of minimization.");
            }
            delete [] arglist;
            return fitResult;
         }
         
         Int_t nfixed = 0;
         for (i=0;i<npar;i++) {
            par = f2->GetParameter(i);
            f2->GetParLimits(i,al,bl);
            if (al*bl != 0 && al >= bl) {
               al = bl = 0;
               arglist[nfixed] = i+1;
               nfixed++;
            }
            we  = 0.3*TMath::Abs(par);
            if (we <= TMath::Abs(par)*1e-6) we = 1;
            grFitter->SetParameter(i,f2->GetParName(i),par,we,al,bl);
         }
         if(nfixed > 0)grFitter->ExecuteCommand("FIX",arglist,nfixed); 
         
         if (fitOption.Verbose) {
            arglist[0] = 0; grFitter->ExecuteCommand("SET PRINT", arglist,1);
         }
         
         Bool_t hasErrors = kFALSE;
         Double_t ex, ey, ez, sumw2=0;
         for (i=gxfirst;i<=gxlast;i++) {
            ex = GetErrorX(i);
            ey = GetErrorY(i);
            ez = GetErrorZ(i);
            if (ex > 0 || ey > 0 || ez > 0) hasErrors = kTRUE;
            sumw2 += ez*ez;
         }
         
         arglist[0] = TVirtualFitter::GetMaxIterations();
         arglist[1] = sumw2*TVirtualFitter::GetPrecision();
         grFitter->ExecuteCommand("MIGRAD",arglist,2);
         if (fitOption.Errors) {
            grFitter->ExecuteCommand("HESSE",arglist,0);
            grFitter->ExecuteCommand("MINOS",arglist,0);
         }
         grFitter->GetStats(amin,edm,errdef,nvpar,nparx);
         f2->SetChisquare(amin);
         Int_t ndf = f2->GetNumberFitPoints()-npar+nfixed;
         f2->SetNDF(ndf);
         
         char parName[50];
         for (i=0;i<npar;i++) {
            grFitter->GetParameter(i,parName, par,we,al,bl);
            if (!fitOption.Errors) werr = we;
            else {
               grFitter->GetErrors(i,eplus,eminus,eparab,globcc);
               if (eplus > 0 && eminus < 0) werr = 0.5*(eplus-eminus);
               else                         werr = we;
            }
            if (!hasErrors && ndf > 1) werr *= TMath::Sqrt(amin/(ndf-1));
            f2->SetParameter(i,par);
            f2->SetParError(i,werr);
         }
      }
      
      if (!fitOption.Quiet) {
         if (fitOption.Errors) grFitter->PrintResults(4,amin);
         else                  grFitter->PrintResults(3,amin);
      }
      delete [] arglist;
      
   if (!fitOption.Nostore) {
      if (!fFunctions) fFunctions = new TList;
      if (!fitOption.Plus) {
         TIter next(fFunctions, kIterBackward);
         TObject *obj;
         while ((obj = next())) {
            if (obj->InheritsFrom(TF1::Class())) delete obj;
         }
      }
      fnew2 = new TF2();
      f2->Copy(*fnew2);
      fFunctions->Add(fnew2);
      fnew2->SetParent(this);
      fnew2->Save(xmin,xmax,0,0,0,0);
      if (fitOption.Nograph) fnew2->SetBit(TF1::kNotDraw);
      fnew2->SetBit(TFormula::kNotGlobal);
      if (TestBit(kCanDelete)) return fitResult;
      if (gPad) gPad->Modified();
   }
   return fitResult;
}
TAxis *TGraph2D::GetXaxis() const
{
   
   
   TH1 *h = ((TGraph2D*)this)->GetHistogram();
   if (!h) return 0;
   return h->GetXaxis();
}
TAxis *TGraph2D::GetYaxis() const
{
   
   
   TH1 *h = ((TGraph2D*)this)->GetHistogram();
   if (!h) return 0;
   return h->GetYaxis();
}
TAxis *TGraph2D::GetZaxis() const
{
   
   
   TH1 *h = ((TGraph2D*)this)->GetHistogram();
   if (!h) return 0;
   return h->GetZaxis();
}
TList *TGraph2D::GetContourList(Double_t contour)
{
   
   
   
   if (fNpoints <= 0) {
      Error("GetContourList", "Empty TGraph2D");
      return 0;
   }
   if(!fHistogram) GetHistogram("empty");
   if (!fPainter) fPainter = fHistogram->GetPainter();
   return fPainter->GetContourList(contour);
}
Double_t TGraph2D::GetErrorX(Int_t) const
{
   
   
   return -1;
}
Double_t TGraph2D::GetErrorY(Int_t) const
{
   
   
   return -1;
}
Double_t TGraph2D::GetErrorZ(Int_t) const
{
   
   
   return -1;
}
TH2D *TGraph2D::GetHistogram(Option_t *option)
{
   
   
   
   
   
   
   
   
   if (fNpoints <= 0) {
      Error("GetHistogram", "Empty TGraph2D");
      return 0;
   }
   TString opt = option;
   opt.ToLower();
   Bool_t empty = opt.Contains("empty");
   if (fHistogram) {
      if (!empty && fHistogram->GetEntries()==0) {
         if (!fUserHisto) {
            delete fHistogram;
            fHistogram = 0;
         }
      } else {
         return fHistogram;
      }
   }
   Double_t hxmax, hymax, hxmin, hymin;
   
   if (!fUserHisto) {
      Bool_t add = TH1::AddDirectoryStatus();
      TH1::AddDirectory(kFALSE);
      Double_t xmax  = GetXmax();
      Double_t ymax  = GetYmax();
      Double_t xmin  = GetXmin();
      Double_t ymin  = GetYmin();
      hxmin = xmin-fMargin*(xmax-xmin);
      hymin = ymin-fMargin*(ymax-ymin);
      hxmax = xmax+fMargin*(xmax-xmin);
      hymax = ymax+fMargin*(ymax-ymin);
      fHistogram = new TH2D(GetName(),GetTitle(),
                            fNpx ,hxmin, hxmax,
                            fNpy, hymin, hymax);
      TH1::AddDirectory(add);
      fHistogram->SetBit(TH1::kNoStats);
   } else {
      hxmin = fHistogram->GetXaxis()->GetXmin();
      hymin = fHistogram->GetYaxis()->GetXmin();
      hxmax = fHistogram->GetXaxis()->GetXmax();
      hymax = fHistogram->GetYaxis()->GetXmax();
   }
   
   TGraphDelaunay *dt = new TGraphDelaunay(this);
   dt->SetMaxIter(fMaxIter);
   dt->SetMarginBinsContent(fZout);
   TList *hl = fHistogram->GetListOfFunctions();
   hl->Add(dt);
   
   if (empty) {
      if (fMinimum != -1111) {
         fHistogram->SetMinimum(fMinimum);
      } else {
         fHistogram->SetMinimum(GetZmin());
      }
      if (fMaximum != -1111) {
         fHistogram->SetMaximum(fMaximum);
      } else {
         fHistogram->SetMaximum(GetZmax());
      }
      return fHistogram;
   }
   Double_t dx = (hxmax-hxmin)/fNpx;
   Double_t dy = (hymax-hymin)/fNpy;
   Double_t x, y, z;
   for (Int_t ix=1; ix<=fNpx; ix++) {
      x  = hxmin+(ix-0.5)*dx;
      for (Int_t iy=1; iy<=fNpy; iy++) {
         y  = hymin+(iy-0.5)*dy;
         z  = dt->ComputeZ(x, y);
         fHistogram->Fill(x, y, z);
      }
   }
   if (fMinimum != -1111) fHistogram->SetMinimum(fMinimum);
   if (fMaximum != -1111) fHistogram->SetMaximum(fMaximum);
   return fHistogram;
}
Double_t TGraph2D::GetXmax() const
{
   
   Double_t v = fX[0];
   for (Int_t i=1; i<fNpoints; i++) if (fX[i]>v) v=fX[i];
   return v;
}
Double_t TGraph2D::GetXmin() const
{
   
   Double_t v = fX[0];
   for (Int_t i=1; i<fNpoints; i++) if (fX[i]<v) v=fX[i];
   return v;
}
Double_t TGraph2D::GetYmax() const
{
   
   Double_t v = fY[0];
   for (Int_t i=1; i<fNpoints; i++) if (fY[i]>v) v=fY[i];
   return v;
}
Double_t TGraph2D::GetYmin() const
{
   
   Double_t v = fY[0];
   for (Int_t i=1; i<fNpoints; i++) if (fY[i]<v) v=fY[i];
   return v;
}
Double_t TGraph2D::GetZmax() const
{
   
   Double_t v = fZ[0];
   for (Int_t i=1; i<fNpoints; i++) if (fZ[i]>v) v=fZ[i];
   return v;
}
Double_t TGraph2D::GetZmin() const
{
   
   Double_t v = fZ[0];
   for (Int_t i=1; i<fNpoints; i++) if (fZ[i]<v) v=fZ[i];
   return v;
}
Double_t TGraph2D::Interpolate(Double_t x, Double_t y)
{
   
   
   if (fNpoints <= 0) {
      Error("Interpolate", "Empty TGraph2D");
      return 0;
   }
   TGraphDelaunay *dt;
   if(!fHistogram) GetHistogram("empty");
   TList *hl = fHistogram->GetListOfFunctions();
   dt = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
   return dt->ComputeZ(x, y);
}
void TGraph2D::Paint(Option_t *option)
{
   
   if (fNpoints <= 0) {
      Error("Paint", "Empty TGraph2D");
      return;
   }
   TString opt = option;
   opt.ToLower();
   if (opt.Contains("p") && !opt.Contains("tri")) {
      if (!opt.Contains("pol") &&
          !opt.Contains("sph") &&
          !opt.Contains("psr")) opt.Append("tri0");
   }
   if (opt.Contains("line") && !opt.Contains("tri")) opt.Append("tri0");
   if (opt.Contains("tri0")) {
      GetHistogram("empty");
   } else {
      GetHistogram();
   }
   fHistogram->SetLineColor(GetLineColor());
   fHistogram->SetLineStyle(GetLineStyle());
   fHistogram->SetLineWidth(GetLineWidth());
   fHistogram->SetFillColor(GetFillColor());
   fHistogram->SetFillStyle(GetFillStyle());
   fHistogram->SetMarkerColor(GetMarkerColor());
   fHistogram->SetMarkerStyle(GetMarkerStyle());
   fHistogram->SetMarkerSize(GetMarkerSize());
   fHistogram->Paint(opt.Data());
}
TH1 *TGraph2D::Project(Option_t *option) const
{
   
   
   
   
   
   
   
   if (fNpoints <= 0) {
      Error("Project", "Empty TGraph2D");
      return 0;
   }
   TString opt = option; opt.ToLower();
   Int_t pcase = 0;
   if (opt.Contains("x"))  pcase = 1;
   if (opt.Contains("y"))  pcase = 2;
   if (opt.Contains("xy")) pcase = 3;
   if (opt.Contains("yx")) pcase = 4;
   
   TH1D *h1 = 0;
   TH2D *h2 = 0;
   Int_t nch = strlen(GetName()) +opt.Length() +2;
   char *name = new char[nch];
   sprintf(name,"%s_%s",GetName(),option);
   nch = strlen(GetTitle()) +opt.Length() +2;
   char *title = new char[nch];
   sprintf(title,"%s_%s",GetTitle(),option);
   Double_t hxmin = GetXmin();
   Double_t hxmax = GetXmax();
   Double_t hymin = GetYmin();
   Double_t hymax = GetYmax();
   switch (pcase) {
      case 1:
         
         h1 = new TH1D(name,title,fNpx,hxmin,hxmax);
         break;
      case 2:
         
         h1 = new TH1D(name,title,fNpy,hymin,hymax);
         break;
      case 3:
         
         h2 = new TH2D(name,title,fNpx,hxmin,hxmax,fNpy,hymin,hymax);
         break;
      case 4:
         
         h2 = new TH2D(name,title,fNpy,hymin,hymax,fNpx,hxmin,hxmax);
         break;
   }
   delete [] name;
   delete [] title;
   TH1 *h = h1;
   if (h2) h = h2;
   if (h == 0) return 0;
   
   Double_t entries = 0;
   for (Int_t n=0; n<fNpoints; n++) {
      switch (pcase) {
         case 1:
            
            h1->Fill(fX[n], fZ[n]);
            break;
         case 2:
            
            h1->Fill(fY[n], fZ[n]);
            break;
         case 3:
            
            h2->Fill(fX[n], fY[n], fZ[n]);
            break;
         case 4:
            
            h2->Fill(fY[n], fX[n], fZ[n]);
            break;
      }
      entries += fZ[n];
   }
   h->SetEntries(entries);
   return h;
}
Int_t TGraph2D::RemovePoint(Int_t ipoint)
{
   
   if (ipoint < 0) return -1;
   if (ipoint >= fNpoints) return -1;
   fNpoints--;
   Double_t *newX = new Double_t[fNpoints];
   Double_t *newY = new Double_t[fNpoints];
   Double_t *newZ = new Double_t[fNpoints];
   Int_t j = -1;
   for (Int_t i=0;i<fNpoints+1;i++) {
      if (i == ipoint) continue;
      j++;
      newX[j] = fX[i];
      newY[j] = fY[i];
      newZ[j] = fZ[i];
   }
   delete [] fX;
   delete [] fY;
   delete [] fZ;
   fX = newX;
   fY = newY;
   fZ = newZ;
   if (fHistogram) {delete fHistogram; fHistogram = 0;}
   return ipoint;
}
void TGraph2D::SavePrimitive(ostream &out, Option_t *option )
{
   
   char quote = '"';
   out<<"   "<<endl;
   if (gROOT->ClassSaved(TGraph2D::Class())) {
      out<<"   ";
   } else {
      out<<"   TGraph2D *";
   }
   out<<"graph = new TGraph2D("<<fNpoints<<");"<<endl;
   out<<"   graph->SetName("<<quote<<GetName()<<quote<<");"<<endl;
   out<<"   graph->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
   if (fDirectory == 0) {
      out<<"   "<<GetName()<<"->SetDirectory(0);"<<endl;
   }
   SaveFillAttributes(out,"graph",0,1001);
   SaveLineAttributes(out,"graph",1,1,1);
   SaveMarkerAttributes(out,"graph",1,1,1);
   for (Int_t i=0;i<fNpoints;i++) {
      out<<"   graph->SetPoint("<<i<<","<<fX[i]<<","<<fY[i]<<","<<fZ[i]<<");"<<endl;
   }
   
   TIter next(fFunctions);
   TObject *obj;
   while ((obj=next())) {
      obj->SavePrimitive(out,"nodraw");
      out<<"   graph->GetListOfFunctions()->Add("<<obj->GetName()<<");"<<endl;
      if (obj->InheritsFrom("TPaveStats")) {
         out<<"   ptstats->SetParent(graph->GetListOfFunctions());"<<endl;
      }
   }
   out<<"   graph->Draw("<<quote<<option<<quote<<");"<<endl;
}
void TGraph2D::SetDirectory(TDirectory *dir)
{
   
   
   
   
   
   if (fDirectory == dir) return;
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fDirectory = dir;
   if (fDirectory) fDirectory->GetList()->Add(this);
}
void TGraph2D::SetHistogram(TH2 *h)
{
   
   fUserHisto = kTRUE;
   fHistogram = (TH2D*)h;
   fNpx       = h->GetNbinsX();
   fNpy       = h->GetNbinsY();
}
void TGraph2D::SetMargin(Double_t m)
{
   
   if (m<0 || m>1) {
      Warning("SetMargin","The margin must be >= 0 && <= 1, fMargin set to 0.1");
      fMargin = 0.1;
   } else {
      fMargin = m;
   }
   if (fHistogram) {delete fHistogram; fHistogram = 0;}
}
void TGraph2D::SetMarginBinsContent(Double_t z)
{
   
   
   fZout = z;
   if (fHistogram) {delete fHistogram; fHistogram = 0;}
}
void TGraph2D::SetMaximum(Double_t maximum)
{
   
   fMaximum = maximum;
   GetHistogram()->SetMaximum(maximum);
}
void TGraph2D::SetMinimum(Double_t minimum)
{
   
   fMinimum = minimum;
   GetHistogram()->SetMinimum(minimum);
}
void TGraph2D::SetName(const char *name)
{
   
   
   
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fName = name;
   if (fDirectory) fDirectory->GetList()->Add(this);
}
void TGraph2D::SetNameTitle(const char *name, const char *title)
{
   
   
   
   
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fName  = name;
   SetTitle(title);
   if (fDirectory) fDirectory->GetList()->Add(this);
}
void TGraph2D::SetNpx(Int_t npx)
{
   
   if (npx < 4) {
      Warning("SetNpx","Number of points must be >4 && < 500, fNpx set to 4");
      fNpx = 4;
   } else if(npx > 500) {
      Warning("SetNpx","Number of points must be >4 && < 500, fNpx set to 500");
      fNpx = 500;
   } else {
      fNpx = npx;
   }
   if (fHistogram) {delete fHistogram; fHistogram = 0;}
}
void TGraph2D::SetNpy(Int_t npy)
{
   
   if (npy < 4) {
      Warning("SetNpy","Number of points must be >4 && < 500, fNpy set to 4");
      fNpy = 4;
   } else if(npy > 500) {
      Warning("SetNpy","Number of points must be >4 && < 500, fNpy set to 500");
      fNpy = 500;
   } else {
      fNpy = npy;
   }
   if (fHistogram) {delete fHistogram; fHistogram = 0;}
}
void TGraph2D::SetPoint(Int_t n, Double_t x, Double_t y, Double_t z)
{
   
   
   
   if (n < 0) return;
   if (!fX || !fY || !fZ || n >= fSize) {
   
      Int_t newN = TMath::Max(2*fSize,n+1);
      Double_t *savex = new Double_t [newN];
      Double_t *savey = new Double_t [newN];
      Double_t *savez = new Double_t [newN];
      if (fX && fSize) {
         memcpy(savex,fX,fSize*sizeof(Double_t));
         memset(&savex[fSize],0,(newN-fSize)*sizeof(Double_t));
         delete [] fX;
      }
      if (fY && fSize) {
         memcpy(savey,fY,fSize*sizeof(Double_t));
         memset(&savey[fSize],0,(newN-fSize)*sizeof(Double_t));
         delete [] fY;
      }
      if (fZ && fSize) {
         memcpy(savez,fZ,fSize*sizeof(Double_t));
         memset(&savez[fSize],0,(newN-fSize)*sizeof(Double_t));
         delete [] fZ;
      }
      fX    = savex;
      fY    = savey;
      fZ    = savez;
      fSize = newN;
   }
   fX[n]    = x;
   fY[n]    = y;
   fZ[n]    = z;
   fNpoints = TMath::Max(fNpoints,n+1);
}
void TGraph2D::SetTitle(const char* title)
{
   
   fTitle = title;
   if (fHistogram) fHistogram->SetTitle(title);
}
void TGraph2D::Streamer(TBuffer &b)
{
   
   if (b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = b.ReadVersion(&R__s, &R__c);
      b.ReadClassBuffer(TGraph2D::Class(), this, R__v, R__s, R__c);
      if (!gROOT->ReadingObject()) {
         fDirectory = gDirectory;
         if (!gDirectory->GetList()->FindObject(this)) gDirectory->Append(this);
      }
      ResetBit(kCanDelete);
   } else {
      b.WriteClassBuffer(TGraph2D::Class(),this);
   }
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.