diff --git a/graf/inc/LinkDef2.h b/graf/inc/LinkDef2.h index 034502ea60e61480e7b6f57fd7d94486c1cccbea..e9b348828b3cf094e3d4322836786f55a798bc72 100644 --- a/graf/inc/LinkDef2.h +++ b/graf/inc/LinkDef2.h @@ -1,4 +1,4 @@ -/* @(#)root/graf:$Name: $:$Id: LinkDef2.h,v 1.6 2003/10/28 17:43:07 brun Exp $ */ +/* @(#)root/graf:$Name: $:$Id: LinkDef2.h,v 1.7 2003/11/20 16:57:46 brun Exp $ */ /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * @@ -15,6 +15,7 @@ #pragma link off all functions; #pragma link C++ class TGraph2D-; +#pragma link C++ class TGraph2DErrors-; #pragma link C++ class TGraphSmooth+; #pragma link C++ class TLatex+; #pragma link C++ class TLegend+; diff --git a/graf/inc/TGraph2D.h b/graf/inc/TGraph2D.h index b60e418bdada1bb1eb7a38101f8e9249eaae1fdd..8e3a867470896be8ad863493fbde6fc4dfcb6d29 100644 --- a/graf/inc/TGraph2D.h +++ b/graf/inc/TGraph2D.h @@ -34,6 +34,7 @@ #include "TF2.h" #endif +class TView; class TDirectory; class TGraph2D : public TNamed, public TAttLine, public TAttFill, public TAttMarker { @@ -58,6 +59,7 @@ protected: Double_t fXoffset; //! Double_t fYoffset; //!Parameters used to normalize fX and fY Double_t fScaleFactor; //! + Double_t *fGridLevels; //!Grid levels along Z axis Double_t fMargin; // Extra space (in %) around interpolated area for 2D histo Double_t fMinimum; // Minimum value for plotting along z Double_t fMaximum; // Maximum value for plotting along z @@ -65,6 +67,7 @@ protected: Double_t *fDist; //!Array used to order mass points by distance Int_t fMaxIter; //!Maximum number of iterations to find Delaunay triangles Int_t fTriedSize; //!Real size of the fxTried arrays + Int_t fNbLevels; //|Number of Grid levels Int_t *fPTried; //! Int_t *fNTried; //!Delaunay triangles storage Int_t *fMTried; //! @@ -73,19 +76,26 @@ protected: TList *fFunctions; // Pointer to list of functions (fits and user) TH2D *fHistogram; //!2D histogram of z values linearly interpolated TDirectory *fDirectory; //!Pointer to directory holding this 2D graph + TView *fView; //!TView used to paint the triangles void Build(Int_t n); Double_t ComputeZ(Double_t x, Double_t y); + void DefineGridLevels(); Bool_t Enclose(Int_t T1, Int_t T2, Int_t T3, Int_t Ex) const; void FileIt(Int_t P, Int_t N, Int_t M); void FindAllTriangles(); void FindHull(); Bool_t InHull(Int_t E, Int_t X) const; Double_t InterpolateOnPlane(Int_t TI1, Int_t TI2, Int_t TI3, Int_t E) const; + void PaintOneTriangle(Int_t *T,Double_t *x, Double_t *y); void PaintTriangles(Option_t *option=""); void Reset(Int_t level=0); public: + // TGraph2D status bits + enum { + kFitInit = BIT(19) + }; TGraph2D(); TGraph2D(Int_t n, Option_t *option=""); @@ -113,6 +123,9 @@ public: Double_t GetMarginBinsContent() const {return fZout;} TH2D *GetHistogram(Option_t *option="") const; TList *GetListOfFunctions() const { return fFunctions; } + virtual Double_t GetErrorX(Int_t bin) const; + virtual Double_t GetErrorY(Int_t bin) const; + virtual Double_t GetErrorZ(Int_t bin) const; Int_t GetN() const {return fNpoints;} Double_t *GetX() const {return fX;} Double_t *GetY() const {return fY;} diff --git a/graf/src/TGraph2D.cxx b/graf/src/TGraph2D.cxx index 5b1aca43b2b071209d04d415ce35a204030de895..9252c9d7cd4d18da572f64345a50eda9c4b81409 100644 --- a/graf/src/TGraph2D.cxx +++ b/graf/src/TGraph2D.cxx @@ -18,6 +18,8 @@ #include "TVirtualPad.h" #include "TVirtualFitter.h" #include "TView.h" +#include "THLimitsFinder.h" +#include "TStyle.h" ClassImp(TGraph2D) @@ -68,6 +70,7 @@ ClassImp(TGraph2D) // An hidden surface drawing technique is used // "TRIW" : the Delaunay triangles are drawn as wire frame // "P" : draw a marker at each vertex +// "P0" : draw a circle at each vertex. Each circle background is white. // // A TGraph2D can be also drawn with ANY options valid to draw a 2D histogram. // @@ -674,6 +677,37 @@ L90: } +//______________________________________________________________________________ +void TGraph2D::DefineGridLevels() +{ + // Define the grid levels drawn on the triangles. + // The grid levels are aligned on the Z axis' main tick marks. + // The function assumes that fView has been defined. + + Int_t i, nbins; + Double_t BinLow, BinHigh, BinWidth; + + // Find the main tick marks positions. + Double_t *rmin = fView->GetRmin(); + Double_t *rmax = fView->GetRmax(); + Int_t ndivz = fHistogram->GetZaxis()->GetNdivisions()%100; + + if (ndivz > 0) { + THLimitsFinder::Optimize(rmin[2], rmax[2], ndivz, + BinLow, BinHigh, nbins, BinWidth, " "); + } else { + nbins = TMath::Abs(ndivz); + BinLow = rmin[2]; + BinHigh = rmax[2]; + BinWidth = (BinHigh-BinLow)/nbins; + } + // Define the grid levels + fNbLevels = nbins+1; + fGridLevels = new Double_t[fNbLevels]; + for (i = 0; i < fNbLevels; ++i) fGridLevels[i] = BinLow+i*BinWidth; +} + + //______________________________________________________________________________ Int_t TGraph2D::DistancetoPrimitive(Int_t px, Int_t py) { @@ -1112,6 +1146,9 @@ void TGraph2D::Build(Int_t n) fPTried = 0; fNTried = 0; fMTried = 0; + fGridLevels = 0; + fNbLevels = 0; + fView = 0; SetMaxIter(); @@ -1427,7 +1464,7 @@ Int_t TGraph2D::Fit(TF2 *f2, Option_t *option, Option_t *) } //*-*- Is a Fit range specified? -///Int_t gxfirst, gxlast; + Int_t gxfirst, gxlast; ///if (fitOption.Range) { /// f2->GetRange(xmin, ymin, xmax, ymax); /// gxfirst = fNpoints +1; @@ -1438,8 +1475,8 @@ Int_t TGraph2D::Fit(TF2 *f2, Option_t *option, Option_t *) /// } ///} else { /// f2->SetRange(xmin, ymin, xmax, ymax); -/// gxfirst = 0; -/// gxlast = fNpoints-1; + gxfirst = 0; + gxlast = fNpoints-1; ///} // Some initialisations @@ -1451,7 +1488,7 @@ Int_t TGraph2D::Fit(TF2 *f2, Option_t *option, Option_t *) } // Set error criterion for chisquare - arglist[0] = TVirtualFitter::GetErrorDef(); + arglist[0] = 1; if (!fitOption.User) grFitter->SetFitMethod("Graph2DFitChisquare"); fitResult = grFitter->ExecuteCommand("SET ERR",arglist,1); if (fitResult != 0) { @@ -1485,16 +1522,16 @@ Int_t TGraph2D::Fit(TF2 *f2, Option_t *option, Option_t *) // Compute sum of squares of errors in the bin range Bool_t hasErrors = kFALSE; - Double_t sumw2=0; -///Double_t ex, ey, sumw2=0; -///for (i=gxfirst;i<=gxlast;i++) { -/// ex = GetErrorX(i); -/// ey = GetErrorY(i); -/// if (ex > 0 || ey > 0) hasErrors = kTRUE; -/// sumw2 += ey*ey; -///} + 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; + } //*-*- Perform minimization -///if (!InheritsFrom("TGraphErrors")) SetBit(kFitInit); + if (!InheritsFrom("TGraph2DErrors")) SetBit(kFitInit); arglist[0] = TVirtualFitter::GetMaxIterations(); arglist[1] = sumw2*TVirtualFitter::GetPrecision(); grFitter->ExecuteCommand("MIGRAD",arglist,2); @@ -1555,6 +1592,36 @@ Int_t TGraph2D::Fit(TF2 *f2, Option_t *option, Option_t *) } +//______________________________________________________________________________ +Double_t TGraph2D::GetErrorX(Int_t) const +{ + // This function is called by Graph2DFitChisquare. + // It always returns a negative value. Real implementation in TGraph2DErrors + + return -1; +} + + +//______________________________________________________________________________ +Double_t TGraph2D::GetErrorY(Int_t) const +{ + // This function is called by Graph2DFitChisquare. + // It always returns a negative value. Real implementation in TGraph2DErrors + + return -1; +} + + +//______________________________________________________________________________ +Double_t TGraph2D::GetErrorZ(Int_t) const +{ + // This function is called by Graph2DFitChisquare. + // It always returns a negative value. Real implementation in TGraph2DErrors + + return -1; +} + + //______________________________________________________________________________ TH2D *TGraph2D::GetHistogram(Option_t *option) const { @@ -1756,6 +1823,59 @@ void TGraph2D::Paint(Option_t *option) } } +//______________________________________________________________________________ +void TGraph2D::PaintOneTriangle(Int_t *T,Double_t *x, Double_t *y) +{ + // Paints one triangle + + Int_t P0=T[0]-1; + Int_t P1=T[1]-1; + Int_t P2=T[2]-1; + Double_t xl[2],yl[2]; + Double_t Zl, R21, R20, R10; + Double_t X0 = x[0] , X2 = x[0]; + Double_t Y0 = y[0] , Y2 = y[0]; + Double_t Z0 = fZ[P0], Z2 = fZ[P0]; + Int_t I0=0; + Int_t I1=0; + Int_t I2=0; + + if(fZ[P1]<Z0){Z0=fZ[P1];X0=x[1];Y0=y[1];I0=1;} + if(fZ[P2]<Z0){Z0=fZ[P2];X0=x[2];Y0=y[2];I0=2;} + if(fZ[P1]>Z2){Z2=fZ[P1];X2=x[1];Y2=y[1];I2=1;} + if(fZ[P2]>Z2){Z2=fZ[P2];X2=x[2];Y2=y[2];I2=2;} + + I1 = 3-I2-I0; + Double_t X1 = x[I1]; + Double_t Y1 = y[I1]; + Double_t Z1 = fZ[T[I1]-1]; + + SetLineStyle(3); + TAttLine::Modify(); + + for(Int_t i=0; i<fNbLevels; i++){ + Zl=fGridLevels[i]; + if(Zl >= Z0 && Zl <=Z2) { + R21=(Zl-Z1)/(Z2-Z1); + R20=(Zl-Z0)/(Z2-Z0); + R10=(Zl-Z0)/(Z1-Z0); + xl[0]=R20*(X2-X0)+X0; + yl[0]=R20*(Y2-Y0)+Y0; + if(Zl >= Z1 && Zl <=Z2) { + xl[1]=R21*(X2-X1)+X1; + yl[1]=R21*(Y2-Y1)+Y1; + } else { + xl[1]=R10*(X1-X0)+X0; + yl[1]=R10*(Y1-Y0)+Y0; + } + gPad->PaintPolyLine(2,xl,yl); + } + } +///Int_t ncolors = gStyle->GetNumberOfColors(); +///color = Int_t(0.01+(z-zmin)*scale); + SetLineStyle(1); + TAttLine::Modify(); +} //______________________________________________________________________________ void TGraph2D::PaintTriangles(Option_t *option) @@ -1768,6 +1888,7 @@ void TGraph2D::PaintTriangles(Option_t *option) TString opt = option; Bool_t triangles = opt.Contains("tri"); Bool_t markers = opt.Contains("p"); + Bool_t markers0 = opt.Contains("p0"); Bool_t wire = opt.Contains("w"); Bool_t same = opt.Contains("s"); Bool_t backbox = opt.Contains("bb"); @@ -1792,12 +1913,12 @@ void TGraph2D::PaintTriangles(Option_t *option) if (!axis) fHistogram->Paint("abb"); } - TView *view = gPad->GetView(); - if (!view) { + fView = gPad->GetView(); + if (!fView) { Error("PaintTriangles", "No TView in current pad"); return; } - + DefineGridLevels(); // Compute minimums and maximums TAxis *xaxis = fHistogram->GetXaxis(); Int_t first = xaxis->GetFirst(); @@ -1817,8 +1938,8 @@ void TGraph2D::PaintTriangles(Option_t *option) // the triangles from back to front. if (triangles) { FindAllTriangles(); - Double_t cp = TMath::Cos(view->GetLongitude()*TMath::Pi()/180.); - Double_t sp = TMath::Sin(view->GetLongitude()*TMath::Pi()/180.); + Double_t cp = TMath::Cos(fView->GetLongitude()*TMath::Pi()/180.); + Double_t sp = TMath::Sin(fView->GetLongitude()*TMath::Pi()/180.); if (fOrder) {delete [] fOrder; fOrder = 0;} if (fDist) {delete [] fDist; fDist = 0;} fOrder = new Int_t[fNdt]; @@ -1862,19 +1983,28 @@ void TGraph2D::PaintTriangles(Option_t *option) if (logx) temp1[0] = TMath::Log10(temp1[0]); if (logy) temp1[1] = TMath::Log10(temp1[1]); if (logz) temp1[2] = TMath::Log10(temp1[2]); - view->WCtoNDC(temp1, &temp2[0]); + fView->WCtoNDC(temp1, &temp2[0]); xm[IT] = temp2[0]; ym[IT] = temp2[1]; } - SetMarkerStyle(20); - SetMarkerSize(0.4); - SetMarkerColor(0); - TAttMarker::Modify(); - gPad->PaintPolyMarker(fNpoints,xm,ym); - SetMarkerStyle(24); - SetMarkerColor(1); - TAttMarker::Modify(); - gPad->PaintPolyMarker(fNpoints,xm,ym); + if (markers0) { + SetMarkerStyle(20); + SetMarkerSize(GetMarkerSize()); + Int_t MC = GetMarkerColor(); + SetMarkerColor(0); + TAttMarker::Modify(); + gPad->PaintPolyMarker(fNpoints,xm,ym); + SetMarkerStyle(24); + SetMarkerColor(MC); + TAttMarker::Modify(); + gPad->PaintPolyMarker(fNpoints,xm,ym); + } else { + SetMarkerStyle(GetMarkerStyle()); + SetMarkerSize(GetMarkerSize()); + SetMarkerColor(GetMarkerColor()); + TAttMarker::Modify(); + gPad->PaintPolyMarker(fNpoints,xm,ym); + } delete [] xm; delete [] ym; @@ -1885,6 +2015,7 @@ void TGraph2D::PaintTriangles(Option_t *option) TAttFill::Modify(); SetLineColor(GetLineColor()); TAttLine::Modify(); + Int_t LS = GetLineStyle(); for (IT=0; IT<fNdt; IT++) { T[0] = fPTried[fOrder[IT]]; T[1] = fNTried[fOrder[IT]]; @@ -1900,26 +2031,40 @@ void TGraph2D::PaintTriangles(Option_t *option) if (logx) temp1[0] = TMath::Log10(temp1[0]); if (logy) temp1[1] = TMath::Log10(temp1[1]); if (logz) temp1[2] = TMath::Log10(temp1[2]); - view->WCtoNDC(temp1, &temp2[0]); + fView->WCtoNDC(temp1, &temp2[0]); x[t] = temp2[0]; y[t] = temp2[1]; } x[3] = x[0]; y[3] = y[0]; - if (!wire) gPad->PaintFillArea(3,x,y); + if (!wire) { + gPad->PaintFillArea(3,x,y); + PaintOneTriangle(T,x,y); + } gPad->PaintPolyLine(4,x,y); if (markers) { - SetMarkerStyle(20); - SetMarkerSize(0.4); - SetMarkerColor(0); - TAttMarker::Modify(); - gPad->PaintPolyMarker(3,x,y); - SetMarkerStyle(24); - SetMarkerColor(1); - TAttMarker::Modify(); - gPad->PaintPolyMarker(3,x,y); + if (markers0) { + SetMarkerStyle(20); + SetMarkerSize(GetMarkerSize()); + Int_t MC = GetMarkerColor(); + SetMarkerColor(0); + TAttMarker::Modify(); + gPad->PaintPolyMarker(3,x,y); + SetMarkerStyle(24); + SetMarkerColor(MC); + TAttMarker::Modify(); + gPad->PaintPolyMarker(3,x,y); + } else { + SetMarkerStyle(GetMarkerStyle()); + SetMarkerSize(GetMarkerSize()); + SetMarkerColor(GetMarkerColor()); + TAttMarker::Modify(); + gPad->PaintPolyMarker(3,x,y); + } } } + SetLineStyle(LS); + TAttLine::Modify(); delete [] fOrder; fOrder = 0; delete [] fDist; fDist = 0; }