// @(#)root/histpainter:$Id: TGraphPainter.cxx,v 1.00 // Author: Olivier Couet /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #include "TROOT.h" #include "TGraphPainter.h" #include "TMath.h" #include "TGraph.h" #include "TPolyLine.h" #include "TPolyMarker.h" #include "TVirtualPad.h" #include "TView.h" #include "TStyle.h" #include "TH1.h" #include "TF1.h" #include "TPaveStats.h" #include "TGaxis.h" #include "TGraphAsymmErrors.h" #include "TGraphBentErrors.h" #include "TGraphPolargram.h" #include "TGraphPolar.h" #include "TGraphQQ.h" #include "TLatex.h" #include "TArrow.h" #include "TFrame.h" #include "TVirtualPadEditor.h" Double_t *gxwork, *gywork, *gxworkl, *gyworkl; ClassImp(TGraphPainter); //______________________________________________________________________________ /* Begin_Html
To draw a graph "graph" it's enough to do:
graph->Draw("AL");
The option "AL" in the Draw() method means:
TGraphPainter offers many options to paint the various kind of graphs.
It is separated from the graph classes so that one can have graphs without the graphics overhead, for example in a batch program.
When a displayed graph is modified, there is no need to call Draw() again; the image will be refreshed the next time the pad will be updated.
A pad is updated after one of these three actions:
"A" | Axis are drawn around the graph |
---|---|
"L" | A simple polyline is drawn |
"F" | A fill area is drawn ('CF' draw a smoothed fill area) |
"C" | A smooth Curve is drawn |
"*" | A Star is plotted at each point |
"P" | The current marker is plotted at each point |
"B" | A Bar chart is drawn |
"1" | When a graph is drawn as a bar chart, this option makes the bars start from the bottom of the pad. By default they start at 0. |
"X+" | The X-axis is drawn on the top side of the plot. |
"Y+" | The Y-axis is drawn on the right side of the plot. |
Drawing options can be combined. In the following example the graph
is drawn as a smooth curve (option "C") with markers (option "P") and
with axes (option "A").
End_Html
Begin_Macro(source)
{
TCanvas *c1 = new TCanvas("c1","c1",200,10,600,400);
c1->SetFillColor(42);
c1->SetGrid();
const Int_t n = 20;
Double_t x[n], y[n];
for (Int_t i=0;i The following macro shows the option "B" usage. It can be combined with the
option "1".
End_Html
Begin_Macro(source)
{
TCanvas *c47 = new TCanvas("c47","c47",200,10,600,400);
c47->Divide(1,2);
const Int_t n = 20;
Double_t x[n], y[n];
for (Int_t i=0;i This drawing mode is activated when the absolute value of the graph line
width (set by SetLineWidth()) is greater than 99. In that
case the line width number is interpreted as:
gStyle->SetErrorX(dx) controls the size of the error along x.
dx = 0 removes the error along x.
gStyle->SetEndErrorSize(np) controls the size of the lines
at the end of the error bars (when option 1 is used).
By default np=1. (np represents the number of pixels).
The option "0" shows the error bars for data points outside range.
End_Html
Begin_Macro(source)
{
TCanvas *c48 = new TCanvas("c48","c48",200,10,600,400);
float x[] = {1,2,3};
float err_x[] = {0,0,0};
float err_y[] = {5,5,5};
float y[] = {1,4,9};
TGraphErrors tg(3,x,y,err_x,err_y);
c48->Divide(2,1);
c48->cd(1); gPad->DrawFrame(0,0,4,8); tg.Draw("PC");
c48->cd(2); gPad->DrawFrame(0,0,4,8); tg.Draw("0PC");
return c48;
}
End_Macro
Begin_Html
The option "3" shows the errors as a band.
End_Html
Begin_Macro(source)
{
TCanvas *c41 = new TCanvas("c41","c41",200,10,600,400);
double x[] = {0, 1, 2, 3, 4};
double y[] = {0, 2, 4, 1, 3};
double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
double ey[] = {1, 0.5, 1, 0.5, 1};
TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
ge->SetFillColor(4);
ge->SetFillStyle(3010);
ge->Draw("a3");
return c41;
}
End_Macro
Begin_Html
The option "4" is similar to the option "3" except that the band
is smoothed. As the following picture shows, this option should be
used carefully because the smoothing algorithm may show some (huge)
"bouncing" effects. In some cases it looks nicer than option "3"
(because it is smooth) but it can be misleading.
End_Html
Begin_Macro(source)
{
TCanvas *c42 = new TCanvas("c42","c42",200,10,600,400);
double x[] = {0, 1, 2, 3, 4};
double y[] = {0, 2, 4, 1, 3};
double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
double ey[] = {1, 0.5, 1, 0.5, 1};
TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
ge->SetFillColor(6);
ge->SetFillStyle(3005);
ge->Draw("a4");
return c42;
}
End_Macro
Begin_Html
The following example shows how the option "[]" can be used to superimpose
systematic errors on top of a graph with statistical errors.
End_Html
Begin_Macro(source)
{
TCanvas *c43 = new TCanvas("c43","c43",200,10,600,400);
c43->DrawFrame(0., -0.5, 6., 2);
double x[5] = {1, 2, 3, 4, 5};
double zero[5] = {0, 0, 0, 0, 0};
// data set (1) with stat and sys errors
double y1[5] = {1.2, 1.15, 1.19, 0.9, 1.4};
double ey_stat1[5] = {0.2, 0.18, 0.17, 0.2, 0.4};
double ey_sys1[5] = {0.5, 0.71, 0.76, 0.5, 0.45};
// data set (2) with stat and sys errors
double y2[5] = {0.25, 0.18, 0.29, 0.2, 0.21};
double ey_stat2[5] = {0.2, 0.18, 0.17, 0.2, 0.4};
double ey_sys2[5] = {0.63, 0.19, 0.7, 0.2, 0.7};
// Now draw data set (1)
// We first have to draw it only with the stat errors
TGraphErrors *graph1 = new TGraphErrors(5, x, y1, zero, ey_stat1);
graph1->SetMarkerStyle(20);
graph1->Draw("P");
// Now we have to somehow depict the sys errors
TGraphErrors *graph1_sys = new TGraphErrors(5, x, y1, zero, ey_sys1);
graph1_sys->Draw("[]");
// Now draw data set (2)
// We first have to draw it only with the stat errors
TGraphErrors *graph2 = new TGraphErrors(5, x, y2, zero, ey_stat2);
graph2->SetMarkerStyle(24);
graph2->Draw("P");
// Now we have to somehow depict the sys errors
TGraphErrors *graph2_sys = new TGraphErrors(5, x, y2, zero, ey_sys2);
graph2_sys->Draw("[]");
return c43;
}
End_Macro
Begin_Html
npoints : Number of points in gxwork and in gywork.
Compute the closest distance of approach from point px,py to this line.
The distance is computed in pixels units.
End_Html */
// Are we on the axis?
Int_t distance;
if (theGraph->GetHistogram()) {
distance = theGraph->GetHistogram()->DistancetoPrimitive(px,py);
if (distance <= 5) return distance;
}
// Somewhere on the graph points?
const Int_t big = 9999;
const Int_t kMaxDiff = 10;
Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
// return if point is not in the graph area
if (px <= puxmin) return big;
if (py >= puymin) return big;
if (px >= puxmax) return big;
if (py <= puymax) return big;
// check if point is near one of the graph points
Int_t i, pxp, pyp, d;
distance = big;
Int_t theNpoints = theGraph->GetN();
Double_t *theX, *theY;
if (theGraph->InheritsFrom(TGraphPolar::Class())) {
TGraphPolar *theGraphPolar = (TGraphPolar*) theGraph;
theX = theGraphPolar->GetXpol();
theY = theGraphPolar->GetYpol();
} else {
theX = theGraph->GetX();
theY = theGraph->GetY();
}
for (i=0;i
This member function is called when a graph is clicked with the locator.
If the left mouse button is clicked on one of the line end points, this point
follows the cursor until button is released.
If the middle mouse button clicked, the line is moved parallel to itself
until the button is released.
End_Html */
Int_t i, d;
Double_t xmin, xmax, ymin, ymax, dx, dy, dxr, dyr;
const Int_t kMaxDiff = 3;
static Bool_t middle, badcase;
static Int_t ipoint, pxp, pyp;
static Int_t px1,px2,py1,py2;
static Int_t pxold, pyold, px1old, py1old, px2old, py2old;
static Int_t dpx, dpy;
static Int_t *x=0, *y=0;
if (!theGraph->IsEditable() || theGraph->InheritsFrom(TGraphPolar::Class())) {
gPad->SetCursor(kHand);
return;
}
if (!gPad->IsEditable()) return;
Int_t theNpoints = theGraph->GetN();
Double_t *theX = theGraph->GetX();
Double_t *theY = theGraph->GetY();
switch (event) {
case kButton1Down:
badcase = kFALSE;
gVirtualX->SetLineColor(-1);
theGraph->TAttLine::Modify(); //Change line attributes only if necessary
px1 = gPad->XtoAbsPixel(gPad->GetX1());
py1 = gPad->YtoAbsPixel(gPad->GetY1());
px2 = gPad->XtoAbsPixel(gPad->GetX2());
py2 = gPad->YtoAbsPixel(gPad->GetY2());
ipoint = -1;
if (x || y) break;
x = new Int_t[theNpoints+1];
y = new Int_t[theNpoints+1];
for (i=0;i
Input parameters:
The aspect of the histogram is done according to the value of the chopt.
The original code is from an underlaying routine for Draw based on the
CERN GD3 routine TVIPTE:
Reference Marlow and Powell, Harwell report No.R.7092.1972
MCCONALOGUE, Computer Journal VOL.13, NO4, NOV1970P p392 6
Exclusion graphs
When a graph is painted with the option "C" or "L" it is
possible to draw a filled area on one side of the line. This is useful to show
exclusion zones.
100*ff+ll = ffll
The current fill area attributes are used to draw the hatched zone.
End_Html
Begin_Macro(source)
../../../tutorials/graphs/exclusiongraph.C
End_Macro
Begin_Html
Graphs with error bars
Three classes are available to handle graphs with error bars:
TGraphErrors, TGraphAsymmErrors and TGraphBentErrors.
The following drawing options are specific to graphs with error bars:
"Z"
Do not draw small horizontal and vertical lines the end of the error bars.
Without "Z", the default is to draw these.
">"
An arrow is drawn at the end of the error bars.
The size of the arrow is set to 2/3 of the marker size.
"|>"
A filled arrow is drawn at the end of the error bars.
The size of the arrow is set to 2/3 of the marker size.
"X"
Do not draw error bars. By default, graph classes that have errors
are drawn with the errors (TGraph itself has no errors, and so this option
has no effect.)
"||"
Draw only the small vertical/horizontal lines at the ends of the
error bars, without drawing the bars themselves. This option is
interesting to superimpose statistical-only errors on top of a graph
with statistical+systematic errors.
"[]"
Does the same as option "||" except that it draws additional marks at the
ends of the small vertical/horizontal lines. It makes plots less ambiguous
in case several graphs are drawn on the same picture.
"0"
By default, when a data point is outside the visible range along the Y
axis, the error bars are not drawn. This option forces error bars' drawing for
the data points outside the visible range along the Y axis (see example below).
"2"
Error rectangles are drawn.
"3"
A filled area is drawn through the end points of the vertical error bars.
"4"
A smoothed filled area is drawn through the end points of the vertical error
bars.
"5"
Error rectangles are drawn like option "2". In addition the contour line
around the boxes is drawn. This can be useful when boxes' fill colors are very
light or in gray scale mode.
TGraphErrors
A TGraphErrors is a TGraph with error bars. The errors are
defined along X and Y and are symmetric: The left and right errors are the same
along X and the bottom and up errors are the same along Y.
End_Html
Begin_Macro(source)
{
TCanvas *c4 = new TCanvas("c4","c4",200,10,600,400);
double x[] = {0, 1, 2, 3, 4};
double y[] = {0, 2, 4, 1, 3};
double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
double ey[] = {1, 0.5, 1, 0.5, 1};
TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
ge->Draw("ap");
return c4;
}
End_Macro
Begin_Html
TGraphAsymmErrors
A TGraphAsymmErrors is like a TGraphErrors but the errors
defined along X and Y are not symmetric: The left and right errors are
different along X and the bottom and up errors are different along Y.
End_Html
Begin_Macro(source)
{
TCanvas *c44 = new TCanvas("c44","c44",200,10,600,400);
double ax[] = {0, 1, 2, 3, 4};
double ay[] = {0, 2, 4, 1, 3};
double aexl[] = {0.1, 0.2, 0.3, 0.4, 0.5};
double aexh[] = {0.5, 0.4, 0.3, 0.2, 0.1};
double aeyl[] = {1, 0.5, 1, 0.5, 1};
double aeyh[] = {0.5, 1, 0.5, 1, 0.5};
TGraphAsymmErrors* gae = new TGraphAsymmErrors(5, ax, ay, aexl, aexh, aeyl, aeyh);
gae->SetFillColor(2);
gae->SetFillStyle(3001);
gae->Draw("a2");
gae->Draw("p");
return c44;
}
End_Macro
Begin_Html
TGraphBentErrors
A TGraphBentErrors is like a TGraphAsymmErrors.
An extra parameter allows to bend the error bars to better see them
when several graphs are drawn on the same plot.
End_Html
Begin_Macro(source)
{
TCanvas *c45 = new TCanvas("c45","c45",200,10,600,400);
const Int_t n = 10;
Double_t x[n] = {-0.22, 0.05, 0.25, 0.35, 0.5, 0.61,0.7,0.85,0.89,0.95};
Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};
Double_t exld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
Double_t eyld[n] = {.0,.0,.05,.0,.0,.0,.0,.0,.0,.0};
Double_t exhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
Double_t eyhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.05,.0};
TGraphBentErrors *gr = new TGraphBentErrors(n,x,y,exl,exh,eyl,eyh,exld,exhd,eyld,eyhd);
gr->SetTitle("TGraphBentErrors Example");
gr->SetMarkerColor(4);
gr->SetMarkerStyle(21);
gr->Draw("ALP");
return c45;
}
End_Macro
Begin_Html
TGraphPolar options
The drawing options for the polar graphs are the following:
End_Html
Begin_Macro(source)
{
TCanvas *c46 = new TCanvas("c46","c46",500,500);
TGraphPolar * grP1 = new TGraphPolar();
grP1->SetTitle("TGraphPolar example");
grP1->SetPoint(0, (1*TMath::Pi())/4., 0.05);
grP1->SetPoint(1, (2*TMath::Pi())/4., 0.10);
grP1->SetPoint(2, (3*TMath::Pi())/4., 0.15);
grP1->SetPoint(3, (4*TMath::Pi())/4., 0.20);
grP1->SetPoint(4, (5*TMath::Pi())/4., 0.25);
grP1->SetPoint(5, (6*TMath::Pi())/4., 0.30);
grP1->SetPoint(6, (7*TMath::Pi())/4., 0.35);
grP1->SetPoint(7, (8*TMath::Pi())/4., 0.40);
grP1->SetMarkerStyle(20);
grP1->SetMarkerSize(1.);
grP1->SetMarkerColor(4);
grP1->SetLineColor(4);
grP1->Draw("ALP");
// Update, otherwise GetPolargram returns 0
c46->Update();
grP1->GetPolargram()->SetToRadian();
return c46;
}
End_Macro
Begin_Html
End_Html */
//______________________________________________________________________________
TGraphPainter::TGraphPainter()
{
/* Begin_Html
Default constructor
End_Html */
}
//______________________________________________________________________________
TGraphPainter::~TGraphPainter()
{
/* Begin_Html
Destructor.
End_Html */
}
//______________________________________________________________________________
void TGraphPainter::ComputeLogs(Int_t npoints, Int_t opt)
{
/* Begin_Html
Compute the logarithm of global variables gxwork and gywork
according to the value of Options and put the results in the global
variables gxworkl and gyworkl.
"O"
Polar labels are drawn orthogonally to the polargram radius.
"P"
Polymarker are drawn at each point position.
"E"
Draw error bars.
"F"
Draw fill area (closed polygon).
"A"
Force axis redrawing even if a polargram already exists.
"N"
Disable the display of the polar labels.
End_Html */
Int_t i;
memcpy(gxworkl,gxwork,npoints*8);
memcpy(gyworkl,gywork,npoints*8);
if (gPad->GetLogx()) {
for (i=0;i
End_Html */
const char *where = "PaintGraphHist";
Int_t optionLine , optionAxis , optionCurve, optionStar, optionMark;
Int_t optionBar , optionRot , optionOne , optionOff ;
Int_t optionFill , optionZ;
Int_t optionHist , optionBins , optionMarker;
Int_t i, j, npt;
Int_t drawtype=0, drawborder, drawbordersav;
Double_t xlow, xhigh, ylow, yhigh;
Double_t wmin, wmax;
Double_t dbar, offset, wminstep;
Double_t delta = 0;
Double_t ylast = 0;
Double_t xi, xi1, xj, xj1, yi1, yi, yj, yj1, xwmin, ywmin;
Int_t first, last, nbins;
Int_t fillarea;
char choptaxis[10] = " ";
if (npoints <= 0) {
Error(where, "illegal number of points (%d)", npoints);
return;
}
TString opt = chopt;
opt.ToUpper();
if(opt.Contains("H")) optionHist = 1; else optionHist = 0;
if(opt.Contains("F")) optionFill = 1; else optionFill = 0;
if(opt.Contains("C")) optionCurve= 1; else optionCurve= 0;
if(opt.Contains("*")) optionStar = 1; else optionStar = 0;
if(opt.Contains("R")) optionRot = 1; else optionRot = 0;
if(opt.Contains("1")) optionOne = 1; else optionOne = 0;
if(opt.Contains("B")) optionBar = 1; else optionBar = 0;
if(opt.Contains("N")) optionBins = 1; else optionBins = 0;
if(opt.Contains("L")) optionLine = 1; else optionLine = 0;
if(opt.Contains("P")) optionMark = 1; else optionMark = 0;
if(opt.Contains("A")) optionAxis = 1; else optionAxis = 0;
if(opt.Contains("][")) optionOff = 1; else optionOff = 0;
if(opt.Contains("P0")) optionMark = 10;
Int_t optionFill2 = 0;
if(opt.Contains("F") && opt.Contains("2")) {
optionFill = 0; optionFill2 = 1;
}
// Set Clipping option
Option_t *noClip;
if (theGraph->TestBit(TGraph::kClipFrame)) noClip = "";
else noClip = "C";
gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
optionZ = 1;
if (optionStar) theGraph->SetMarkerStyle(3);
first = 1;
last = npoints;
nbins = last - first + 1;
// Draw the Axis with a fixed number of division: 510
Double_t baroffset = gStyle->GetBarOffset();
Double_t barwidth = gStyle->GetBarWidth();
Double_t rwxmin = gPad->GetUxmin();
Double_t rwxmax = gPad->GetUxmax();
Double_t rwymin = gPad->GetUymin();
Double_t rwymax = gPad->GetUymax();
Double_t uxmin = gPad->PadtoX(rwxmin);
Double_t uxmax = gPad->PadtoX(rwxmax);
Double_t rounding = (uxmax-uxmin)*1.e-5;
drawborder = gStyle->GetDrawBorder();
if (optionAxis) {
Int_t nx1, nx2, ndivx, ndivy, ndiv;
choptaxis[0] = 0;
Double_t rwmin = rwxmin;
Double_t rwmax = rwxmax;
ndivx = gStyle->GetNdivisions("X");
ndivy = gStyle->GetNdivisions("Y");
if (ndivx > 1000) {
nx2 = ndivx/100;
nx1 = TMath::Max(1, ndivx%100);
ndivx = 100*nx2 + Int_t(Double_t(nx1)*gPad->GetAbsWNDC());
}
ndiv =TMath::Abs(ndivx);
// coverity [Calling risky function]
if (ndivx < 0) strlcat(choptaxis, "N",10);
if (gPad->GetGridx()) {
// coverity [Calling risky function]
strlcat(choptaxis, "W",10);
}
if (gPad->GetLogx()) {
rwmin = TMath::Power(10,rwxmin);
rwmax = TMath::Power(10,rwxmax);
// coverity [Calling risky function]
strlcat(choptaxis, "G",10);
}
TGaxis *axis = new TGaxis();
axis->SetLineColor(gStyle->GetAxisColor("X"));
axis->SetTextColor(gStyle->GetLabelColor("X"));
axis->SetTextFont(gStyle->GetLabelFont("X"));
axis->SetLabelSize(gStyle->GetLabelSize("X"));
axis->SetLabelOffset(gStyle->GetLabelOffset("X"));
axis->SetTickSize(gStyle->GetTickLength("X"));
axis->PaintAxis(rwxmin,rwymin,rwxmax,rwymin,rwmin,rwmax,ndiv,choptaxis);
choptaxis[0] = 0;
rwmin = rwymin;
rwmax = rwymax;
if (ndivy < 0) {
nx2 = ndivy/100;
nx1 = TMath::Max(1, ndivy%100);
ndivy = 100*nx2 + Int_t(Double_t(nx1)*gPad->GetAbsHNDC());
// coverity [Calling risky function]
strlcat(choptaxis, "N",10);
}
ndiv =TMath::Abs(ndivy);
if (gPad->GetGridy()) {
// coverity [Calling risky function]
strlcat(choptaxis, "W",10);
}
if (gPad->GetLogy()) {
rwmin = TMath::Power(10,rwymin);
rwmax = TMath::Power(10,rwymax);
// coverity [Calling risky function]
strlcat(choptaxis,"G",10);
}
axis->SetLineColor(gStyle->GetAxisColor("Y"));
axis->SetTextColor(gStyle->GetLabelColor("Y"));
axis->SetTextFont(gStyle->GetLabelFont("Y"));
axis->SetLabelSize(gStyle->GetLabelSize("Y"));
axis->SetLabelOffset(gStyle->GetLabelOffset("Y"));
axis->SetTickSize(gStyle->GetTickLength("Y"));
axis->PaintAxis(rwxmin,rwymin,rwxmin,rwymax,rwmin,rwmax,ndiv,choptaxis);
delete axis;
}
// Set attributes
theGraph->TAttLine::Modify();
theGraph->TAttFill::Modify();
theGraph->TAttMarker::Modify();
// Min-Max scope
if (!optionRot) {wmin = x[0]; wmax = x[1];}
else {wmin = y[0]; wmax = y[1];}
if (!optionBins) delta = (wmax - wmin)/ Double_t(nbins);
Int_t fwidth = gPad->GetFrameLineWidth();
TFrame *frame = gPad->GetFrame();
if (frame) fwidth = frame->GetLineWidth();
if (optionOff) fwidth = 1;
Double_t dxframe = gPad->AbsPixeltoX(fwidth/2) - gPad->AbsPixeltoX(0);
Double_t vxmin = gPad->PadtoX(gPad->GetUxmin() + dxframe);
Double_t vxmax = gPad->PadtoX(gPad->GetUxmax() - dxframe);
Double_t dyframe = -gPad->AbsPixeltoY(fwidth/2) + gPad->AbsPixeltoY(0);
Double_t vymin = gPad->GetUymin() + dyframe; //y already in log scale
vxmin = TMath::Max(vxmin,wmin);
vxmax = TMath::Min(vxmax,wmax);
// Draw the histogram with a fill area
gxwork = new Double_t[2*npoints+10];
gywork = new Double_t[2*npoints+10];
gxworkl = new Double_t[2*npoints+10];
gyworkl = new Double_t[2*npoints+10];
if (optionFill && !optionCurve) {
fillarea = kTRUE;
if (!optionRot) {
gxwork[0] = vxmin;
if (!optionOne) gywork[0] = TMath::Min(TMath::Max((Double_t)0,gPad->GetUymin())
,gPad->GetUymax());
else gywork[0] = gPad->GetUymin();
npt = 2;
for (j=first; j<=last;j++) {
if (!optionBins) {
gxwork[npt-1] = gxwork[npt-2];
gxwork[npt] = wmin+((j-first+1)*delta);
if (gxwork[npt] < gxwork[0]) gxwork[npt] = gxwork[0];
}
else {
xj1 = x[j]; xj = x[j-1];
if (xj1 < xj) {
if (j != last) Error(where, "X must be in increasing order");
else Error(where, "X must have N+1 values with option N");
return;
}
gxwork[npt-1] = x[j-1]; gxwork[npt] = x[j];
}
gywork[npt-1] = y[j-1];
gywork[npt] = y[j-1];
if (gywork[npt] < vymin) {gywork[npt] = vymin; gywork[npt-1] = vymin;}
if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
else gxwork[npt-2] = TMath::Min(gxwork[npt], uxmax);
if (j == last) {
gxwork[npt-1] = gxwork[npt-2];
gywork[npt-1] = gywork[0];
//make sure that the fill area does not overwrite the frame
//take into account the frame linewidth
if (gxwork[0 ] < vxmin) {gxwork[0 ] = vxmin; gxwork[1 ] = vxmin;}
if (gywork[0] < vymin) {gywork[0] = vymin; gywork[npt-1] = vymin;}
//transform to log ?
ComputeLogs(npt, optionZ);
gPad->PaintFillArea(npt,gxworkl,gyworkl);
if (drawborder) {
if (!fillarea) gyworkl[0] = ylast;
gPad->PaintPolyLine(npt-1,gxworkl,gyworkl,noClip);
}
continue;
}
} //endfor (j=first; j<=last;j++) {
}
else {
gywork[0] = wmin;
if (!optionOne) gxwork[0] = TMath::Max((Double_t)0,gPad->GetUxmin());
else gxwork[0] = gPad->GetUxmin();
npt = 2;
for (j=first; j<=last;j++) {
if (!optionBins) {
gywork[npt-1] = gywork[npt-2];
gywork[npt] = wmin+((j-first+1)*delta);
}
else {
yj1 = y[j]; yj = y[j-1];
if (yj1 < yj) {
if (j != last) Error(where, "Y must be in increasing order");
else Error(where, "Y must have N+1 values with option N");
return;
}
gywork[npt-1] = y[j-1]; gywork[npt] = y[j];
}
gxwork[npt-1] = x[j-1]; gxwork[npt] = x[j-1];
if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
if (j == last) {
gywork[npt-1] = gywork[npt-2];
gxwork[npt-1] = gxwork[0];
ComputeLogs(npt, optionZ);
gPad->PaintFillArea(npt,gxworkl,gyworkl);
if (drawborder) {
if (!fillarea) gyworkl[0] = ylast;
gPad->PaintPolyLine(npt-1,gxworkl,gyworkl,noClip);
}
continue;
}
} //endfor (j=first; j<=last;j++)
}
theGraph->TAttLine::Modify();
theGraph->TAttFill::Modify();
}
// Draw a standard Histogram (default)
if ((optionHist) || strlen(chopt) == 0) {
if (!optionRot) {
gxwork[0] = wmin;
gywork[0] = gPad->GetUymin();
ywmin = gywork[0];
npt = 2;
for (i=first; i<=last;i++) {
if (!optionBins) {
gxwork[npt-1] = gxwork[npt-2];
gxwork[npt] = wmin+((i-first+1)*delta);
}
else {
xi1 = x[i]; xi = x[i-1];
if (xi1 < xi) {
if (i != last) Error(where, "X must be in increasing order");
else Error(where, "X must have N+1 values with option N");
return;
}
gxwork[npt-1] = x[i-1]; gxwork[npt] = x[i];
}
gywork[npt-1] = y[i-1];
gywork[npt] = y[i-1];
if (gywork[npt] < vymin) {gywork[npt] = vymin; gywork[npt-1] = vymin;}
if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
else gxwork[npt-2] = TMath::Min(gxwork[npt], uxmax);
if (i == last) {
gxwork[npt-1] = gxwork[npt-2];
gywork[npt-1] = gywork[0];
//make sure that the fill area does not overwrite the frame
//take into account the frame linewidth
if (gxwork[0] < vxmin) {gxwork[0] = vxmin; gxwork[1 ] = vxmin;}
if (gywork[0] < vymin) {gywork[0] = vymin; gywork[npt-1] = vymin;}
ComputeLogs(npt, optionZ);
// do not draw the two vertical lines on the edges
Int_t nbpoints = npt-2;
Int_t point1 = 1;
if (optionOff) {
// remove points before the low cutoff
Int_t ip;
for (ip=point1; ip<=nbpoints; ip++) {
if (gyworkl[ip] != ywmin) {
point1 = ip;
break;
}
}
// remove points after the high cutoff
Int_t point2 = nbpoints;
for (ip=point2; ip>=point1; ip--) {
if (gyworkl[ip] != ywmin) {
point2 = ip;
break;
}
}
nbpoints = point2-point1+1;
} else {
// if the 1st or last bin are not on the pad limits the
// the two vertical lines on the edges are added.
if (gxwork[0] > gPad->GetUxmin()) { nbpoints++; point1 = 0; }
if (gxwork[nbpoints] < gPad->GetUxmax()) nbpoints++;
}
gPad->PaintPolyLine(nbpoints,&gxworkl[point1],&gyworkl[point1],noClip);
continue;
}
} //endfor (i=first; i<=last;i++)
}
else {
gywork[0] = wmin;
gxwork[0] = TMath::Max((Double_t)0,gPad->GetUxmin());
xwmin = gxwork[0];
npt = 2;
for (i=first; i<=last;i++) {
if (!optionBins) {
gywork[npt-1] = gywork[npt-2];
gywork[npt] = wmin+((i-first+1)*delta);
}
else {
yi1 = y[i]; yi = y[i-1];
if (yi1 < yi) {
if (i != last) Error(where, "Y must be in increasing order");
else Error(where, "Y must have N+1 values with option N");
return;
}
gywork[npt-1] = y[i-1]; gywork[npt] = y[i];
}
gxwork[npt-1] = x[i-1]; gxwork[npt] = x[i-1];
if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
if (i == last) {
gywork[npt-1] = gywork[npt-2];
gxwork[npt-1] = xwmin;
ComputeLogs(npt, optionZ);
gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
continue;
}
} //endfor (i=first; i<=last;i++)
}
}
// Draw the histogram with a smooth Curve.
// The smoothing is done by the method Smooth()
if (optionCurve) {
if (!optionFill) drawtype = 1;
else {
if (!optionOne) drawtype = 2;
else drawtype = 3;
}
if (!optionRot) {
npt = 0;
for (i=first; i<=last;i++) {
npt++;
if (!optionBins) gxwork[npt-1] = wmin+(i-first)*delta+0.5*delta;
else {
xi1 = x[i]; xi = x[i-1];
if (xi1 < xi) {
if (i != last) Error(where, "X must be in increasing order");
else Error(where, "X must have N+1 values with option N");
return;
}
gxwork[npt-1] = x[i-1] + 0.5*(x[i]-x[i-1]);
}
if (gxwork[npt-1] < uxmin || gxwork[npt-1] > uxmax) {
npt--;
continue;
}
gywork[npt-1] = y[i-1];
ComputeLogs(npt, optionZ);
if ((gyworkl[npt-1] < rwymin) || (gyworkl[npt-1] > rwymax)) {
if (npt > 2) {
ComputeLogs(npt, optionZ);
Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
}
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
continue;
}
if (npt >= 50) {
ComputeLogs(50, optionZ);
Smooth(theGraph, 50,gxworkl,gyworkl,drawtype);
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
}
} //endfor (i=first; i<=last;i++)
if (npt > 1) {
ComputeLogs(npt, optionZ);
Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
}
}
else {
drawtype = drawtype+10;
npt = 0;
for (i=first; i<=last;i++) {
npt++;
if (!optionBins) gywork[npt-1] = wmin+(i-first)*delta+0.5*delta;
else {
yi1 = y[i]; yi = y[i-1];
if (yi1 < yi) {
if (i != last) Error(where, "Y must be in increasing order");
else Error(where, "Y must have N+1 values with option N");
return;
}
gywork[npt-1] = y[i-1] + 0.5*(y[i]-y[i-1]);
}
gxwork[npt-1] = x[i-1];
ComputeLogs(npt, optionZ);
if ((gxworkl[npt] < uxmin) || (gxworkl[npt] > uxmax)) {
if (npt > 2) {
ComputeLogs(npt, optionZ);
Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
}
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
continue;
}
if (npt >= 50) {
ComputeLogs(50, optionZ);
Smooth(theGraph, 50,gxworkl,gyworkl,drawtype);
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
}
} //endfor (i=first; i<=last;i++)
if (npt > 1) {
ComputeLogs(npt, optionZ);
Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
}
}
}
// Draw the histogram with a simple line or/and a marker
optionMarker = 0;
if ((optionStar) || (optionMark))optionMarker=1;
if ((optionMarker) || (optionLine)) {
wminstep = wmin + 0.5*delta;
Axis_t ax1,ax2,ay1,ay2;
gPad->GetRangeAxis(ax1,ay1,ax2,ay2);
Int_t ax1Pix = gPad->XtoAbsPixel(ax1);
Int_t ax2Pix = gPad->XtoAbsPixel(ax2);
Int_t ay1Pix = gPad->YtoAbsPixel(ay1);
Int_t ay2Pix = gPad->YtoAbsPixel(ay2);
Int_t nrPix;
if (!optionRot)
nrPix = ax2Pix-ax1Pix+1;
else
nrPix = ay2Pix-ay1Pix+1;
// Make here decision whether it should be painted in high or low resolution
Int_t ip, ipix, lowRes = 0;
if (3*nrPix < last-first+1) {
lowRes = 1;
}
if (optionFill2) lowRes = 0;
if (opt.Contains("9")) lowRes = 0;
if (lowRes) {
Double_t *minPix = new Double_t[nrPix];
Double_t *maxPix = new Double_t[nrPix];
Double_t *centrPix = new Double_t[nrPix];
Int_t *nrEntries = new Int_t[nrPix];
for (ip = 0; ip < nrPix; ip++) {
minPix[ip] = 1e100;
maxPix[ip] = -1e100;
nrEntries[ip] = 0;
}
for (ip = first; ip < last; ip++) {
Double_t xw;
if (!optionBins) xw = wmin + (ip-first)*delta+0.5*delta;
else xw = x[ip-1] + 0.5*(x[ip]-x[ip-1]);;
if (!optionRot) {
Int_t ix = gPad->XtoAbsPixel(gPad->XtoPad(xw))-ax1Pix;
if (ix < 0) ix = 0;
if (ix >= nrPix) ix = nrPix-1;
Int_t yPixel = gPad->YtoAbsPixel(y[ip-1]);
if (yPixel >= ay1Pix) continue;
if (minPix[ix] > yPixel) minPix[ix] = yPixel;
if (maxPix[ix] < yPixel) maxPix[ix] = yPixel;
(nrEntries[ix])++;
} else {
Int_t iy = gPad->YtoAbsPixel(gPad->YtoPad(y[ip-1]))-ay1Pix;
if (iy < 0) iy = 0;
if (iy >= nrPix) iy = nrPix-1;;
Int_t xPixel = gPad->XtoAbsPixel(gPad->XtoPad(xw));
if (minPix[iy] > xPixel) minPix[iy] = xPixel;
if (maxPix[iy] < xPixel) maxPix[iy] = xPixel;
(nrEntries[iy])++;
}
}
for (ipix = 0; ipix < nrPix; ipix++) {
if (nrEntries[ipix] > 0)
centrPix[ipix] = (minPix[ipix]+maxPix[ipix])/2.0;
else
centrPix[ipix] = 2*TMath::Max(TMath::Abs(minPix[ipix]),
TMath::Abs(maxPix[ipix]));
}
Double_t *xc = new Double_t[nrPix];
Double_t *yc = new Double_t[nrPix];
Double_t xcadjust = 0.3*(gPad->AbsPixeltoX(ax1Pix+1) - gPad->AbsPixeltoX(ax1Pix));
Double_t ycadjust = 0.3*(gPad->AbsPixeltoY(ay1Pix) - gPad->AbsPixeltoY(ay1Pix+1));
Int_t nrLine = 0;
for (ipix = 0; ipix < nrPix; ipix++) {
if (minPix[ipix] <= maxPix[ipix]) {
Double_t xl[2]; Double_t yl[2];
if (!optionRot) {
xc[nrLine] = gPad->AbsPixeltoX(ax1Pix+ipix) + xcadjust;
yc[nrLine] = gPad->AbsPixeltoY((Int_t)centrPix[ipix]);
xl[0] = xc[nrLine];
yl[0] = gPad->AbsPixeltoY((Int_t)minPix[ipix]);
xl[1] = xc[nrLine];
yl[1] = gPad->AbsPixeltoY((Int_t)maxPix[ipix]);
} else {
yc[nrLine] = gPad->AbsPixeltoY(ay1Pix+ipix) + ycadjust;
xc[nrLine] = gPad->AbsPixeltoX((Int_t)centrPix[ipix]);
xl[0] = gPad->AbsPixeltoX((Int_t)minPix[ipix]);
yl[0] = yc[nrLine];
xl[1] = gPad->AbsPixeltoX((Int_t)maxPix[ipix]);
yl[1] = yc[nrLine];
}
if (!optionZ && gPad->GetLogx()) {
if (xc[nrLine] > 0) xc[nrLine] = TMath::Log10(xc[nrLine]);
else xc[nrLine] = gPad->GetX1();
for (Int_t il = 0; il < 2; il++) {
if (xl[il] > 0) xl[il] = TMath::Log10(xl[il]);
else xl[il] = gPad->GetX1();
}
}
if (!optionZ && gPad->GetLogy()) {
if (yc[nrLine] > 0) yc[nrLine] = TMath::Log10(yc[nrLine]);
else yc[nrLine] = gPad->GetY1();
for (Int_t il = 0; il < 2; il++) {
if (yl[il] > 0) yl[il] = TMath::Log10(yl[il]);
else yl[il] = gPad->GetY1();
}
}
gPad->PaintPolyLine(2,xl,yl,noClip);
nrLine++;
}
}
gPad->PaintPolyLine(nrLine,xc,yc,noClip);
delete [] xc;
delete [] yc;
delete [] minPix;
delete [] maxPix;
delete [] centrPix;
delete [] nrEntries;
} else {
if (!optionRot) {
npt = 0;
for (i=first; i<=last;i++) {
npt++;
if (!optionBins) gxwork[npt-1] = wmin+(i-first)*delta+0.5*delta;
else {
xi1 = x[i]; xi = x[i-1];
if (xi1 < xi) {
if (i != last) Error(where, "X must be in increasing order");
else Error(where, "X must have N+1 values with option N");
return;
}
gxwork[npt-1] = x[i-1] + 0.5*(x[i]-x[i-1]);
}
if (gxwork[npt-1] < uxmin || gxwork[npt-1] > uxmax) { npt--; continue;}
if ((optionMark != 10) && (optionLine == 0)) {
if (y[i-1] <= rwymin) {npt--; continue;}
}
gywork[npt-1] = y[i-1];
gywork[npt] = y[i-1]; //new
if ((gywork[npt-1] < rwymin) || ((gywork[npt-1] > rwymax) && !optionFill2)) {
if ((gywork[npt-1] < rwymin)) gywork[npt-1] = rwymin;
if ((gywork[npt-1] > rwymax)) gywork[npt-1] = rwymax;
if (npt > 2) {
if (optionMarker) {
ComputeLogs(npt, optionZ);
gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
}
if (optionLine) {
if (!optionMarker) ComputeLogs(npt, optionZ);
gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
}
}
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
continue;
}
if (npt >= 50) {
if (optionMarker) {
ComputeLogs(50, optionZ);
gPad->PaintPolyMarker(50,gxworkl,gyworkl);
}
if (optionLine) {
if (!optionMarker) ComputeLogs(50, optionZ);
if (optionFill2) {
gxworkl[npt] = gxworkl[npt-1]; gyworkl[npt] = rwymin;
gxworkl[npt+1] = gxworkl[0]; gyworkl[npt+1] = rwymin;
gPad->PaintFillArea(52,gxworkl,gyworkl);
}
gPad->PaintPolyLine(50,gxworkl,gyworkl);
}
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
}
} //endfor (i=first; i<=last;i++)
if (optionMarker && npt > 0) {
ComputeLogs(npt, optionZ);
gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
}
if (optionLine && npt > 1) {
if (!optionMarker) ComputeLogs(npt, optionZ);
if (optionFill2) {
gxworkl[npt] = gxworkl[npt-1]; gyworkl[npt] = rwymin;
gxworkl[npt+1] = gxworkl[0]; gyworkl[npt+1] = rwymin;
gPad->PaintFillArea(npt+2,gxworkl,gyworkl);
}
gPad->PaintPolyLine(npt,gxworkl,gyworkl);
}
}
else {
npt = 0;
for (i=first; i<=last;i++) {
npt++;
if (!optionBins) gywork[npt-1] = wminstep+(i-first)*delta+0.5*delta;
else {
yi1 = y[i]; yi = y[i-1];
if (yi1 < yi) {
if (i != last) Error(where, "Y must be in increasing order");
else Error(where, "Y must have N+1 values with option N");
return;
}
gywork[npt-1] = y[i-1] + 0.5*(y[i]-y[i-1]);
}
gxwork[npt-1] = x[i-1];
if ((gxwork[npt-1] < uxmin) || (gxwork[npt-1] > uxmax)) {
if (npt > 2) {
if (optionMarker) {
ComputeLogs(npt, optionZ);
gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
}
if (optionLine) {
if (!optionMarker) ComputeLogs(npt, optionZ);
gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
}
}
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
continue;
}
if (npt >= 50) {
if (optionMarker) {
ComputeLogs(50, optionZ);
gPad->PaintPolyMarker(50,gxworkl,gyworkl);
}
if (optionLine) {
if (!optionMarker) ComputeLogs(50, optionZ);
gPad->PaintPolyLine(50,gxworkl,gyworkl);
}
gxwork[0] = gxwork[npt-1];
gywork[0] = gywork[npt-1];
npt = 1;
}
} //endfor (i=first; i<=last;i++)
if (optionMarker && npt > 0) {
ComputeLogs(npt, optionZ);
gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
}
if (optionLine != 0 && npt > 1) {
if (!optionMarker) ComputeLogs(npt, optionZ);
gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
}
}
}
}
// Draw the histogram as a bar chart
if (optionBar) {
if (!optionBins) { offset = delta*baroffset; dbar = delta*barwidth; }
else {
if (!optionRot) {
offset = (x[1]-x[0])*baroffset;
dbar = (x[1]-x[0])*barwidth;
} else {
offset = (y[1]-y[0])*baroffset;
dbar = (y[1]-y[0])*barwidth;
}
}
drawbordersav = drawborder;
gStyle->SetDrawBorder(1);
if (!optionRot) {
xlow = wmin+offset;
xhigh = wmin+offset+dbar;
if (!optionOne) ylow = TMath::Min(TMath::Max((Double_t)0,gPad->GetUymin())
,gPad->GetUymax());
else ylow = gPad->GetUymin();
for (i=first; i<=last;i++) {
yhigh = y[i-1];
gxwork[0] = xlow;
gywork[0] = ylow;
gxwork[1] = xhigh;
gywork[1] = yhigh;
ComputeLogs(2, optionZ);
gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
if (!optionBins) {
xlow = xlow+delta;
xhigh = xhigh+delta;
}
else {
if (i < last) {
xi1 = x[i]; xi = x[i-1];
if (xi1 < xi) {
Error(where, "X must be in increasing order");
return;
}
offset = (x[i+1]-x[i])*baroffset;
dbar = (x[i+1]-x[i])*barwidth;
xlow = x[i] + offset;
xhigh = x[i] + offset + dbar;
}
}
} //endfor (i=first; i<=last;i++)
}
else {
ylow = wmin + offset;
yhigh = wmin + offset + dbar;
if (!optionOne) xlow = TMath::Max((Double_t)0,gPad->GetUxmin());
else xlow = gPad->GetUxmin();
for (i=first; i<=last;i++) {
xhigh = x[i-1];
gxwork[0] = xlow;
gywork[0] = ylow;
gxwork[1] = xhigh;
gywork[1] = yhigh;
ComputeLogs(2, optionZ);
gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
gPad->PaintBox(xlow,ylow,xhigh,yhigh);
if (!optionBins) {
ylow = ylow + delta;
yhigh = yhigh + delta;
}
else {
if (i < last) {
yi1 = y[i]; yi = y[i-1];
if (yi1 < yi) {
Error(where, "Y must be in increasing order");
return;
}
offset = (y[i+1]-y[i])*baroffset;
dbar = (y[i+1]-y[i])*barwidth;
ylow = y[i] + offset;
yhigh = y[i] + offset + dbar;
}
}
} //endfor (i=first; i<=last;i++)
}
gStyle->SetDrawBorder(drawbordersav);
}
gPad->ResetBit(TGraph::kClipFrame);
delete [] gxwork;
delete [] gywork;
delete [] gxworkl;
delete [] gyworkl;
}
//______________________________________________________________________________
void TGraphPainter::PaintGraphAsymmErrors(TGraph *theGraph, Option_t *option)
{
/* Begin_Html
Paint this TGraphAsymmErrors with its current attributes.
End_Html */
Double_t *xline = 0;
Double_t *yline = 0;
Int_t if1 = 0;
Int_t if2 = 0;
Double_t xb[4], yb[4];
const Int_t kBASEMARKER=8;
Double_t s2x, s2y, symbolsize, sbase;
Double_t x, y, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
static Float_t cxx[15] = {1,1,0.6,0.6,1,1,0.6,0.5,1,0.6,0.6,1,0.6,1,1};
static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
Int_t theNpoints = theGraph->GetN();
Double_t *theX = theGraph->GetX();
Double_t *theY = theGraph->GetY();
Double_t *theEXlow = theGraph->GetEXlow(); if (!theEXlow) return;
Double_t *theEYlow = theGraph->GetEYlow(); if (!theEYlow) return;
Double_t *theEXhigh = theGraph->GetEXhigh(); if (!theEXhigh) return;
Double_t *theEYhigh = theGraph->GetEYhigh(); if (!theEYhigh) return;
if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
Bool_t brackets = kFALSE;
Bool_t braticks = kFALSE;
if (strstr(option,"||") || strstr(option,"[]")) {
brackets = kTRUE;
if (strstr(option,"[]")) braticks = kTRUE;
}
Bool_t endLines = kTRUE;
if (strchr(option,'z')) endLines = kFALSE;
if (strchr(option,'Z')) endLines = kFALSE;
const char *arrowOpt = 0;
if (strchr(option,'>')) arrowOpt = ">";
if (strstr(option,"|>")) arrowOpt = "|>";
Bool_t axis = kFALSE;
if (strchr(option,'a')) axis = kTRUE;
if (strchr(option,'A')) axis = kTRUE;
if (axis) PaintGraphSimple(theGraph, option);
Bool_t option0 = kFALSE;
Bool_t option2 = kFALSE;
Bool_t option3 = kFALSE;
Bool_t option4 = kFALSE;
Bool_t option5 = kFALSE;
if (strchr(option,'0')) option0 = kTRUE;
if (strchr(option,'2')) option2 = kTRUE;
if (strchr(option,'3')) option3 = kTRUE;
if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
if (strchr(option,'5')) {option2 = kTRUE; option5 = kTRUE;}
if (option3) {
xline = new Double_t[2*theNpoints];
yline = new Double_t[2*theNpoints];
if (!xline || !yline) {
Error("Paint", "too many points, out of memory");
return;
}
if1 = 1;
if2 = 2*theNpoints;
}
theGraph->TAttLine::Modify();
TArrow arrow;
arrow.SetLineWidth(theGraph->GetLineWidth());
arrow.SetLineColor(theGraph->GetLineColor());
arrow.SetFillColor(theGraph->GetFillColor());
TBox box;
Double_t x1b,y1b,x2b,y2b;
box.SetLineWidth(theGraph->GetLineWidth());
box.SetLineColor(theGraph->GetLineColor());
box.SetFillColor(theGraph->GetFillColor());
box.SetFillStyle(theGraph->GetFillStyle());
symbolsize = theGraph->GetMarkerSize();
sbase = symbolsize*kBASEMARKER;
Int_t mark = theGraph->GetMarkerStyle();
Double_t cx = 0;
Double_t cy = 0;
if (mark >= 20 && mark <= 34) {
cx = cxx[mark-20];
cy = cyy[mark-20];
}
// Define the offset of the error bars due to the symbol size
s2x = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
s2y =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
Int_t dxend = Int_t(gStyle->GetEndErrorSize());
tx = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
ty =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
for (Int_t i=0;i"R"
Graph is drawn horizontaly, parallel to X axis. (default is vertically,
parallel to Y axis)
If option R is selected the user must give:
Otherwise the user must give:
"L"
A simple polyline beetwen every points is drawn.
"H"
An Histogram with equidistant bins is drawn as a polyline.
"F"
An histogram with equidistant bins is drawn as a fill area. Contour is not
drawn unless chopt='H' is also selected..
"N"
Non equidistant bins (default is equidistant). If N is the number of channels
array X and Y must be dimensionned as follow:
"F1"
Idem as 'F' except that fill area base line is the minimum of the pad instead
of Y=0.
"F2"
Draw a Fill area polyline connecting the center of bins
"C"
A smooth Curve is drawn.
"*"
A Star is plotted at the center of each bin.
"P"
Idem with the current marker.
"P0"
Idem with the current marker. Empty bins also drawn.
"B"
A Bar chart with equidistant bins is drawn as fill areas (Contours are drawn).
"9"
Force graph to be drawn in high resolution mode. By default, the graph is
drawn in low resolution in case the number of points is greater than the
number of pixels in the current pad.
"]["
"Cutoff" style. When this option is selected together with H option, the
first and last vertical lines of the histogram are not drawn.
Author - Marlow etc. Modified by - P. Ward Date - 3.10.1973
This method draws a smooth tangentially continuous curve through
the sequence of data points P(I) I=1,N where P(I)=(X(I),Y(I)).
The curve is approximated by a polygonal arc of short vectors.
The data points can represent open curves, P(1) != P(N) or closed
curves P(2) == P(N). If a tangential discontinuity at P(I) is
required, then set P(I)=P(I+1). Loops are also allowed.
End_Html */
Int_t i, k, kp, km, npointsMax, banksize, n2, npt;
Int_t maxiterations, finished;
Int_t jtype, ktype, closed;
Double_t sxmin, sxmax, symin, symax;
Double_t delta;
Double_t xorg, yorg;
Double_t ratio_signs, xratio, yratio;
Int_t flgic, flgis;
Int_t iw, loptx;
Double_t p1, p2, p3, p4, p5, p6;
Double_t w1, w2, w3;
Double_t a, b, c, r, s, t, z;
Double_t co, so, ct, st, ctu, stu, xnt;
Double_t dx1, dy1, dx2, dy2, dk1, dk2;
Double_t xo, yo, dx, dy, xt, yt;
Double_t xa, xb, ya, yb;
Double_t u1, u2, u3, tj;
Double_t cc, err;
Double_t sb, sth;
Double_t wsign, tsquare, tcube;
c = t = co = so = ct = st = ctu = stu = dx1 = dy1 = dx2 = dy2 = 0;
xt = yt = xa = xb = ya = yb = u1 = u2 = u3 = tj = sb = 0;
npointsMax = npoints*10;
n2 = npointsMax-2;
banksize = n2;
Double_t *qlx = new Double_t[npointsMax];
Double_t *qly = new Double_t[npointsMax];
if (!qlx || !qly) {
Error("Smooth", "not enough space in memory");
return;
}
// Decode the type of curve (drawtype).
loptx = kFALSE;
jtype = (drawtype%1000)-10;
if (jtype > 0) { ktype = jtype; loptx = kTRUE; }
else ktype = drawtype%1000;
Double_t ruxmin = gPad->GetUxmin();
Double_t ruymin = gPad->GetUymin();
if (ktype == 3) {
xorg = ruxmin;
yorg = ruymin;
} else {
xorg = TMath::Max((Double_t)0,ruxmin);
yorg = TMath::Min(TMath::Max((Double_t)0,ruymin),gPad->GetUymax());
}
// delta is the accuracy required in constructing the curve.
// If it is zero then the routine calculates a value otherwise
// it uses this value. (default is 0.0)
delta = 0.00055;
maxiterations = 20;
// Scale data to the range 0-ratio_signs in X, 0-1 in Y
// where ratio_signs is the ratio between the number of changes
// of sign in Y divided by the number of changes of sign in X
sxmin = x[0];
sxmax = x[0];
symin = y[0];
symax = y[0];
Double_t six = 1;
Double_t siy = 1;
for (i=1;i