Logo ROOT   6.08/07
Reference Guide
TGraphPainter.cxx
Go to the documentation of this file.
1 // @(#)root/histpainter:$Id: TGraphPainter.cxx,v 1.00
2 // Author: Olivier Couet
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TROOT.h"
13 #include "TGraphPainter.h"
14 #include "TMath.h"
15 #include "TGraph.h"
16 #include "TPolyLine.h"
17 #include "TPolyMarker.h"
18 #include "TVirtualPad.h"
19 #include "TView.h"
20 #include "TStyle.h"
21 #include "TH1.h"
22 #include "TF1.h"
23 #include "TPaveStats.h"
24 #include "TGaxis.h"
25 #include "TGraphAsymmErrors.h"
26 #include "TGraphBentErrors.h"
27 #include "TGraphPolargram.h"
28 #include "TGraphPolar.h"
29 #include "TGraphQQ.h"
30 #include "TLatex.h"
31 #include "TArrow.h"
32 #include "TFrame.h"
33 #include "TVirtualPadEditor.h"
34 
37 
39 
40 
41 ////////////////////////////////////////////////////////////////////////////////
42 
43 /*! \class TGraphPainter
44  \ingroup Histpainter
45  \brief The graph painter class. Implements all graphs' drawing's options.
46 
47 - [Introduction](#GP00)
48 - [Graphs' plotting options](#GP01)
49 - [Exclusion graphs](#GP02)
50 - [Graphs with error bars](#GP03)
51  - [TGraphErrors](#GP03a)
52  - [TGraphAsymmErrors](#GP03b)
53  - [TGraphBentErrors](#GP03c)
54 - [TGraphPolar options](#GP034)
55 
56 ### <a name="GP00"></a> Introduction
57 
58 Graphs are drawn via the painter `TGraphPainter` class. This class
59 implements techniques needed to display the various kind of
60 graphs i.e.: `TGraph`, `TGraphErrors`, `TGraphBentErrors` and `TGraphAsymmErrors`.
61 
62 To draw a graph `graph` it's enough to do:
63 
64  graph->Draw("AL");
65 
66 The option `AL` in the `Draw()` method means:
67 
68 1. The axis should be drawn (option `A`),
69 2. The graph should be drawn as a simple line (option `L`).
70 
71  By default a graph is drawn in the current pad in the current coordinate system.
72 To define a suitable coordinate system and draw the axis the option
73 `A` must be specified.
74 
75 `TGraphPainter` offers many options to paint the various kind of graphs.
76 
77 It is separated from the graph classes so that one can have graphs without the
78 graphics overhead, for example in a batch program.
79 
80 When a displayed graph is modified, there is no need to call `Draw()` again; the
81 image will be refreshed the next time the pad will be updated. A pad is updated
82 after one of these three actions:
83 
84 1. a carriage return on the ROOT command line,
85 2. a click inside the pad,
86 3. a call to `TPad::Update`.
87 
88 ### <a name="GP01"></a> Graphs' plotting options
89 Graphs can be drawn with the following options:
90 
91 | Option | Description |
92 |----------|-------------------------------------------------------------------|
93 | "A" | Axis are drawn around the graph |
94 | "I" | Combine with option 'A' it draws invisible axis |
95 | "L" | A simple polyline is drawn |
96 | "F" | A fill area is drawn ('CF' draw a smoothed fill area) |
97 | "C" | A smooth Curve is drawn |
98 | "*" | A Star is plotted at each point |
99 | "P" | The current marker is plotted at each point |
100 | "B" | A Bar chart is drawn |
101 | "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. |
102 | "X+" | The X-axis is drawn on the top side of the plot. |
103 | "Y+" | The Y-axis is drawn on the right side of the plot. |
104 
105 
106 Drawing options can be combined. In the following example the graph
107 is drawn as a smooth curve (option "C") with markers (option "P") and
108 with axes (option "A").
109 
110 Begin_Macro(source)
111 {
112  TCanvas *c1 = new TCanvas("c1","c1",200,10,600,400);
113 
114  c1->SetFillColor(42);
115  c1->SetGrid();
116 
117  const Int_t n = 20;
118  Double_t x[n], y[n];
119  for (Int_t i=0;i<n;i++) {
120  x[i] = i*0.1;
121  y[i] = 10*sin(x[i]+0.2);
122  }
123  gr = new TGraph(n,x,y);
124  gr->SetLineColor(2);
125  gr->SetLineWidth(4);
126  gr->SetMarkerColor(4);
127  gr->SetMarkerSize(1.5);
128  gr->SetMarkerStyle(21);
129  gr->SetTitle("Option ACP example");
130  gr->GetXaxis()->SetTitle("X title");
131  gr->GetYaxis()->SetTitle("Y title");
132  gr->Draw("ACP");
133 
134  // TCanvas::Update() draws the frame, after which one can change it
135  c1->Update();
136  c1->GetFrame()->SetFillColor(21);
137  c1->GetFrame()->SetBorderSize(12);
138  c1->Modified();
139  return c1;
140 }
141 End_Macro
142 
143 The following macro shows the option "B" usage. It can be combined with the
144 option "1".
145 
146 Begin_Macro(source)
147 {
148  TCanvas *c47 = new TCanvas("c47","c47",200,10,600,400);
149  c47->Divide(1,2);
150  const Int_t n = 20;
151  Double_t x[n], y[n];
152  for (Int_t i=0;i<n;i++) {
153  x[i] = i*0.1;
154  y[i] = 10*sin(x[i]+0.2)-6;
155  }
156  gr = new TGraph(n,x,y);
157  gr->SetFillColor(38);
158  c47->cd(1); gr->Draw("AB");
159  c47->cd(2); gr->Draw("AB1");
160  return c47;
161 }
162 End_Macro
163 
164 ### <a name="GP02"></a> Exclusion graphs
165 
166 When a graph is painted with the option `C` or `L` it is
167 possible to draw a filled area on one side of the line. This is useful to show
168 exclusion zones.
169 
170 This drawing mode is activated when the absolute value of the graph line
171 width (set by `SetLineWidth()`) is greater than 99. In that
172 case the line width number is interpreted as:
173 
174  100*ff+ll = ffll
175 
176 - The two digits number `ll` represent the normal line width
177 - The two digits number `ff` represent the filled area width.
178 - The sign of "ffll" allows to flip the filled area from one side of the line to the other.
179 
180 The current fill area attributes are used to draw the hatched zone.
181 
182 Begin_Macro(source)
183 ../../../tutorials/graphs/exclusiongraph.C
184 End_Macro
185 
186 ### <a name="GP03"></a> Graphs with error bars
187 Three classes are available to handle graphs with error bars:
188 `TGraphErrors`, `TGraphAsymmErrors` and `TGraphBentErrors`.
189 The following drawing options are specific to graphs with error bars:
190 
191 | Option | Description |
192 |----------|-------------------------------------------------------------------|
193 | "Z" | Do not draw small horizontal and vertical lines the end of the error bars. Without "Z", the default is to draw these. |
194 | ">" | 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. |
195 | \"\|>\" | 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. |
196 | "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.) |
197 | \"\|\|\" | 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. |
198 | "[]" | 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. |
199 | "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). |
200 | "2" | Error rectangles are drawn. |
201 | "3" | A filled area is drawn through the end points of the vertical error bars. |
202 | "4" | A smoothed filled area is drawn through the end points of the vertical error bars. |
203 | "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. |
204 
205 
206 `gStyle->SetErrorX(dx)` controls the size of the error along x.
207 `dx = 0` removes the error along x.
208 
209 `gStyle->SetEndErrorSize(np)` controls the size of the lines
210 at the end of the error bars (when option 1 is used).
211 By default `np=1`. (np represents the number of pixels).
212 
213 #### <a name="GP03a"></a> TGraphErrors
214 
215 A `TGraphErrors` is a `TGraph` with error bars. The errors are
216 defined along X and Y and are symmetric: The left and right errors are the same
217 along X and the bottom and up errors are the same along Y.
218 
219 Begin_Macro(source)
220 {
221  TCanvas *c4 = new TCanvas("c4","c4",200,10,600,400);
222  double x[] = {0, 1, 2, 3, 4};
223  double y[] = {0, 2, 4, 1, 3};
224  double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
225  double ey[] = {1, 0.5, 1, 0.5, 1};
226  TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
227  ge->Draw("ap");
228  return c4;
229 }
230 End_Macro
231 
232 The option "0" shows the error bars for data points outside range.
233 
234 Begin_Macro(source)
235 {
236  TCanvas *c48 = new TCanvas("c48","c48",200,10,600,400);
237  float x[] = {1,2,3};
238  float err_x[] = {0,0,0};
239  float err_y[] = {5,5,5};
240  float y[] = {1,4,9};
241  TGraphErrors tg(3,x,y,err_x,err_y);
242  c48->Divide(2,1);
243  c48->cd(1); gPad->DrawFrame(0,0,4,8); tg.Draw("PC");
244  c48->cd(2); gPad->DrawFrame(0,0,4,8); tg.Draw("0PC");
245  return c48;
246 }
247 End_Macro
248 
249 The option "3" shows the errors as a band.
250 
251 Begin_Macro(source)
252 {
253  TCanvas *c41 = new TCanvas("c41","c41",200,10,600,400);
254  double x[] = {0, 1, 2, 3, 4};
255  double y[] = {0, 2, 4, 1, 3};
256  double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
257  double ey[] = {1, 0.5, 1, 0.5, 1};
258  TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
259  ge->SetFillColor(4);
260  ge->SetFillStyle(3010);
261  ge->Draw("a3");
262  return c41;
263 }
264 End_Macro
265 
266 The option "4" is similar to the option "3" except that the band
267 is smoothed. As the following picture shows, this option should be
268 used carefully because the smoothing algorithm may show some (huge)
269 "bouncing" effects. In some cases it looks nicer than option "3"
270 (because it is smooth) but it can be misleading.
271 
272 Begin_Macro(source)
273 {
274  TCanvas *c42 = new TCanvas("c42","c42",200,10,600,400);
275  double x[] = {0, 1, 2, 3, 4};
276  double y[] = {0, 2, 4, 1, 3};
277  double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
278  double ey[] = {1, 0.5, 1, 0.5, 1};
279  TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
280  ge->SetFillColor(6);
281  ge->SetFillStyle(3005);
282  ge->Draw("a4");
283  return c42;
284 }
285 End_Macro
286 
287 The following example shows how the option "[]" can be used to superimpose
288 systematic errors on top of a graph with statistical errors.
289 
290 Begin_Macro(source)
291 {
292  TCanvas *c43 = new TCanvas("c43","c43",200,10,600,400);
293  c43->DrawFrame(0., -0.5, 6., 2);
294 
295  double x[5] = {1, 2, 3, 4, 5};
296  double zero[5] = {0, 0, 0, 0, 0};
297 
298  // data set (1) with stat and sys errors
299  double py1[5] = {1.2, 1.15, 1.19, 0.9, 1.4};
300  double ey_stat1[5] = {0.2, 0.18, 0.17, 0.2, 0.4};
301  double ey_sys1[5] = {0.5, 0.71, 0.76, 0.5, 0.45};
302 
303  // data set (2) with stat and sys errors
304  double y2[5] = {0.25, 0.18, 0.29, 0.2, 0.21};
305  double ey_stat2[5] = {0.2, 0.18, 0.17, 0.2, 0.4};
306  double ey_sys2[5] = {0.63, 0.19, 0.7, 0.2, 0.7};
307 
308  // Now draw data set (1)
309 
310  // We first have to draw it only with the stat errors
311  TGraphErrors *graph1 = new TGraphErrors(5, x, py1, zero, ey_stat1);
312  graph1->SetMarkerStyle(20);
313  graph1->Draw("P");
314 
315  // Now we have to somehow depict the sys errors
316 
317  TGraphErrors *graph1_sys = new TGraphErrors(5, x, py1, zero, ey_sys1);
318  graph1_sys->Draw("[]");
319 
320  // Now draw data set (2)
321 
322  // We first have to draw it only with the stat errors
323  TGraphErrors *graph2 = new TGraphErrors(5, x, y2, zero, ey_stat2);
324  graph2->SetMarkerStyle(24);
325  graph2->Draw("P");
326 
327  // Now we have to somehow depict the sys errors
328 
329  TGraphErrors *graph2_sys = new TGraphErrors(5, x, y2, zero, ey_sys2);
330  graph2_sys->Draw("[]");
331  return c43;
332 }
333 End_Macro
334 
335 #### <a name="GP03b"></a> TGraphAsymmErrors
336 A `TGraphAsymmErrors` is like a `TGraphErrors` but the errors
337 defined along X and Y are not symmetric: The left and right errors are
338 different along X and the bottom and up errors are different along Y.
339 
340 Begin_Macro(source)
341 {
342  TCanvas *c44 = new TCanvas("c44","c44",200,10,600,400);
343  double ax[] = {0, 1, 2, 3, 4};
344  double ay[] = {0, 2, 4, 1, 3};
345  double aexl[] = {0.1, 0.2, 0.3, 0.4, 0.5};
346  double aexh[] = {0.5, 0.4, 0.3, 0.2, 0.1};
347  double aeyl[] = {1, 0.5, 1, 0.5, 1};
348  double aeyh[] = {0.5, 1, 0.5, 1, 0.5};
349  TGraphAsymmErrors* gae = new TGraphAsymmErrors(5, ax, ay, aexl, aexh, aeyl, aeyh);
350  gae->SetFillColor(2);
351  gae->SetFillStyle(3001);
352  gae->Draw("a2");
353  gae->Draw("p");
354  return c44;
355 }
356 End_Macro
357 
358 
359 #### <a name="GP03c"></a> TGraphBentErrors
360 A `TGraphBentErrors` is like a `TGraphAsymmErrors`.
361 An extra parameter allows to bend the error bars to better see them
362 when several graphs are drawn on the same plot.
363 
364 Begin_Macro(source)
365 {
366  TCanvas *c45 = new TCanvas("c45","c45",200,10,600,400);
367  const Int_t n = 10;
368  Double_t x[n] = {-0.22, 0.05, 0.25, 0.35, 0.5, 0.61,0.7,0.85,0.89,0.95};
369  Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
370  Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
371  Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
372  Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
373  Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};
374  Double_t exld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
375  Double_t eyld[n] = {.0,.0,.05,.0,.0,.0,.0,.0,.0,.0};
376  Double_t exhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
377  Double_t eyhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.05,.0};
378  TGraphBentErrors *gr = new TGraphBentErrors(n,x,y,exl,exh,eyl,eyh,exld,exhd,eyld,eyhd);
379  gr->SetTitle("TGraphBentErrors Example");
380  gr->SetMarkerColor(4);
381  gr->SetMarkerStyle(21);
382  gr->Draw("ALP");
383  return c45;
384 }
385 End_Macro
386 
387 
388 ### <a name="GP04"></a> TGraphPolar options
389 
390 The drawing options for the polar graphs are the following:
391 
392 | Option | Description |
393 |----------|-------------------------------------------------------------------|
394 | "O" | Polar labels are drawn orthogonally to the polargram radius. |
395 | "P" | Polymarker are drawn at each point position. |
396 | "E" | Draw error bars. |
397 | "F" | Draw fill area (closed polygon). |
398 | "A" | Force axis redrawing even if a polargram already exists. |
399 | "N" | Disable the display of the polar labels. |
400 
401 
402 Begin_Macro(source)
403 {
404  TCanvas *c46 = new TCanvas("c46","c46",500,500);
405  TGraphPolar * grP1 = new TGraphPolar();
406  grP1->SetTitle("TGraphPolar example");
407 
408  grP1->SetPoint(0, (1*TMath::Pi())/4., 0.05);
409  grP1->SetPoint(1, (2*TMath::Pi())/4., 0.10);
410  grP1->SetPoint(2, (3*TMath::Pi())/4., 0.15);
411  grP1->SetPoint(3, (4*TMath::Pi())/4., 0.20);
412  grP1->SetPoint(4, (5*TMath::Pi())/4., 0.25);
413  grP1->SetPoint(5, (6*TMath::Pi())/4., 0.30);
414  grP1->SetPoint(6, (7*TMath::Pi())/4., 0.35);
415  grP1->SetPoint(7, (8*TMath::Pi())/4., 0.40);
416 
417  grP1->SetMarkerStyle(20);
418  grP1->SetMarkerSize(1.);
419  grP1->SetMarkerColor(4);
420  grP1->SetLineColor(4);
421  grP1->Draw("ALP");
422 
423  // Update, otherwise GetPolargram returns 0
424  c46->Update();
425  grP1->GetPolargram()->SetToRadian();
426 
427  return c46;
428 }
429 End_Macro
430 
431  */
432 
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Default constructor
436 
438 {
439 }
440 
441 
442 ////////////////////////////////////////////////////////////////////////////////
443 /// Destructor.
444 
446 {
447 }
448 
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Compute the logarithm of global variables `gxwork` and `gywork`
452 /// according to the value of Options and put the results in the global
453 /// variables `gxworkl` and `gyworkl`.
454 ///
455 /// npoints : Number of points in gxwork and in gywork.
456 ///
457 /// - opt = 1 ComputeLogs is called from PaintGrapHist
458 /// - opt = 0 ComputeLogs is called from PaintGraph
459 
460 void TGraphPainter::ComputeLogs(Int_t npoints, Int_t opt)
461 {
462 
463 
464  Int_t i;
465  memcpy(gxworkl,gxwork,npoints*8);
466  memcpy(gyworkl,gywork,npoints*8);
467  if (gPad->GetLogx()) {
468  for (i=0;i<npoints;i++) {
469  if (gxworkl[i] > 0) gxworkl[i] = TMath::Log10(gxworkl[i]);
470  else gxworkl[i] = gPad->GetX1();
471  }
472  }
473  if (!opt && gPad->GetLogy()) {
474  for (i=0;i<npoints;i++) {
475  if (gyworkl[i] > 0) gyworkl[i] = TMath::Log10(gyworkl[i]);
476  else gyworkl[i] = gPad->GetY1();
477  }
478  }
479 }
480 
481 
482 ////////////////////////////////////////////////////////////////////////////////
483 /// Compute distance from point px,py to a graph.
484 ///
485 /// Compute the closest distance of approach from point px,py to this line.
486 /// The distance is computed in pixels units.
487 
489 {
490 
491  // Are we on the axis?
492  Int_t distance;
493  if (theGraph->GetHistogram()) {
494  distance = theGraph->GetHistogram()->DistancetoPrimitive(px,py);
495  if (distance <= 5) return distance;
496  }
497 
498  // Somewhere on the graph points?
499  const Int_t big = 9999;
500  const Int_t kMaxDiff = 10;
501  Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
502  Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
503  Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
504  Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
505 
506  // return if point is not in the graph area
507  if (px <= puxmin) return big;
508  if (py >= puymin) return big;
509  if (px >= puxmax) return big;
510  if (py <= puymax) return big;
511 
512  // check if point is near one of the graph points
513  Int_t i, pxp, pyp, d;
514  distance = big;
515 
516  Int_t theNpoints = theGraph->GetN();
517  Double_t *theX, *theY;
518  if (theGraph->InheritsFrom(TGraphPolar::Class())) {
519  TGraphPolar *theGraphPolar = (TGraphPolar*) theGraph;
520  theX = theGraphPolar->GetXpol();
521  theY = theGraphPolar->GetYpol();
522  } else {
523  theX = theGraph->GetX();
524  theY = theGraph->GetY();
525  }
526 
527  for (i=0;i<theNpoints;i++) {
528  pxp = gPad->XtoAbsPixel(gPad->XtoPad(theX[i]));
529  pyp = gPad->YtoAbsPixel(gPad->YtoPad(theY[i]));
530  d = TMath::Abs(pxp-px) + TMath::Abs(pyp-py);
531  if (d < distance) distance = d;
532  }
533  if (distance < kMaxDiff) return distance;
534 
535  for (i=0;i<theNpoints-1;i++) {
536  TAttLine l;
537  d = l.DistancetoLine(px, py, gPad->XtoPad(theX[i]), gPad->YtoPad(theY[i]), gPad->XtoPad(theX[i+1]), gPad->YtoPad(theY[i+1]));
538  if (d < distance) distance = d;
539  }
540 
541  // If graph has been drawn with the fill area option, check if we are inside
542  TString drawOption = theGraph->GetDrawOption();
543  drawOption.ToLower();
544  if (drawOption.Contains("f")) {
545  Double_t xp = gPad->AbsPixeltoX(px); xp = gPad->PadtoX(xp);
546  Double_t yp = gPad->AbsPixeltoY(py); yp = gPad->PadtoY(yp);
547  if (TMath::IsInside(xp,yp,theNpoints,theX,theY) != 0) distance = 1;
548  }
549 
550  // Loop on the list of associated functions and user objects
551  TObject *f;
552  TList *functions = theGraph->GetListOfFunctions();
553  TIter next(functions);
554  while ((f = (TObject*) next())) {
555  Int_t dist;
556  if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
557  else dist = f->DistancetoPrimitive(px,py);
558  if (dist < kMaxDiff) {
559  gPad->SetSelected(f);
560  return 0; //must be o and not dist in case of TMultiGraph
561  }
562  }
563 
564  return distance;
565 }
566 
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Display a panel with all histogram drawing options.
570 
572 {
573 
574  if (!gPad) {
575  Error("DrawPanel", "need to draw graph first");
576  return;
577  }
579  editor->Show();
580  gROOT->ProcessLine(Form("((TCanvas*)0x%lx)->Selected((TVirtualPad*)0x%lx,(TObject*)0x%lx,1)",
581  (ULong_t)gPad->GetCanvas(), (ULong_t)gPad, (ULong_t)theGraph));
582 }
583 
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Execute action corresponding to one event.
587 ///
588 /// This member function is called when a graph is clicked with the locator.
589 ///
590 /// If the left mouse button is clicked on one of the line end points, this point
591 /// follows the cursor until button is released.
592 ///
593 /// If the middle mouse button clicked, the line is moved parallel to itself
594 /// until the button is released.
595 
596 void TGraphPainter::ExecuteEventHelper(TGraph *theGraph, Int_t event, Int_t px, Int_t py)
597 {
598 
599  if (!gPad) return;
600 
601  Int_t i, d;
602  Double_t xmin, xmax, ymin, ymax, dx, dy, dxr, dyr;
603  const Int_t kMaxDiff = 10;//3;
604  static Bool_t middle, badcase;
605  static Int_t ipoint, pxp, pyp;
606  static Int_t px1,px2,py1,py2;
607  static Int_t pxold, pyold, px1old, py1old, px2old, py2old;
608  static Int_t dpx, dpy;
609  static Int_t *x=0, *y=0;
610  Bool_t opaque = gPad->OpaqueMoving();
611 
612  if (!theGraph->IsEditable() || theGraph->InheritsFrom(TGraphPolar::Class())) {
613  gPad->SetCursor(kHand);
614  return;
615  }
616  if (!gPad->IsEditable()) return;
617  Int_t theNpoints = theGraph->GetN();
618  Double_t *theX = theGraph->GetX();
619  Double_t *theY = theGraph->GetY();
620 
621  switch (event) {
622 
623  case kButton1Down:
624  badcase = kFALSE;
625  gVirtualX->SetLineColor(-1);
626  theGraph->TAttLine::Modify(); //Change line attributes only if necessary
627  px1 = gPad->XtoAbsPixel(gPad->GetX1());
628  py1 = gPad->YtoAbsPixel(gPad->GetY1());
629  px2 = gPad->XtoAbsPixel(gPad->GetX2());
630  py2 = gPad->YtoAbsPixel(gPad->GetY2());
631  ipoint = -1;
632 
633 
634  if (x || y) break;
635  x = new Int_t[theNpoints+1];
636  y = new Int_t[theNpoints+1];
637  for (i=0;i<theNpoints;i++) {
638  pxp = gPad->XtoAbsPixel(gPad->XtoPad(theX[i]));
639  pyp = gPad->YtoAbsPixel(gPad->YtoPad(theY[i]));
640  if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
641  pyp < -kMaxPixel || pyp >= kMaxPixel) {
642  badcase = kTRUE;
643  continue;
644  }
645  if (!opaque) {
646  gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4);
647  gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4);
648  gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4);
649  gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4);
650  }
651  x[i] = pxp;
652  y[i] = pyp;
653  d = TMath::Abs(pxp-px) + TMath::Abs(pyp-py);
654  if (d < kMaxDiff) ipoint =i;
655  }
656  dpx = 0;
657  dpy = 0;
658  pxold = px;
659  pyold = py;
660  if (ipoint < 0) return;
661  if (ipoint == 0) {
662  px1old = 0;
663  py1old = 0;
664  px2old = gPad->XtoAbsPixel(theX[1]);
665  py2old = gPad->YtoAbsPixel(theY[1]);
666  } else if (ipoint == theNpoints-1) {
667  px1old = gPad->XtoAbsPixel(gPad->XtoPad(theX[theNpoints-2]));
668  py1old = gPad->YtoAbsPixel(gPad->YtoPad(theY[theNpoints-2]));
669  px2old = 0;
670  py2old = 0;
671  } else {
672  px1old = gPad->XtoAbsPixel(gPad->XtoPad(theX[ipoint-1]));
673  py1old = gPad->YtoAbsPixel(gPad->YtoPad(theY[ipoint-1]));
674  px2old = gPad->XtoAbsPixel(gPad->XtoPad(theX[ipoint+1]));
675  py2old = gPad->YtoAbsPixel(gPad->YtoPad(theY[ipoint+1]));
676  }
677  pxold = gPad->XtoAbsPixel(gPad->XtoPad(theX[ipoint]));
678  pyold = gPad->YtoAbsPixel(gPad->YtoPad(theY[ipoint]));
679 
680  break;
681 
682 
683  case kMouseMotion:
684 
685  middle = kTRUE;
686  for (i=0;i<theNpoints;i++) {
687  pxp = gPad->XtoAbsPixel(gPad->XtoPad(theX[i]));
688  pyp = gPad->YtoAbsPixel(gPad->YtoPad(theY[i]));
689  d = TMath::Abs(pxp-px) + TMath::Abs(pyp-py);
690  if (d < kMaxDiff) middle = kFALSE;
691  }
692 
693 
694  // check if point is close to an axis
695  if (middle) gPad->SetCursor(kMove);
696  else gPad->SetCursor(kHand);
697  break;
698 
699  case kButton1Motion:
700  if (!opaque) {
701  if (middle) {
702  for(i=0;i<theNpoints-1;i++) {
703  gVirtualX->DrawLine(x[i]+dpx, y[i]+dpy, x[i+1]+dpx, y[i+1]+dpy);
704  pxp = x[i]+dpx;
705  pyp = y[i]+dpy;
706  if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
707  pyp < -kMaxPixel || pyp >= kMaxPixel) continue;
708  gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4);
709  gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4);
710  gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4);
711  gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4);
712  }
713  pxp = x[theNpoints-1]+dpx;
714  pyp = y[theNpoints-1]+dpy;
715  gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4);
716  gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4);
717  gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4);
718  gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4);
719  dpx += px - pxold;
720  dpy += py - pyold;
721  pxold = px;
722  pyold = py;
723  for(i=0;i<theNpoints-1;i++) {
724  gVirtualX->DrawLine(x[i]+dpx, y[i]+dpy, x[i+1]+dpx, y[i+1]+dpy);
725  pxp = x[i]+dpx;
726  pyp = y[i]+dpy;
727  if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
728  pyp < -kMaxPixel || pyp >= kMaxPixel) continue;
729  gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4);
730  gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4);
731  gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4);
732  gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4);
733  }
734  pxp = x[theNpoints-1]+dpx;
735  pyp = y[theNpoints-1]+dpy;
736  gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4);
737  gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4);
738  gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4);
739  gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4);
740  } else {
741  if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
742  if (px2old) gVirtualX->DrawLine(pxold, pyold, px2old, py2old);
743  gVirtualX->DrawLine(pxold-4, pyold-4, pxold+4, pyold-4);
744  gVirtualX->DrawLine(pxold+4, pyold-4, pxold+4, pyold+4);
745  gVirtualX->DrawLine(pxold+4, pyold+4, pxold-4, pyold+4);
746  gVirtualX->DrawLine(pxold-4, pyold+4, pxold-4, pyold-4);
747  pxold = px;
748  pxold = TMath::Max(pxold, px1);
749  pxold = TMath::Min(pxold, px2);
750  pyold = py;
751  pyold = TMath::Max(pyold, py2);
752  pyold = TMath::Min(pyold, py1);
753  if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
754  if (px2old) gVirtualX->DrawLine(pxold, pyold, px2old, py2old);
755  gVirtualX->DrawLine(pxold-4, pyold-4, pxold+4, pyold-4);
756  gVirtualX->DrawLine(pxold+4, pyold-4, pxold+4, pyold+4);
757  gVirtualX->DrawLine(pxold+4, pyold+4, pxold-4, pyold+4);
758  gVirtualX->DrawLine(pxold-4, pyold+4, pxold-4, pyold-4);
759  }
760  } else {
761  xmin = gPad->GetUxmin();
762  xmax = gPad->GetUxmax();
763  ymin = gPad->GetUymin();
764  ymax = gPad->GetUymax();
765  dx = xmax-xmin;
766  dy = ymax-ymin;
767  dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
768  dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
769 
770  if (theGraph->GetHistogram()) {
771  // Range() could change the size of the pad pixmap and therefore should
772  // be called before the other paint routines
773  gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
774  ymin - dyr*gPad->GetBottomMargin(),
775  xmax + dxr*gPad->GetRightMargin(),
776  ymax + dyr*gPad->GetTopMargin());
777  gPad->RangeAxis(xmin, ymin, xmax, ymax);
778  }
779  if (middle) {
780  dpx += px - pxold;
781  dpy += py - pyold;
782  pxold = px;
783  pyold = py;
784  for(i=0;i<theNpoints;i++) {
785  if (badcase) continue; //do not update if big zoom and points moved
786  if (x) theX[i] = gPad->PadtoX(gPad->AbsPixeltoX(x[i]+dpx));
787  if (y) theY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i]+dpy));
788  }
789  } else {
790  pxold = px;
791  pxold = TMath::Max(pxold, px1);
792  pxold = TMath::Min(pxold, px2);
793  pyold = py;
794  pyold = TMath::Max(pyold, py2);
795  pyold = TMath::Min(pyold, py1);
796  theX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold));
797  theY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold));
798  if (theGraph->InheritsFrom("TCutG")) {
799  //make sure first and last point are the same
800  if (ipoint == 0) {
801  theX[theNpoints-1] = theX[0];
802  theY[theNpoints-1] = theY[0];
803  }
804  if (ipoint == theNpoints-1) {
805  theX[0] = theX[theNpoints-1];
806  theY[0] = theY[theNpoints-1];
807  }
808  }
809  }
810  badcase = kFALSE;
811  gPad->Modified(kTRUE);
812  //gPad->Update();
813  }
814  break;
815 
816  case kButton1Up:
817 
818  if (gROOT->IsEscaped()) {
819  gROOT->SetEscape(kFALSE);
820  delete [] x; x = 0;
821  delete [] y; y = 0;
822  break;
823  }
824 
825  // Compute x,y range
826  xmin = gPad->GetUxmin();
827  xmax = gPad->GetUxmax();
828  ymin = gPad->GetUymin();
829  ymax = gPad->GetUymax();
830  dx = xmax-xmin;
831  dy = ymax-ymin;
832  dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
833  dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
834 
835  if (theGraph->GetHistogram()) {
836  // Range() could change the size of the pad pixmap and therefore should
837  // be called before the other paint routines
838  gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
839  ymin - dyr*gPad->GetBottomMargin(),
840  xmax + dxr*gPad->GetRightMargin(),
841  ymax + dyr*gPad->GetTopMargin());
842  gPad->RangeAxis(xmin, ymin, xmax, ymax);
843  }
844  if (middle) {
845  for(i=0;i<theNpoints;i++) {
846  if (badcase) continue; //do not update if big zoom and points moved
847  if (x) theX[i] = gPad->PadtoX(gPad->AbsPixeltoX(x[i]+dpx));
848  if (y) theY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i]+dpy));
849  }
850  } else {
851  theX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold));
852  theY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold));
853  if (theGraph->InheritsFrom("TCutG")) {
854  //make sure first and last point are the same
855  if (ipoint == 0) {
856  theX[theNpoints-1] = theX[0];
857  theY[theNpoints-1] = theY[0];
858  }
859  if (ipoint == theNpoints-1) {
860  theX[0] = theX[theNpoints-1];
861  theY[0] = theY[theNpoints-1];
862  }
863  }
864  }
865  badcase = kFALSE;
866  delete [] x; x = 0;
867  delete [] y; y = 0;
868  gPad->Modified(kTRUE);
869  gVirtualX->SetLineColor(-1);
870  }
871 }
872 
873 
874 ////////////////////////////////////////////////////////////////////////////////
875 
876 char *TGraphPainter::GetObjectInfoHelper(TGraph * /*theGraph*/, Int_t /*px*/, Int_t /*py*/) const
877 {
878  return (char*)"";
879 }
880 
881 
882 ////////////////////////////////////////////////////////////////////////////////
883 /// Paint a any kind of TGraph
884 
885 void TGraphPainter::PaintHelper(TGraph *theGraph, Option_t *option)
886 {
887 
888  if (theGraph) {
890  if (theGraph->InheritsFrom(TGraphBentErrors::Class())) {
891  PaintGraphBentErrors(theGraph,option);
892  } else if (theGraph->InheritsFrom(TGraphQQ::Class())) {
893  PaintGraphQQ(theGraph,option);
894  } else if (theGraph->InheritsFrom(TGraphAsymmErrors::Class())) {
895  PaintGraphAsymmErrors(theGraph,option);
896  } else if (theGraph->InheritsFrom(TGraphErrors::Class())) {
897  if (theGraph->InheritsFrom(TGraphPolar::Class())) {
898  PaintGraphPolar(theGraph,option);
899  } else {
900  PaintGraphErrors(theGraph,option);
901  }
902  } else {
903  PaintGraphSimple(theGraph,option);
904  }
905  }
906 }
907 
908 
909 ////////////////////////////////////////////////////////////////////////////////
910 /// [Control function to draw a graph.]($GP01)
911 
912 void TGraphPainter::PaintGraph(TGraph *theGraph, Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
913 {
914 
915  if (theGraph->InheritsFrom("TGraphPolar"))
916  gPad->PushSelectableObject(theGraph);
917 
918  Int_t optionLine , optionAxis , optionCurve , optionStar , optionMark;
919  Int_t optionBar , optionR , optionOne , optionE;
920  Int_t optionFill , optionZ , optionCurveFill, optionIAxis;
921  Int_t i, npt, nloop;
922  Int_t drawtype=0;
923  Double_t xlow, xhigh, ylow, yhigh;
924  Double_t barxmin, barxmax, barymin, barymax;
925  Double_t uxmin, uxmax;
926  Double_t x1, xn, y1, yn;
927  Double_t dbar, bdelta;
928  Int_t theNpoints = theGraph->GetN();
929 
930  if (npoints <= 0) {
931  Error("PaintGraph", "illegal number of points (%d)", npoints);
932  return;
933  }
934  TString opt = chopt;
935  opt.ToUpper();
936  opt.ReplaceAll("SAME","");
937 
938  if (opt.Contains("L")) optionLine = 1; else optionLine = 0;
939  if (opt.Contains("A")) optionAxis = 1; else optionAxis = 0;
940  if (opt.Contains("C")) optionCurve = 1; else optionCurve = 0;
941  if (opt.Contains("*")) optionStar = 1; else optionStar = 0;
942  if (opt.Contains("P")) optionMark = 1; else optionMark = 0;
943  if (opt.Contains("B")) optionBar = 1; else optionBar = 0;
944  if (opt.Contains("R")) optionR = 1; else optionR = 0;
945  if (opt.Contains("1")) optionOne = 1; else optionOne = 0;
946  if (opt.Contains("F")) optionFill = 1; else optionFill = 0;
947  if (opt.Contains("I")) optionIAxis = 1; else optionIAxis = 0;
948  if (opt.Contains("2") || opt.Contains("3") ||
949  opt.Contains("4") || opt.Contains("5")) optionE = 1; else optionE = 0;
950  optionZ = 0;
951 
952  // If no "drawing" option is selected and if chopt<>' ' nothing is done.
953  if (optionLine+optionFill+optionCurve+optionStar+optionMark+optionBar+optionE == 0) {
954  if (!chopt[0]) optionLine=1;
955  else return;
956  }
957 
958  if (optionStar) theGraph->SetMarkerStyle(3);
959 
960  optionCurveFill = 0;
961  if (optionCurve && optionFill) {
962  optionCurveFill = 1;
963  optionFill = 0;
964  }
965 
966  // Draw the Axis.
967  Double_t rwxmin,rwxmax, rwymin, rwymax, maximum, minimum, dx, dy;
968  if (optionAxis) {
969  if (theGraph->GetHistogram()) {
970  rwxmin = gPad->GetUxmin();
971  rwxmax = gPad->GetUxmax();
972  rwymin = gPad->GetUymin();
973  rwymax = gPad->GetUymax();
974  minimum = theGraph->GetHistogram()->GetMinimumStored();
975  maximum = theGraph->GetHistogram()->GetMaximumStored();
976  if (minimum == -1111) { //this can happen after unzooming
977  minimum = theGraph->GetHistogram()->GetYaxis()->GetXmin();
978  theGraph->GetHistogram()->SetMinimum(minimum);
979  }
980  if (maximum == -1111) {
981  maximum = theGraph->GetHistogram()->GetYaxis()->GetXmax();
982  theGraph->GetHistogram()->SetMaximum(maximum);
983  }
984  uxmin = gPad->PadtoX(rwxmin);
985  uxmax = gPad->PadtoX(rwxmax);
986  } else {
987 
988  theGraph->ComputeRange(rwxmin, rwymin, rwxmax, rwymax); //this is redefined in TGraphErrors
989 
990  if (rwxmin == rwxmax) rwxmax += 1.;
991  if (rwymin == rwymax) rwymax += 1.;
992  dx = 0.1*(rwxmax-rwxmin);
993  dy = 0.1*(rwymax-rwymin);
994  uxmin = rwxmin - dx;
995  uxmax = rwxmax + dx;
996  minimum = rwymin - dy;
997  maximum = rwymax + dy;
998  }
999  if (theGraph->GetMinimum() != -1111) rwymin = minimum = theGraph->GetMinimum();
1000  if (theGraph->GetMaximum() != -1111) rwymax = maximum = theGraph->GetMaximum();
1001  if (uxmin < 0 && rwxmin >= 0) uxmin = 0.9*rwxmin;
1002  if (uxmax > 0 && rwxmax <= 0) {
1003  if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
1004  else uxmax = 0;
1005  }
1006  if (minimum < 0 && rwymin >= 0) minimum = 0.9*rwymin;
1007  if (maximum > 0 && rwymax <= 0) {
1008  //if(gPad->GetLogy()) maximum = 1.1*rwymax;
1009  //else maximum = 0;
1010  }
1011  if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
1012  if (uxmin <= 0 && gPad->GetLogx()) {
1013  if (uxmax > 1000) uxmin = 1;
1014  else uxmin = 0.001*uxmax;
1015  }
1016  rwymin = minimum;
1017  rwymax = maximum;
1018 
1019  // Create a temporary histogram and fill each bin with the
1020  // function value.
1021  char chopth[8] = " ";
1022  if (strstr(chopt,"x+")) strncat(chopth, "x+",2);
1023  if (strstr(chopt,"y+")) strncat(chopth, "y+",2);
1024  if (optionIAxis) strncat(chopth, "A",1);
1025  if (!theGraph->GetHistogram()) {
1026  // the graph is created with at least as many bins as there are
1027  // points to permit zooming on the full range.
1028  rwxmin = uxmin;
1029  rwxmax = uxmax;
1030  npt = 100;
1031  if (theNpoints > npt) npt = theNpoints;
1032  TH1F *h = new TH1F(Form("%s_h",GetName()),GetTitle(),npt,rwxmin,rwxmax);
1033  theGraph->SetHistogram(h);
1034  if (!theGraph->GetHistogram()) return;
1035  theGraph->GetHistogram()->SetMinimum(rwymin);
1036  theGraph->GetHistogram()->SetMaximum(rwymax);
1037  theGraph->GetHistogram()->GetYaxis()->SetLimits(rwymin,rwymax);
1038  theGraph->GetHistogram()->SetBit(TH1::kNoStats);
1039  theGraph->GetHistogram()->SetDirectory(0);
1040  theGraph->GetHistogram()->Paint(chopth); // Draw histogram axis, title and grid
1041  } else {
1042  if (gPad->GetLogy()) {
1043  theGraph->GetHistogram()->SetMinimum(rwymin);
1044  theGraph->GetHistogram()->SetMaximum(rwymax);
1045  theGraph->GetHistogram()->GetYaxis()->SetLimits(rwymin,rwymax);
1046  }
1047  theGraph->GetHistogram()->Paint(chopth); // Draw histogram axis, title and grid
1048  }
1049  }
1050 
1051  // Set Clipping option
1052  gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
1053 
1054  TF1 *fit = 0;
1055  TList *functions = theGraph->GetListOfFunctions();
1056  TObject *f;
1057  if (functions) {
1058  f = (TF1*)functions->First();
1059  if (f) {
1060  if (f->InheritsFrom(TF1::Class())) fit = (TF1*)f;
1061  }
1062  TIter next(functions);
1063  while ((f = (TObject*) next())) {
1064  if (f->InheritsFrom(TF1::Class())) {
1065  fit = (TF1*)f;
1066  break;
1067  }
1068  }
1069  }
1070  if (fit) PaintStats(theGraph, fit);
1071 
1072  rwxmin = gPad->GetUxmin();
1073  rwxmax = gPad->GetUxmax();
1074  rwymin = gPad->GetUymin();
1075  rwymax = gPad->GetUymax();
1076  uxmin = gPad->PadtoX(rwxmin);
1077  uxmax = gPad->PadtoX(rwxmax);
1078  if (theGraph->GetHistogram() && !theGraph->InheritsFrom("TGraphPolar")) {
1079  maximum = theGraph->GetHistogram()->GetMaximum();
1080  minimum = theGraph->GetHistogram()->GetMinimum();
1081  } else {
1082  maximum = gPad->PadtoY(rwymax);
1083  minimum = gPad->PadtoY(rwymin);
1084  }
1085 
1086  // Set attributes
1087  theGraph->TAttLine::Modify();
1088  theGraph->TAttFill::Modify();
1089  theGraph->TAttMarker::Modify();
1090 
1091  // Draw the graph with a polyline or a fill area
1092  gxwork = new Double_t[2*npoints+10];
1093  gywork = new Double_t[2*npoints+10];
1094  gxworkl = new Double_t[2*npoints+10];
1095  gyworkl = new Double_t[2*npoints+10];
1096 
1097  if (optionLine || optionFill) {
1098  x1 = x[0];
1099  xn = x[npoints-1];
1100  y1 = y[0];
1101  yn = y[npoints-1];
1102  nloop = npoints;
1103  if (optionFill && (xn != x1 || yn != y1)) nloop++;
1104  npt = 0;
1105  for (i=1;i<=nloop;i++) {
1106  if (i > npoints) {
1107  gxwork[npt] = gxwork[0]; gywork[npt] = gywork[0];
1108  } else {
1109  gxwork[npt] = x[i-1]; gywork[npt] = y[i-1];
1110  npt++;
1111  }
1112  if (i == nloop) {
1113  ComputeLogs(npt, optionZ);
1114  Int_t bord = gStyle->GetDrawBorder();
1115  if (optionR) {
1116  if (optionFill) {
1117  gPad->PaintFillArea(npt,gyworkl,gxworkl);
1118  if (bord) gPad->PaintPolyLine(npt,gyworkl,gxworkl);
1119  } else {
1120  if (TMath::Abs(theGraph->GetLineWidth())>99) PaintPolyLineHatches(theGraph, npt, gyworkl, gxworkl);
1121  gPad->PaintPolyLine(npt,gyworkl,gxworkl);
1122  }
1123  } else {
1124  if (optionFill) {
1125  gPad->PaintFillArea(npt,gxworkl,gyworkl);
1126  if (bord) gPad->PaintPolyLine(npt,gxworkl,gyworkl);
1127  } else {
1128  if (TMath::Abs(theGraph->GetLineWidth())>99) PaintPolyLineHatches(theGraph, npt, gxworkl, gyworkl);
1129  gPad->PaintPolyLine(npt,gxworkl,gyworkl);
1130  }
1131  }
1132  gxwork[0] = gxwork[npt-1]; gywork[0] = gywork[npt-1];
1133  npt = 1;
1134  }
1135  }
1136  }
1137 
1138  // Draw the graph with a smooth Curve. Smoothing via Smooth
1139  if (optionCurve) {
1140  x1 = x[0];
1141  xn = x[npoints-1];
1142  y1 = y[0];
1143  yn = y[npoints-1];
1144  drawtype = 1;
1145  nloop = npoints;
1146  if (optionCurveFill) {
1147  drawtype += 1000;
1148  if (xn != x1 || yn != y1) nloop++;
1149  }
1150  if (!optionR) {
1151  npt = 0;
1152  for (i=1;i<=nloop;i++) {
1153  if (i > npoints) {
1154  gxwork[npt] = gxwork[0]; gywork[npt] = gywork[0];
1155  } else {
1156  gxwork[npt] = x[i-1]; gywork[npt] = y[i-1];
1157  npt++;
1158  }
1159  ComputeLogs(npt, optionZ);
1160  if (gyworkl[npt-1] < rwymin || gyworkl[npt-1] > rwymax) {
1161  if (npt > 2) {
1162  ComputeLogs(npt, optionZ);
1163  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1164  }
1165  gxwork[0] = gxwork[npt-1]; gywork[0] = gywork[npt-1];
1166  npt=1;
1167  continue;
1168  }
1169  }
1170  if (npt > 1) {
1171  ComputeLogs(npt, optionZ);
1172  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1173  }
1174  } else {
1175  drawtype += 10;
1176  npt = 0;
1177  for (i=1;i<=nloop;i++) {
1178  if (i > npoints) {
1179  gxwork[npt] = gxwork[0]; gywork[npt] = gywork[0];
1180  } else {
1181  if (y[i-1] < minimum || y[i-1] > maximum) continue;
1182  if (x[i-1] < uxmin || x[i-1] > uxmax) continue;
1183  gxwork[npt] = x[i-1]; gywork[npt] = y[i-1];
1184  npt++;
1185  }
1186  ComputeLogs(npt, optionZ);
1187  if (gxworkl[npt-1] < rwxmin || gxworkl[npt-1] > rwxmax) {
1188  if (npt > 2) {
1189  ComputeLogs(npt, optionZ);
1190  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1191  }
1192  gxwork[0] = gxwork[npt-1]; gywork[0] = gywork[npt-1];
1193  npt=1;
1194  continue;
1195  }
1196  }
1197  if (npt > 1) {
1198  ComputeLogs(npt, optionZ);
1199  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1200  }
1201  }
1202  }
1203 
1204  // Draw the graph with a '*' on every points
1205  if (optionStar) {
1206  theGraph->SetMarkerStyle(3);
1207  npt = 0;
1208  for (i=1;i<=npoints;i++) {
1209  gxwork[npt] = x[i-1]; gywork[npt] = y[i-1];
1210  npt++;
1211  if (i == npoints) {
1212  ComputeLogs(npt, optionZ);
1213  if (optionR) gPad->PaintPolyMarker(npt,gyworkl,gxworkl);
1214  else gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
1215  npt = 0;
1216  }
1217  }
1218  }
1219 
1220  // Draw the graph with the current polymarker on every points
1221  if (optionMark) {
1222  npt = 0;
1223  for (i=1;i<=npoints;i++) {
1224  gxwork[npt] = x[i-1]; gywork[npt] = y[i-1];
1225  npt++;
1226  if (i == npoints) {
1227  ComputeLogs(npt, optionZ);
1228  if (optionR) gPad->PaintPolyMarker(npt,gyworkl,gxworkl);
1229  else gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
1230  npt = 0;
1231  }
1232  }
1233  }
1234 
1235  // Draw the graph as a bar chart
1236  if (optionBar) {
1237  if (!optionR) {
1238  barxmin = x[0];
1239  barxmax = x[0];
1240  for (i=1;i<npoints;i++) {
1241  if (x[i] < barxmin) barxmin = x[i];
1242  if (x[i] > barxmax) barxmax = x[i];
1243  }
1244  bdelta = (barxmax-barxmin)/Double_t(npoints);
1245  } else {
1246  barymin = y[0];
1247  barymax = y[0];
1248  for (i=1;i<npoints;i++) {
1249  if (y[i] < barymin) barymin = y[i];
1250  if (y[i] > barymax) barymax = y[i];
1251  }
1252  bdelta = (barymax-barymin)/Double_t(npoints);
1253  }
1254  dbar = 0.5*bdelta*gStyle->GetBarWidth();
1255  if (!optionR) {
1256  for (i=1;i<=npoints;i++) {
1257  xlow = x[i-1] - dbar;
1258  xhigh = x[i-1] + dbar;
1259  yhigh = y[i-1];
1260  if (xlow < uxmin) xlow = uxmin;
1261  if (xhigh > uxmax) xhigh = uxmax;
1262  if (!optionOne) ylow = TMath::Max((Double_t)0,gPad->GetUymin());
1263  else ylow = gPad->GetUymin();
1264  gxwork[0] = xlow;
1265  gywork[0] = ylow;
1266  gxwork[1] = xhigh;
1267  gywork[1] = yhigh;
1268  ComputeLogs(2, optionZ);
1269  if (gyworkl[0] < gPad->GetUymin()) gyworkl[0] = gPad->GetUymin();
1270  if (gyworkl[1] < gPad->GetUymin()) continue;
1271  if (gyworkl[1] > gPad->GetUymax()) gyworkl[1] = gPad->GetUymax();
1272  if (gyworkl[0] > gPad->GetUymax()) continue;
1273 
1274  gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
1275  }
1276  } else {
1277  for (i=1;i<=npoints;i++) {
1278  xhigh = x[i-1];
1279  ylow = y[i-1] - dbar;
1280  yhigh = y[i-1] + dbar;
1281  xlow = TMath::Max((Double_t)0, gPad->GetUxmin());
1282  gxwork[0] = xlow;
1283  gywork[0] = ylow;
1284  gxwork[1] = xhigh;
1285  gywork[1] = yhigh;
1286  ComputeLogs(2, optionZ);
1287  gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
1288  }
1289  }
1290  }
1291  gPad->ResetBit(TGraph::kClipFrame);
1292 
1293  delete [] gxwork;
1294  delete [] gywork;
1295  delete [] gxworkl;
1296  delete [] gyworkl;
1297 }
1298 
1299 
1300 ////////////////////////////////////////////////////////////////////////////////
1301 /// This is a service method used by `THistPainter`
1302 /// to paint 1D histograms. It is not used to paint TGraph.
1303 ///
1304 /// Input parameters:
1305 ///
1306 /// - npoints : Number of points in X or in Y.
1307 /// - x[npoints] or x[0] : x coordinates or (xmin,xmax).
1308 /// - y[npoints] or y[0] : y coordinates or (ymin,ymax).
1309 /// - chopt : Option.
1310 ///
1311 /// The aspect of the histogram is done according to the value of the chopt.
1312 ///
1313 /// | Option | Description |
1314 /// |--------|-----------------------------------------------------------------|
1315 /// |"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 2 values for Y (y[0]=YMIN and y[1]=YMAX) or N values for X, one for each channel. Otherwise the user must give, N values for Y, one for each channel or 2 values for X (x[0]=XMIN and x[1]=XMAX) |
1316 /// |"L" | A simple polyline beetwen every points is drawn.|
1317 /// |"H" | An Histogram with equidistant bins is drawn as a polyline.|
1318 /// |"F" | An histogram with equidistant bins is drawn as a fill area. Contour is not drawn unless chopt='H' is also selected..|
1319 /// |"N" | Non equidistant bins (default is equidistant). If N is the number of channels array X and Y must be dimensionned as follow: If option R is not selected (default) then the user must give (N+1) values for X (limits of channels) or N values for Y, one for each channel. Otherwise the user must give (N+1) values for Y (limits of channels). or N values for X, one for each channel |
1320 /// |"F1" | Idem as 'F' except that fill area base line is the minimum of the pad instead of Y=0.|
1321 /// |"F2" | Draw a Fill area polyline connecting the center of bins|
1322 /// |"C" | A smooth Curve is drawn.|
1323 /// |"*" | A Star is plotted at the center of each bin.|
1324 /// |"P" | Idem with the current marker.|
1325 /// |"P0" | Idem with the current marker. Empty bins also drawn.|
1326 /// |"B" | A Bar chart with equidistant bins is drawn as fill areas (Contours are drawn).|
1327 /// |"][" | "Cutoff" style. When this option is selected together with H option, the first and last vertical lines of the histogram are not drawn.|
1328 
1329 void TGraphPainter::PaintGrapHist(TGraph *theGraph, Int_t npoints, const Double_t *x,
1330  const Double_t *y, Option_t *chopt)
1331 {
1332 
1333  const char *where = "PaintGrapHist";
1334 
1335  Int_t optionLine , optionAxis , optionCurve, optionStar, optionMark;
1336  Int_t optionBar , optionRot , optionOne , optionOff ;
1337  Int_t optionFill , optionZ;
1338  Int_t optionHist , optionBins , optionMarker;
1339  Int_t i, j, npt;
1340  Int_t drawtype=0, drawborder, drawbordersav;
1341  Double_t xlow, xhigh, ylow, yhigh;
1342  Double_t wmin, wmax;
1343  Double_t dbar, offset, wminstep;
1344  Double_t delta = 0;
1345  Double_t ylast = 0;
1346  Double_t xi, xi1, xj, xj1, yi1, yi, yj, yj1, xwmin, ywmin;
1347  Int_t first, last, nbins;
1348  Int_t fillarea;
1349 
1350  char choptaxis[10] = " ";
1351 
1352  if (npoints <= 0) {
1353  Error(where, "illegal number of points (%d)", npoints);
1354  return;
1355  }
1356  TString opt = chopt;
1357  opt.ToUpper();
1358  if (opt.Contains("H")) optionHist = 1; else optionHist = 0;
1359  if (opt.Contains("F")) optionFill = 1; else optionFill = 0;
1360  if (opt.Contains("C")) optionCurve= 1; else optionCurve= 0;
1361  if (opt.Contains("*")) optionStar = 1; else optionStar = 0;
1362  if (opt.Contains("R")) optionRot = 1; else optionRot = 0;
1363  if (opt.Contains("1")) optionOne = 1; else optionOne = 0;
1364  if (opt.Contains("B")) optionBar = 1; else optionBar = 0;
1365  if (opt.Contains("N")) optionBins = 1; else optionBins = 0;
1366  if (opt.Contains("L")) optionLine = 1; else optionLine = 0;
1367  if (opt.Contains("P")) optionMark = 1; else optionMark = 0;
1368  if (opt.Contains("A")) optionAxis = 1; else optionAxis = 0;
1369  if (opt.Contains("][")) optionOff = 1; else optionOff = 0;
1370  if (opt.Contains("P0")) optionMark = 10;
1371 
1372  Int_t optionFill2 = 0;
1373  if (opt.Contains("F") && opt.Contains("2")) {
1374  optionFill = 0; optionFill2 = 1;
1375  }
1376 
1377  // Set Clipping option
1378  Option_t *noClip;
1379  if (theGraph->TestBit(TGraph::kClipFrame)) noClip = "";
1380  else noClip = "C";
1381  gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
1382 
1383  optionZ = 1;
1384 
1385  if (optionStar) theGraph->SetMarkerStyle(3);
1386 
1387  first = 1;
1388  last = npoints;
1389  nbins = last - first + 1;
1390 
1391  // Draw the Axis with a fixed number of division: 510
1392 
1393  Double_t baroffset = gStyle->GetBarOffset();
1394  Double_t barwidth = gStyle->GetBarWidth();
1395  Double_t rwxmin = gPad->GetUxmin();
1396  Double_t rwxmax = gPad->GetUxmax();
1397  Double_t rwymin = gPad->GetUymin();
1398  Double_t rwymax = gPad->GetUymax();
1399  Double_t uxmin = gPad->PadtoX(rwxmin);
1400  Double_t uxmax = gPad->PadtoX(rwxmax);
1401  Double_t rounding = (uxmax-uxmin)*1.e-5;
1402  drawborder = gStyle->GetDrawBorder();
1403  if (optionAxis) {
1404  Int_t nx1, nx2, ndivx, ndivy, ndiv;
1405  choptaxis[0] = 0;
1406  Double_t rwmin = rwxmin;
1407  Double_t rwmax = rwxmax;
1408  ndivx = gStyle->GetNdivisions("X");
1409  ndivy = gStyle->GetNdivisions("Y");
1410  if (ndivx > 1000) {
1411  nx2 = ndivx/100;
1412  nx1 = TMath::Max(1, ndivx%100);
1413  ndivx = 100*nx2 + Int_t(Double_t(nx1)*gPad->GetAbsWNDC());
1414  }
1415  ndiv =TMath::Abs(ndivx);
1416  // coverity [Calling risky function]
1417  if (ndivx < 0) strlcat(choptaxis, "N",10);
1418  if (gPad->GetGridx()) {
1419  // coverity [Calling risky function]
1420  strlcat(choptaxis, "W",10);
1421  }
1422  if (gPad->GetLogx()) {
1423  rwmin = TMath::Power(10,rwxmin);
1424  rwmax = TMath::Power(10,rwxmax);
1425  // coverity [Calling risky function]
1426  strlcat(choptaxis, "G",10);
1427  }
1428  TGaxis *axis = new TGaxis();
1429  axis->SetLineColor(gStyle->GetAxisColor("X"));
1430  axis->SetTextColor(gStyle->GetLabelColor("X"));
1431  axis->SetTextFont(gStyle->GetLabelFont("X"));
1432  axis->SetLabelSize(gStyle->GetLabelSize("X"));
1433  axis->SetLabelOffset(gStyle->GetLabelOffset("X"));
1434  axis->SetTickSize(gStyle->GetTickLength("X"));
1435 
1436  axis->PaintAxis(rwxmin,rwymin,rwxmax,rwymin,rwmin,rwmax,ndiv,choptaxis);
1437 
1438  choptaxis[0] = 0;
1439  rwmin = rwymin;
1440  rwmax = rwymax;
1441  if (ndivy < 0) {
1442  nx2 = ndivy/100;
1443  nx1 = TMath::Max(1, ndivy%100);
1444  ndivy = 100*nx2 + Int_t(Double_t(nx1)*gPad->GetAbsHNDC());
1445  // coverity [Calling risky function]
1446  strlcat(choptaxis, "N",10);
1447  }
1448  ndiv =TMath::Abs(ndivy);
1449  if (gPad->GetGridy()) {
1450  // coverity [Calling risky function]
1451  strlcat(choptaxis, "W",10);
1452  }
1453  if (gPad->GetLogy()) {
1454  rwmin = TMath::Power(10,rwymin);
1455  rwmax = TMath::Power(10,rwymax);
1456  // coverity [Calling risky function]
1457  strlcat(choptaxis,"G",10);
1458  }
1459  axis->SetLineColor(gStyle->GetAxisColor("Y"));
1460  axis->SetTextColor(gStyle->GetLabelColor("Y"));
1461  axis->SetTextFont(gStyle->GetLabelFont("Y"));
1462  axis->SetLabelSize(gStyle->GetLabelSize("Y"));
1463  axis->SetLabelOffset(gStyle->GetLabelOffset("Y"));
1464  axis->SetTickSize(gStyle->GetTickLength("Y"));
1465 
1466  axis->PaintAxis(rwxmin,rwymin,rwxmin,rwymax,rwmin,rwmax,ndiv,choptaxis);
1467  delete axis;
1468  }
1469 
1470 
1471  // Set attributes
1472  theGraph->TAttLine::Modify();
1473  theGraph->TAttFill::Modify();
1474  theGraph->TAttMarker::Modify();
1475 
1476  // Min-Max scope
1477 
1478  if (!optionRot) {wmin = x[0]; wmax = x[1];}
1479  else {wmin = y[0]; wmax = y[1];}
1480 
1481  if (!optionBins) delta = (wmax - wmin)/ Double_t(nbins);
1482 
1483  Int_t fwidth = gPad->GetFrameLineWidth();
1484  TFrame *frame = gPad->GetFrame();
1485  if (frame) fwidth = frame->GetLineWidth();
1486  if (optionOff) fwidth = 1;
1487  Double_t dxframe = gPad->AbsPixeltoX(fwidth/2) - gPad->AbsPixeltoX(0);
1488  Double_t vxmin = gPad->PadtoX(gPad->GetUxmin() + dxframe);
1489  Double_t vxmax = gPad->PadtoX(gPad->GetUxmax() - dxframe);
1490  Double_t dyframe = -gPad->AbsPixeltoY(fwidth/2) + gPad->AbsPixeltoY(0);
1491  Double_t vymin = gPad->GetUymin() + dyframe; //y already in log scale
1492  vxmin = TMath::Max(vxmin,wmin);
1493  vxmax = TMath::Min(vxmax,wmax);
1494 
1495  // Draw the histogram with a fill area
1496 
1497  gxwork = new Double_t[2*npoints+10];
1498  gywork = new Double_t[2*npoints+10];
1499  gxworkl = new Double_t[2*npoints+10];
1500  gyworkl = new Double_t[2*npoints+10];
1501 
1502  if (optionFill && !optionCurve) {
1503  fillarea = kTRUE;
1504  if (!optionRot) {
1505  gxwork[0] = vxmin;
1506  if (!optionOne) gywork[0] = TMath::Min(TMath::Max((Double_t)0,gPad->GetUymin())
1507  ,gPad->GetUymax());
1508  else gywork[0] = gPad->GetUymin();
1509  npt = 2;
1510  for (j=first; j<=last;j++) {
1511  if (!optionBins) {
1512  gxwork[npt-1] = gxwork[npt-2];
1513  gxwork[npt] = wmin+((j-first+1)*delta);
1514  if (gxwork[npt] < gxwork[0]) gxwork[npt] = gxwork[0];
1515 
1516  } else {
1517  xj1 = x[j]; xj = x[j-1];
1518  if (xj1 < xj) {
1519  if (j != last) Error(where, "X must be in increasing order");
1520  else Error(where, "X must have N+1 values with option N");
1521  return;
1522  }
1523  gxwork[npt-1] = x[j-1]; gxwork[npt] = x[j];
1524  }
1525  gywork[npt-1] = y[j-1];
1526  gywork[npt] = y[j-1];
1527  if (gywork[npt] < vymin) {gywork[npt] = vymin; gywork[npt-1] = vymin;}
1528  if ((gxwork[npt-1] >= uxmin-rounding && gxwork[npt-1] <= uxmax+rounding) ||
1529  (gxwork[npt] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding)) npt += 2;
1530  if (j == last) {
1531  gxwork[npt-1] = gxwork[npt-2];
1532  gywork[npt-1] = gywork[0];
1533  //make sure that the fill area does not overwrite the frame
1534  //take into account the frame linewidth
1535  if (gxwork[0 ] < vxmin) {gxwork[0 ] = vxmin; gxwork[1 ] = vxmin;}
1536  if (gywork[0] < vymin) {gywork[0] = vymin; gywork[npt-1] = vymin;}
1537 
1538  //transform to log ?
1539  ComputeLogs(npt, optionZ);
1540  gPad->PaintFillArea(npt,gxworkl,gyworkl);
1541  if (drawborder) {
1542  if (!fillarea) gyworkl[0] = ylast;
1543  gPad->PaintPolyLine(npt-1,gxworkl,gyworkl,noClip);
1544  }
1545  continue;
1546  }
1547  } //endfor (j=first; j<=last;j++) {
1548  } else {
1549  gywork[0] = wmin;
1550  if (!optionOne) gxwork[0] = TMath::Max((Double_t)0,gPad->GetUxmin());
1551  else gxwork[0] = gPad->GetUxmin();
1552  npt = 2;
1553  for (j=first; j<=last;j++) {
1554  if (!optionBins) {
1555  gywork[npt-1] = gywork[npt-2];
1556  gywork[npt] = wmin+((j-first+1)*delta);
1557  } else {
1558  yj1 = y[j]; yj = y[j-1];
1559  if (yj1 < yj) {
1560  if (j != last) Error(where, "Y must be in increasing order");
1561  else Error(where, "Y must have N+1 values with option N");
1562  return;
1563  }
1564  gywork[npt-1] = y[j-1]; gywork[npt] = y[j];
1565  }
1566  gxwork[npt-1] = x[j-1]; gxwork[npt] = x[j-1];
1567  if ((gxwork[npt-1] >= uxmin-rounding && gxwork[npt-1] <= uxmax+rounding) ||
1568  (gxwork[npt] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding)) npt += 2;
1569  if (j == last) {
1570  gywork[npt-1] = gywork[npt-2];
1571  gxwork[npt-1] = gxwork[0];
1572  ComputeLogs(npt, optionZ);
1573  gPad->PaintFillArea(npt,gxworkl,gyworkl);
1574  if (drawborder) {
1575  if (!fillarea) gyworkl[0] = ylast;
1576  gPad->PaintPolyLine(npt-1,gxworkl,gyworkl,noClip);
1577  }
1578  continue;
1579  }
1580  } //endfor (j=first; j<=last;j++)
1581  }
1582  theGraph->TAttLine::Modify();
1583  theGraph->TAttFill::Modify();
1584  }
1585 
1586  // Draw a standard Histogram (default)
1587 
1588  if ((optionHist) || !chopt[0]) {
1589  if (!optionRot) {
1590  gxwork[0] = wmin;
1591  gywork[0] = gPad->GetUymin();
1592  ywmin = gywork[0];
1593  npt = 2;
1594  for (i=first; i<=last;i++) {
1595  if (!optionBins) {
1596  gxwork[npt-1] = gxwork[npt-2];
1597  gxwork[npt] = wmin+((i-first+1)*delta);
1598  } else {
1599  xi1 = x[i]; xi = x[i-1];
1600  if (xi1 < xi) {
1601  if (i != last) Error(where, "X must be in increasing order");
1602  else Error(where, "X must have N+1 values with option N");
1603  return;
1604  }
1605  gxwork[npt-1] = x[i-1]; gxwork[npt] = x[i];
1606  }
1607  gywork[npt-1] = y[i-1];
1608  gywork[npt] = y[i-1];
1609  if (gywork[npt] < vymin) {gywork[npt] = vymin; gywork[npt-1] = vymin;}
1610  if ((gxwork[npt-1] >= uxmin-rounding && gxwork[npt-1] <= uxmax+rounding) ||
1611  (gxwork[npt] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding)) npt += 2;
1612  if (i == last) {
1613  gxwork[npt-1] = gxwork[npt-2];
1614  gywork[npt-1] = gywork[0];
1615  //make sure that the fill area does not overwrite the frame
1616  //take into account the frame linewidth
1617  if (gxwork[0] < vxmin) {gxwork[0] = vxmin; gxwork[1 ] = vxmin;}
1618  if (gywork[0] < vymin) {gywork[0] = vymin; gywork[npt-1] = vymin;}
1619 
1620  ComputeLogs(npt, optionZ);
1621 
1622  // do not draw the two vertical lines on the edges
1623  Int_t nbpoints = npt-2;
1624  Int_t point1 = 1;
1625 
1626  if (optionOff) {
1627  // remove points before the low cutoff
1628  Int_t ip;
1629  for (ip=point1; ip<=nbpoints; ip++) {
1630  if (gyworkl[ip] != ywmin) {
1631  point1 = ip;
1632  break;
1633  }
1634  }
1635  // remove points after the high cutoff
1636  Int_t point2 = nbpoints;
1637  for (ip=point2; ip>=point1; ip--) {
1638  if (gyworkl[ip] != ywmin) {
1639  point2 = ip;
1640  break;
1641  }
1642  }
1643  nbpoints = point2-point1+1;
1644  } else {
1645  // if the 1st or last bin are not on the pad limits the
1646  // the two vertical lines on the edges are added.
1647  if (gxwork[0] > gPad->GetUxmin()) { nbpoints++; point1 = 0; }
1648  if (gxwork[nbpoints] < gPad->GetUxmax()) nbpoints++;
1649  }
1650 
1651  gPad->PaintPolyLine(nbpoints,&gxworkl[point1],&gyworkl[point1],noClip);
1652  continue;
1653  }
1654  } //endfor (i=first; i<=last;i++)
1655  } else {
1656  gywork[0] = wmin;
1657  gxwork[0] = TMath::Max((Double_t)0,gPad->GetUxmin());
1658  xwmin = gxwork[0];
1659  npt = 2;
1660  for (i=first; i<=last;i++) {
1661  if (!optionBins) {
1662  gywork[npt-1] = gywork[npt-2];
1663  gywork[npt] = wmin+((i-first+1)*delta);
1664  } else {
1665  yi1 = y[i]; yi = y[i-1];
1666  if (yi1 < yi) {
1667  if (i != last) Error(where, "Y must be in increasing order");
1668  else Error(where, "Y must have N+1 values with option N");
1669  return;
1670  }
1671  gywork[npt-1] = y[i-1]; gywork[npt] = y[i];
1672  }
1673  gxwork[npt-1] = x[i-1]; gxwork[npt] = x[i-1];
1674  if ((gxwork[npt-1] >= uxmin-rounding && gxwork[npt-1] <= uxmax+rounding) ||
1675  (gxwork[npt] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding)) npt += 2;
1676  if (i == last) {
1677  gywork[npt-1] = gywork[npt-2];
1678  gxwork[npt-1] = xwmin;
1679  ComputeLogs(npt, optionZ);
1680  gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
1681  continue;
1682  }
1683  } //endfor (i=first; i<=last;i++)
1684  }
1685  }
1686 
1687  // Draw the histogram with a smooth Curve.
1688  // The smoothing is done by the method Smooth()
1689 
1690  if (optionCurve) {
1691  if (!optionFill) {
1692  drawtype = 1;
1693  } else {
1694  if (!optionOne) drawtype = 2;
1695  else drawtype = 3;
1696  }
1697  if (!optionRot) {
1698  npt = 0;
1699  for (i=first; i<=last;i++) {
1700  npt++;
1701  if (!optionBins) {
1702  gxwork[npt-1] = wmin+(i-first)*delta+0.5*delta;
1703  } else {
1704  xi1 = x[i]; xi = x[i-1];
1705  if (xi1 < xi) {
1706  if (i != last) Error(where, "X must be in increasing order");
1707  else Error(where, "X must have N+1 values with option N");
1708  return;
1709  }
1710  gxwork[npt-1] = x[i-1] + 0.5*(x[i]-x[i-1]);
1711  }
1712  if (gxwork[npt-1] < uxmin || gxwork[npt-1] > uxmax) {
1713  npt--;
1714  continue;
1715  }
1716  gywork[npt-1] = y[i-1];
1717  ComputeLogs(npt, optionZ);
1718  if ((gyworkl[npt-1] < rwymin) || (gyworkl[npt-1] > rwymax)) {
1719  if (npt > 2) {
1720  ComputeLogs(npt, optionZ);
1721  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1722  }
1723  gxwork[0] = gxwork[npt-1];
1724  gywork[0] = gywork[npt-1];
1725  npt = 1;
1726  continue;
1727  }
1728  if (npt >= fgMaxPointsPerLine) {
1729  ComputeLogs(fgMaxPointsPerLine, optionZ);
1730  Smooth(theGraph, fgMaxPointsPerLine,gxworkl,gyworkl,drawtype);
1731  gxwork[0] = gxwork[npt-1];
1732  gywork[0] = gywork[npt-1];
1733  npt = 1;
1734  }
1735  } //endfor (i=first; i<=last;i++)
1736  if (npt > 1) {
1737  ComputeLogs(npt, optionZ);
1738  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1739  }
1740  } else {
1741  drawtype = drawtype+10;
1742  npt = 0;
1743  for (i=first; i<=last;i++) {
1744  npt++;
1745  if (!optionBins) {
1746  gywork[npt-1] = wmin+(i-first)*delta+0.5*delta;
1747  } else {
1748  yi1 = y[i]; yi = y[i-1];
1749  if (yi1 < yi) {
1750  if (i != last) Error(where, "Y must be in increasing order");
1751  else Error(where, "Y must have N+1 values with option N");
1752  return;
1753  }
1754  gywork[npt-1] = y[i-1] + 0.5*(y[i]-y[i-1]);
1755  }
1756  gxwork[npt-1] = x[i-1];
1757  ComputeLogs(npt, optionZ);
1758  if ((gxworkl[npt] < uxmin) || (gxworkl[npt] > uxmax)) {
1759  if (npt > 2) {
1760  ComputeLogs(npt, optionZ);
1761  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1762  }
1763  gxwork[0] = gxwork[npt-1];
1764  gywork[0] = gywork[npt-1];
1765  npt = 1;
1766  continue;
1767  }
1768  if (npt >= fgMaxPointsPerLine) {
1769  ComputeLogs(fgMaxPointsPerLine, optionZ);
1770  Smooth(theGraph, fgMaxPointsPerLine,gxworkl,gyworkl,drawtype);
1771  gxwork[0] = gxwork[npt-1];
1772  gywork[0] = gywork[npt-1];
1773  npt = 1;
1774  }
1775  } //endfor (i=first; i<=last;i++)
1776  if (npt > 1) {
1777  ComputeLogs(npt, optionZ);
1778  Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
1779  }
1780  }
1781  }
1782 
1783  // Draw the histogram with a simple line or/and a marker
1784 
1785  optionMarker = 0;
1786  if ((optionStar) || (optionMark))optionMarker=1;
1787  if ((optionMarker) || (optionLine)) {
1788  wminstep = wmin + 0.5*delta;
1789  Axis_t ax1,ax2,ay1,ay2;
1790  gPad->GetRangeAxis(ax1,ay1,ax2,ay2);
1791 
1792  if (!optionRot) {
1793  npt = 0;
1794  for (i=first; i<=last;i++) {
1795  npt++;
1796  if (!optionBins) {
1797  gxwork[npt-1] = wmin+(i-first)*delta+0.5*delta;
1798  } else {
1799  xi1 = x[i]; xi = x[i-1];
1800  if (xi1 < xi) {
1801  if (i != last) Error(where, "X must be in increasing order");
1802  else Error(where, "X must have N+1 values with option N");
1803  return;
1804  }
1805  gxwork[npt-1] = x[i-1] + 0.5*(x[i]-x[i-1]);
1806  }
1807  if (gxwork[npt-1] < uxmin || gxwork[npt-1] > uxmax) { npt--; continue;}
1808  if ((optionMark != 10) && (optionLine == 0)) {
1809  if (y[i-1] <= rwymin) {npt--; continue;}
1810  }
1811  gywork[npt-1] = y[i-1];
1812  gywork[npt] = y[i-1]; //new
1813  if ((gywork[npt-1] < rwymin) || ((gywork[npt-1] > rwymax) && !optionFill2)) {
1814  if ((gywork[npt-1] < rwymin)) gywork[npt-1] = rwymin;
1815  if ((gywork[npt-1] > rwymax)) gywork[npt-1] = rwymax;
1816  if (npt > 2) {
1817  if (optionMarker) {
1818  ComputeLogs(npt, optionZ);
1819  gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
1820  }
1821  if (optionLine) {
1822  if (!optionMarker) ComputeLogs(npt, optionZ);
1823  gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
1824  }
1825  }
1826  gxwork[0] = gxwork[npt-1];
1827  gywork[0] = gywork[npt-1];
1828  npt = 1;
1829  continue;
1830  }
1831 
1832  if (npt >= fgMaxPointsPerLine) {
1833  if (optionMarker) {
1834  ComputeLogs(fgMaxPointsPerLine, optionZ);
1835  gPad->PaintPolyMarker(fgMaxPointsPerLine,gxworkl,gyworkl);
1836  }
1837  if (optionLine) {
1838  if (!optionMarker) ComputeLogs(fgMaxPointsPerLine, optionZ);
1839  if (optionFill2) {
1840  gxworkl[npt] = gxworkl[npt-1]; gyworkl[npt] = rwymin;
1841  gxworkl[npt+1] = gxworkl[0]; gyworkl[npt+1] = rwymin;
1842  gPad->PaintFillArea(fgMaxPointsPerLine+2,gxworkl,gyworkl);
1843  }
1844  gPad->PaintPolyLine(fgMaxPointsPerLine,gxworkl,gyworkl);
1845  }
1846  gxwork[0] = gxwork[npt-1];
1847  gywork[0] = gywork[npt-1];
1848  npt = 1;
1849  }
1850  } //endfor (i=first; i<=last;i++)
1851  if (optionMarker && npt > 0) {
1852  ComputeLogs(npt, optionZ);
1853  gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
1854  }
1855  if (optionLine && npt > 1) {
1856  if (!optionMarker) ComputeLogs(npt, optionZ);
1857  if (optionFill2) {
1858  gxworkl[npt] = gxworkl[npt-1]; gyworkl[npt] = rwymin;
1859  gxworkl[npt+1] = gxworkl[0]; gyworkl[npt+1] = rwymin;
1860  gPad->PaintFillArea(npt+2,gxworkl,gyworkl);
1861  }
1862  gPad->PaintPolyLine(npt,gxworkl,gyworkl);
1863  }
1864  } else {
1865  npt = 0;
1866  for (i=first; i<=last;i++) {
1867  npt++;
1868  if (!optionBins) {
1869  gywork[npt-1] = wminstep+(i-first)*delta+0.5*delta;
1870  } else {
1871  yi1 = y[i]; yi = y[i-1];
1872  if (yi1 < yi) {
1873  if (i != last) Error(where, "Y must be in increasing order");
1874  else Error(where, "Y must have N+1 values with option N");
1875  return;
1876  }
1877  gywork[npt-1] = y[i-1] + 0.5*(y[i]-y[i-1]);
1878  }
1879  gxwork[npt-1] = x[i-1];
1880  if ((gxwork[npt-1] < uxmin) || (gxwork[npt-1] > uxmax)) {
1881  if (npt > 2) {
1882  if (optionMarker) {
1883  ComputeLogs(npt, optionZ);
1884  gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
1885  }
1886  if (optionLine) {
1887  if (!optionMarker) ComputeLogs(npt, optionZ);
1888  gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
1889  }
1890  }
1891  gxwork[0] = gxwork[npt-1];
1892  gywork[0] = gywork[npt-1];
1893  npt = 1;
1894  continue;
1895  }
1896  if (npt >= fgMaxPointsPerLine) {
1897  if (optionMarker) {
1898  ComputeLogs(fgMaxPointsPerLine, optionZ);
1899  gPad->PaintPolyMarker(fgMaxPointsPerLine,gxworkl,gyworkl);
1900  }
1901  if (optionLine) {
1902  if (!optionMarker) ComputeLogs(fgMaxPointsPerLine, optionZ);
1903  gPad->PaintPolyLine(fgMaxPointsPerLine,gxworkl,gyworkl);
1904  }
1905  gxwork[0] = gxwork[npt-1];
1906  gywork[0] = gywork[npt-1];
1907  npt = 1;
1908  }
1909  } //endfor (i=first; i<=last;i++)
1910  if (optionMarker && npt > 0) {
1911  ComputeLogs(npt, optionZ);
1912  gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
1913  }
1914  if (optionLine != 0 && npt > 1) {
1915  if (!optionMarker) ComputeLogs(npt, optionZ);
1916  gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
1917  }
1918  }
1919  }
1920 
1921  // Draw the histogram as a bar chart
1922 
1923  if (optionBar) {
1924  if (!optionBins) {
1925  offset = delta*baroffset; dbar = delta*barwidth;
1926  } else {
1927  if (!optionRot) {
1928  offset = (x[1]-x[0])*baroffset;
1929  dbar = (x[1]-x[0])*barwidth;
1930  } else {
1931  offset = (y[1]-y[0])*baroffset;
1932  dbar = (y[1]-y[0])*barwidth;
1933  }
1934  }
1935  drawbordersav = drawborder;
1936  gStyle->SetDrawBorder(1);
1937  if (!optionRot) {
1938  xlow = wmin+offset;
1939  xhigh = wmin+offset+dbar;
1940  if (!optionOne) ylow = TMath::Min(TMath::Max((Double_t)0,gPad->GetUymin())
1941  ,gPad->GetUymax());
1942  else ylow = gPad->GetUymin();
1943 
1944  for (i=first; i<=last;i++) {
1945  yhigh = y[i-1];
1946  gxwork[0] = xlow;
1947  gywork[0] = ylow;
1948  gxwork[1] = xhigh;
1949  gywork[1] = yhigh;
1950  ComputeLogs(2, optionZ);
1951  if (xlow < rwxmax && xhigh > rwxmin)
1952  gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
1953  if (!optionBins) {
1954  xlow = xlow+delta;
1955  xhigh = xhigh+delta;
1956  } else {
1957  if (i < last) {
1958  xi1 = x[i]; xi = x[i-1];
1959  if (xi1 < xi) {
1960  Error(where, "X must be in increasing order");
1961  return;
1962  }
1963  offset = (x[i+1]-x[i])*baroffset;
1964  dbar = (x[i+1]-x[i])*barwidth;
1965  xlow = x[i] + offset;
1966  xhigh = x[i] + offset + dbar;
1967  }
1968  }
1969  } //endfor (i=first; i<=last;i++)
1970  } else {
1971  ylow = wmin + offset;
1972  yhigh = wmin + offset + dbar;
1973  if (!optionOne) xlow = TMath::Max((Double_t)0,gPad->GetUxmin());
1974  else xlow = gPad->GetUxmin();
1975  for (i=first; i<=last;i++) {
1976  xhigh = x[i-1];
1977  gxwork[0] = xlow;
1978  gywork[0] = ylow;
1979  gxwork[1] = xhigh;
1980  gywork[1] = yhigh;
1981  ComputeLogs(2, optionZ);
1982  gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
1983  gPad->PaintBox(xlow,ylow,xhigh,yhigh);
1984  if (!optionBins) {
1985  ylow = ylow + delta;
1986  yhigh = yhigh + delta;
1987  } else {
1988  if (i < last) {
1989  yi1 = y[i]; yi = y[i-1];
1990  if (yi1 < yi) {
1991  Error(where, "Y must be in increasing order");
1992  return;
1993  }
1994  offset = (y[i+1]-y[i])*baroffset;
1995  dbar = (y[i+1]-y[i])*barwidth;
1996  ylow = y[i] + offset;
1997  yhigh = y[i] + offset + dbar;
1998  }
1999  }
2000  } //endfor (i=first; i<=last;i++)
2001  }
2002  gStyle->SetDrawBorder(drawbordersav);
2003  }
2004  gPad->ResetBit(TGraph::kClipFrame);
2005 
2006  delete [] gxwork;
2007  delete [] gywork;
2008  delete [] gxworkl;
2009  delete [] gyworkl;
2010 }
2011 
2012 
2013 ////////////////////////////////////////////////////////////////////////////////
2014 /// [Paint this TGraphAsymmErrors with its current attributes.](#GP03)
2015 
2016 void TGraphPainter::PaintGraphAsymmErrors(TGraph *theGraph, Option_t *option)
2018 
2019  Double_t *xline = 0;
2020  Double_t *yline = 0;
2021  Int_t if1 = 0;
2022  Int_t if2 = 0;
2023  Double_t xb[4], yb[4];
2024 
2025  const Int_t kBASEMARKER=8;
2026  Double_t s2x, s2y, symbolsize, sbase;
2027  Double_t x, y, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
2028  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};
2029  static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
2030  Int_t theNpoints = theGraph->GetN();
2031  Double_t *theX = theGraph->GetX();
2032  Double_t *theY = theGraph->GetY();
2033  Double_t *theEXlow = theGraph->GetEXlow(); if (!theEXlow) return;
2034  Double_t *theEYlow = theGraph->GetEYlow(); if (!theEYlow) return;
2035  Double_t *theEXhigh = theGraph->GetEXhigh(); if (!theEXhigh) return;
2036  Double_t *theEYhigh = theGraph->GetEYhigh(); if (!theEYhigh) return;
2037 
2038  if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
2039  Bool_t brackets = kFALSE;
2040  Bool_t braticks = kFALSE;
2041  if (strstr(option,"||") || strstr(option,"[]")) {
2042  brackets = kTRUE;
2043  if (strstr(option,"[]")) braticks = kTRUE;
2044  }
2045  Bool_t endLines = kTRUE;
2046  if (strchr(option,'z')) endLines = kFALSE;
2047  if (strchr(option,'Z')) endLines = kFALSE;
2048  const char *arrowOpt = 0;
2049  if (strchr(option,'>')) arrowOpt = ">";
2050  if (strstr(option,"|>")) arrowOpt = "|>";
2051 
2052  Bool_t axis = kFALSE;
2053  if (strchr(option,'a')) axis = kTRUE;
2054  if (strchr(option,'A')) axis = kTRUE;
2055  if (axis) PaintGraphSimple(theGraph, option);
2056 
2057  Bool_t option0 = kFALSE;
2058  Bool_t option2 = kFALSE;
2059  Bool_t option3 = kFALSE;
2060  Bool_t option4 = kFALSE;
2061  Bool_t option5 = kFALSE;
2062  if (strchr(option,'0')) option0 = kTRUE;
2063  if (strchr(option,'2')) option2 = kTRUE;
2064  if (strchr(option,'3')) option3 = kTRUE;
2065  if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
2066  if (strchr(option,'5')) {option2 = kTRUE; option5 = kTRUE;}
2067 
2068  if (option3) {
2069  xline = new Double_t[2*theNpoints];
2070  yline = new Double_t[2*theNpoints];
2071  if (!xline || !yline) {
2072  Error("Paint", "too many points, out of memory");
2073  return;
2074  }
2075  if1 = 1;
2076  if2 = 2*theNpoints;
2077  }
2078 
2079  theGraph->TAttLine::Modify();
2080 
2081  TArrow arrow;
2082  arrow.SetLineWidth(theGraph->GetLineWidth());
2083  arrow.SetLineColor(theGraph->GetLineColor());
2084  arrow.SetFillColor(theGraph->GetFillColor());
2085 
2086  TBox box;
2087  Double_t x1b,y1b,x2b,y2b;
2088  box.SetLineWidth(theGraph->GetLineWidth());
2089  box.SetLineColor(theGraph->GetLineColor());
2090  box.SetFillColor(theGraph->GetFillColor());
2091  box.SetFillStyle(theGraph->GetFillStyle());
2092 
2093  symbolsize = theGraph->GetMarkerSize();
2094  sbase = symbolsize*kBASEMARKER;
2095  Int_t mark = theGraph->GetMarkerStyle();
2096  Double_t cx = 0;
2097  Double_t cy = 0;
2098  if (mark >= 20 && mark <= 34) {
2099  cx = cxx[mark-20];
2100  cy = cyy[mark-20];
2101  }
2102 
2103  // Define the offset of the error bars due to the symbol size
2104  s2x = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
2105  s2y =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
2106  Int_t dxend = Int_t(gStyle->GetEndErrorSize());
2107  tx = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
2108  ty =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
2109  Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
2110 
2111  gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
2112  for (Int_t i=0;i<theNpoints;i++) {
2113  x = gPad->XtoPad(theX[i]);
2114  y = gPad->YtoPad(theY[i]);
2115  if (!option0) {
2116  if (option3) {
2117  if (x < gPad->GetUxmin()) x = gPad->GetUxmin();
2118  if (x > gPad->GetUxmax()) x = gPad->GetUxmax();
2119  if (y < gPad->GetUymin()) y = gPad->GetUymin();
2120  if (y > gPad->GetUymax()) y = gPad->GetUymax();
2121  } else {
2122  if (x < gPad->GetUxmin()) continue;
2123  if (x > gPad->GetUxmax()) continue;
2124  if (y < gPad->GetUymin()) continue;
2125  if (y > gPad->GetUymax()) continue;
2126  }
2127  }
2128  xl1 = x - s2x*cx;
2129  xl2 = gPad->XtoPad(theX[i] - theEXlow[i]);
2130 
2131  // draw the error rectangles
2132  if (option2) {
2133  x1b = gPad->XtoPad(theX[i] - theEXlow[i]);
2134  y1b = gPad->YtoPad(theY[i] - theEYlow[i]);
2135  x2b = gPad->XtoPad(theX[i] + theEXhigh[i]);
2136  y2b = gPad->YtoPad(theY[i] + theEYhigh[i]);
2137  if (x1b < gPad->GetUxmin()) x1b = gPad->GetUxmin();
2138  if (x1b > gPad->GetUxmax()) x1b = gPad->GetUxmax();
2139  if (y1b < gPad->GetUymin()) y1b = gPad->GetUymin();
2140  if (y1b > gPad->GetUymax()) y1b = gPad->GetUymax();
2141  if (x2b < gPad->GetUxmin()) x2b = gPad->GetUxmin();
2142  if (x2b > gPad->GetUxmax()) x2b = gPad->GetUxmax();
2143  if (y2b < gPad->GetUymin()) y2b = gPad->GetUymin();
2144  if (y2b > gPad->GetUymax()) y2b = gPad->GetUymax();
2145  if (option5) box.PaintBox(x1b, y1b, x2b, y2b, "l");
2146  else box.PaintBox(x1b, y1b, x2b, y2b);
2147  continue;
2148  }
2149 
2150  // keep points for fill area drawing
2151  if (option3) {
2152  xline[if1-1] = x;
2153  xline[if2-1] = x;
2154  yline[if1-1] = gPad->YtoPad(theY[i] + theEYhigh[i]);
2155  yline[if2-1] = gPad->YtoPad(theY[i] - theEYlow[i]);
2156  if1++;
2157  if2--;
2158  continue;
2159  }
2160 
2161  if (xl1 > xl2) {
2162  if (arrowOpt) {
2163  arrow.PaintArrow(xl1,y,xl2,y,asize,arrowOpt);
2164  } else {
2165  if (!brackets) gPad->PaintLine(xl1,y,xl2,y);
2166  if (endLines) {
2167  if (braticks) {
2168  xb[0] = xl2+tx; yb[0] = y-ty;
2169  xb[1] = xl2; yb[1] = y-ty;
2170  xb[2] = xl2; yb[2] = y+ty;
2171  xb[3] = xl2+tx; yb[3] = y+ty;
2172  gPad->PaintPolyLine(4, xb, yb);
2173  } else {
2174  gPad->PaintLine(xl2,y-ty,xl2,y+ty);
2175  }
2176  }
2177  }
2178  }
2179  xr1 = x + s2x*cx;
2180  xr2 = gPad->XtoPad(theX[i] + theEXhigh[i]);
2181  if (xr1 < xr2) {
2182  if (arrowOpt) {
2183  arrow.PaintArrow(xr1,y,xr2,y,asize,arrowOpt);
2184  } else {
2185  if (!brackets) gPad->PaintLine(xr1,y,xr2,y);
2186  if (endLines) {
2187  if (braticks) {
2188  xb[0] = xr2-tx; yb[0] = y-ty;
2189  xb[1] = xr2; yb[1] = y-ty;
2190  xb[2] = xr2; yb[2] = y+ty;
2191  xb[3] = xr2-tx; yb[3] = y+ty;
2192  gPad->PaintPolyLine(4, xb, yb);
2193  } else {
2194  gPad->PaintLine(xr2,y-ty,xr2,y+ty);
2195  }
2196  }
2197  }
2198  }
2199  yup1 = y + s2y*cy;
2200  yup2 = gPad->YtoPad(theY[i] + theEYhigh[i]);
2201  if (yup2 > gPad->GetUymax()) yup2 = gPad->GetUymax();
2202  if (yup2 > yup1) {
2203  if (arrowOpt) {
2204  arrow.PaintArrow(x,yup1,x,yup2,asize,arrowOpt);
2205  } else {
2206  if (!brackets) gPad->PaintLine(x,yup1,x,yup2);
2207  if (endLines) {
2208  if (braticks) {
2209  xb[0] = x-tx; yb[0] = yup2-ty;
2210  xb[1] = x-tx; yb[1] = yup2;
2211  xb[2] = x+tx; yb[2] = yup2;
2212  xb[3] = x+tx; yb[3] = yup2-ty;
2213  gPad->PaintPolyLine(4, xb, yb);
2214  } else {
2215  gPad->PaintLine(x-tx,yup2,x+tx,yup2);
2216  }
2217  }
2218  }
2219  }
2220  ylow1 = y - s2y*cy;
2221  ylow2 = gPad->YtoPad(theY[i] - theEYlow[i]);
2222  if (ylow2 < gPad->GetUymin()) ylow2 = gPad->GetUymin();
2223  if (ylow2 < ylow1) {
2224  if (arrowOpt) {
2225  arrow.PaintArrow(x,ylow1,x,ylow2,asize,arrowOpt);
2226  } else {
2227  if (!brackets) gPad->PaintLine(x,ylow1,x,ylow2);
2228  if (endLines) {
2229  if (braticks) {
2230  xb[0] = x-tx; yb[0] = ylow2+ty;
2231  xb[1] = x-tx; yb[1] = ylow2;
2232  xb[2] = x+tx; yb[2] = ylow2;
2233  xb[3] = x+tx; yb[3] = ylow2+ty;
2234  gPad->PaintPolyLine(4, xb, yb);
2235  } else {
2236  gPad->PaintLine(x-tx,ylow2,x+tx,ylow2);
2237  }
2238  }
2239  }
2240  }
2241  }
2242  if (!brackets && !axis) PaintGraphSimple(theGraph, option);
2243  gPad->ResetBit(TGraph::kClipFrame);
2244 
2245  if (option3) {
2246  Int_t logx = gPad->GetLogx();
2247  Int_t logy = gPad->GetLogy();
2248  gPad->SetLogx(0);
2249  gPad->SetLogy(0);
2250  if (option4) PaintGraph(theGraph, 2*theNpoints, xline, yline,"FC");
2251  else PaintGraph(theGraph, 2*theNpoints, xline, yline,"F");
2252  gPad->SetLogx(logx);
2253  gPad->SetLogy(logy);
2254  delete [] xline;
2255  delete [] yline;
2256  }
2257 }
2258 
2259 
2260 ////////////////////////////////////////////////////////////////////////////////
2261 /// [Paint this TGraphBentErrors with its current attributes.]($GP03)
2262 
2263 void TGraphPainter::PaintGraphBentErrors(TGraph *theGraph, Option_t *option)
2265 
2266  Double_t *xline = 0;
2267  Double_t *yline = 0;
2268  Int_t if1 = 0;
2269  Int_t if2 = 0;
2270  Double_t xb[4], yb[4];
2271 
2272  const Int_t kBASEMARKER=8;
2273  Double_t s2x, s2y, symbolsize, sbase;
2274  Double_t x, y, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
2275  Double_t bxl, bxh, byl, byh;
2276  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};
2277  static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
2278  Int_t theNpoints = theGraph->GetN();
2279  Double_t *theX = theGraph->GetX();
2280  Double_t *theY = theGraph->GetY();
2281  Double_t *theEXlow = theGraph->GetEXlow(); if (!theEXlow) return;
2282  Double_t *theEYlow = theGraph->GetEYlow(); if (!theEYlow) return;
2283  Double_t *theEXhigh = theGraph->GetEXhigh(); if (!theEXhigh) return;
2284  Double_t *theEYhigh = theGraph->GetEYhigh(); if (!theEYhigh) return;
2285  Double_t *theEXlowd = theGraph->GetEXlowd(); if (!theEXlowd) return;
2286  Double_t *theEXhighd = theGraph->GetEXhighd(); if (!theEXhighd) return;
2287  Double_t *theEYlowd = theGraph->GetEYlowd(); if (!theEYlowd) return;
2288  Double_t *theEYhighd = theGraph->GetEYhighd(); if (!theEYhighd) return;
2289 
2290  if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
2291  Bool_t brackets = kFALSE;
2292  Bool_t braticks = kFALSE;
2293  if (strstr(option,"||") || strstr(option,"[]")) {
2294  brackets = kTRUE;
2295  if (strstr(option,"[]")) braticks = kTRUE;
2296  }
2297  Bool_t endLines = kTRUE;
2298  if (strchr(option,'z')) endLines = kFALSE;
2299  if (strchr(option,'Z')) endLines = kFALSE;
2300  const char *arrowOpt = 0;
2301  if (strchr(option,'>')) arrowOpt = ">";
2302  if (strstr(option,"|>")) arrowOpt = "|>";
2303 
2304  Bool_t axis = kFALSE;
2305  if (strchr(option,'a')) axis = kTRUE;
2306  if (strchr(option,'A')) axis = kTRUE;
2307  if (axis) PaintGraphSimple(theGraph,option);
2308 
2309  Bool_t option0 = kFALSE;
2310  Bool_t option2 = kFALSE;
2311  Bool_t option3 = kFALSE;
2312  Bool_t option4 = kFALSE;
2313  Bool_t option5 = kFALSE;
2314  if (strchr(option,'0')) option0 = kTRUE;
2315  if (strchr(option,'2')) option2 = kTRUE;
2316  if (strchr(option,'3')) option3 = kTRUE;
2317  if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
2318  if (strchr(option,'5')) {option2 = kTRUE; option5 = kTRUE;}
2319 
2320  if (option3) {
2321  xline = new Double_t[2*theNpoints];
2322  yline = new Double_t[2*theNpoints];
2323  if (!xline || !yline) {
2324  Error("Paint", "too many points, out of memory");
2325  return;
2326  }
2327  if1 = 1;
2328  if2 = 2*theNpoints;
2329  }
2330 
2331  theGraph->TAttLine::Modify();
2332 
2333  TArrow arrow;
2334  arrow.SetLineWidth(theGraph->GetLineWidth());
2335  arrow.SetLineColor(theGraph->GetLineColor());
2336  arrow.SetFillColor(theGraph->GetFillColor());
2337 
2338  TBox box;
2339  Double_t x1b,y1b,x2b,y2b;
2340  box.SetLineWidth(theGraph->GetLineWidth());
2341  box.SetLineColor(theGraph->GetLineColor());
2342  box.SetFillColor(theGraph->GetFillColor());
2343  box.SetFillStyle(theGraph->GetFillStyle());
2344 
2345  symbolsize = theGraph->GetMarkerSize();
2346  sbase = symbolsize*kBASEMARKER;
2347  Int_t mark = theGraph->GetMarkerStyle();
2348  Double_t cx = 0;
2349  Double_t cy = 0;
2350  if (mark >= 20 && mark <= 34) {
2351  cx = cxx[mark-20];
2352  cy = cyy[mark-20];
2353  }
2354 
2355  // define the offset of the error bars due to the symbol size
2356  s2x = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
2357  s2y =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
2358  Int_t dxend = Int_t(gStyle->GetEndErrorSize());
2359  tx = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
2360  ty =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
2361  Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
2362 
2363  gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
2364  for (Int_t i=0;i<theNpoints;i++) {
2365  x = gPad->XtoPad(theX[i]);
2366  y = gPad->YtoPad(theY[i]);
2367  bxl = gPad->YtoPad(theY[i]+theEXlowd[i]);
2368  bxh = gPad->YtoPad(theY[i]+theEXhighd[i]);
2369  byl = gPad->XtoPad(theX[i]+theEYlowd[i]);
2370  byh = gPad->XtoPad(theX[i]+theEYhighd[i]);
2371  if (!option0) {
2372  if (option3) {
2373  if (x < gPad->GetUxmin()) x = gPad->GetUxmin();
2374  if (x > gPad->GetUxmax()) x = gPad->GetUxmax();
2375  if (y < gPad->GetUymin()) y = gPad->GetUymin();
2376  if (y > gPad->GetUymax()) y = gPad->GetUymax();
2377  } else {
2378  if (x < gPad->GetUxmin()) continue;
2379  if (x > gPad->GetUxmax()) continue;
2380  if (y < gPad->GetUymin()) continue;
2381  if (y > gPad->GetUymax()) continue;
2382  }
2383  }
2384 
2385  // draw the error rectangles
2386  if (option2) {
2387  x1b = gPad->XtoPad(theX[i] - theEXlow[i]);
2388  y1b = gPad->YtoPad(theY[i] - theEYlow[i]);
2389  x2b = gPad->XtoPad(theX[i] + theEXhigh[i]);
2390  y2b = gPad->YtoPad(theY[i] + theEYhigh[i]);
2391  if (x1b < gPad->GetUxmin()) x1b = gPad->GetUxmin();
2392  if (x1b > gPad->GetUxmax()) x1b = gPad->GetUxmax();
2393  if (y1b < gPad->GetUymin()) y1b = gPad->GetUymin();
2394  if (y1b > gPad->GetUymax()) y1b = gPad->GetUymax();
2395  if (x2b < gPad->GetUxmin()) x2b = gPad->GetUxmin();
2396  if (x2b > gPad->GetUxmax()) x2b = gPad->GetUxmax();
2397  if (y2b < gPad->GetUymin()) y2b = gPad->GetUymin();
2398  if (y2b > gPad->GetUymax()) y2b = gPad->GetUymax();
2399  if (option5) box.PaintBox(x1b, y1b, x2b, y2b, "l");
2400  else box.PaintBox(x1b, y1b, x2b, y2b);
2401  continue;
2402  }
2403 
2404  // keep points for fill area drawing
2405  if (option3) {
2406  xline[if1-1] = byh;
2407  xline[if2-1] = byl;
2408  yline[if1-1] = gPad->YtoPad(theY[i] + theEYhigh[i]);
2409  yline[if2-1] = gPad->YtoPad(theY[i] - theEYlow[i]);
2410  if1++;
2411  if2--;
2412  continue;
2413  }
2414 
2415  xl1 = x - s2x*cx;
2416  xl2 = gPad->XtoPad(theX[i] - theEXlow[i]);
2417  if (xl1 > xl2) {
2418  if (arrowOpt) {
2419  arrow.PaintArrow(xl1,y,xl2,bxl,asize,arrowOpt);
2420  } else {
2421  if (!brackets) gPad->PaintLine(xl1,y,xl2,bxl);
2422  if (endLines) {
2423  if (braticks) {
2424  xb[0] = xl2+tx; yb[0] = bxl-ty;
2425  xb[1] = xl2; yb[1] = bxl-ty;
2426  xb[2] = xl2; yb[2] = bxl+ty;
2427  xb[3] = xl2+tx; yb[3] = bxl+ty;
2428  gPad->PaintPolyLine(4, xb, yb);
2429  } else {
2430  gPad->PaintLine(xl2,bxl-ty,xl2,bxl+ty);
2431  }
2432  }
2433  }
2434  }
2435  xr1 = x + s2x*cx;
2436  xr2 = gPad->XtoPad(theX[i] + theEXhigh[i]);
2437  if (xr1 < xr2) {
2438  if (arrowOpt) {
2439  arrow.PaintArrow(xr1,y,xr2,bxh,asize,arrowOpt);
2440  } else {
2441  if (!brackets) gPad->PaintLine(xr1,y,xr2,bxh);
2442  if (endLines) {
2443  if (braticks) {
2444  xb[0] = xr2-tx; yb[0] = bxh-ty;
2445  xb[1] = xr2; yb[1] = bxh-ty;
2446  xb[2] = xr2; yb[2] = bxh+ty;
2447  xb[3] = xr2-tx; yb[3] = bxh+ty;
2448  gPad->PaintPolyLine(4, xb, yb);
2449  } else {
2450  gPad->PaintLine(xr2,bxh-ty,xr2,bxh+ty);
2451  }
2452  }
2453  }
2454  }
2455  yup1 = y + s2y*cy;
2456  yup2 = gPad->YtoPad(theY[i] + theEYhigh[i]);
2457  if (yup2 > gPad->GetUymax()) yup2 = gPad->GetUymax();
2458  if (yup2 > yup1) {
2459  if (arrowOpt) {
2460  arrow.PaintArrow(x,yup1,byh,yup2,asize,arrowOpt);
2461  } else {
2462  if (!brackets) gPad->PaintLine(x,yup1,byh,yup2);
2463  if (endLines) {
2464  if (braticks) {
2465  xb[0] = byh-tx; yb[0] = yup2-ty;
2466  xb[1] = byh-tx; yb[1] = yup2;
2467  xb[2] = byh+tx; yb[2] = yup2;
2468  xb[3] = byh+tx; yb[3] = yup2-ty;
2469  gPad->PaintPolyLine(4, xb, yb);
2470  } else {
2471  gPad->PaintLine(byh-tx,yup2,byh+tx,yup2);
2472  }
2473  }
2474  }
2475  }
2476  ylow1 = y - s2y*cy;
2477  ylow2 = gPad->YtoPad(theY[i] - theEYlow[i]);
2478  if (ylow2 < gPad->GetUymin()) ylow2 = gPad->GetUymin();
2479  if (ylow2 < ylow1) {
2480  if (arrowOpt) {
2481  arrow.PaintArrow(x,ylow1,byl,ylow2,asize,arrowOpt);
2482  } else {
2483  if (!brackets) gPad->PaintLine(x,ylow1,byl,ylow2);
2484  if (endLines) {
2485  if (braticks) {
2486  xb[0] = byl-tx; yb[0] = ylow2+ty;
2487  xb[1] = byl-tx; yb[1] = ylow2;
2488  xb[2] = byl+tx; yb[2] = ylow2;
2489  xb[3] = byl+tx; yb[3] = ylow2+ty;
2490  gPad->PaintPolyLine(4, xb, yb);
2491  } else {
2492  gPad->PaintLine(byl-tx,ylow2,byl+tx,ylow2);
2493  }
2494  }
2495  }
2496  }
2497  }
2498  if (!brackets && !axis) PaintGraphSimple(theGraph, option);
2499  gPad->ResetBit(TGraph::kClipFrame);
2500 
2501  if (option3) {
2502  Int_t logx = gPad->GetLogx();
2503  Int_t logy = gPad->GetLogy();
2504  gPad->SetLogx(0);
2505  gPad->SetLogy(0);
2506  if (option4) PaintGraph(theGraph, 2*theNpoints, xline, yline,"FC");
2507  else PaintGraph(theGraph, 2*theNpoints, xline, yline,"F");
2508  gPad->SetLogx(logx);
2509  gPad->SetLogy(logy);
2510  delete [] xline;
2511  delete [] yline;
2512  }
2513 }
2514 
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// [Paint this TGraphErrors with its current attributes.]($GP03)
2518 
2519 void TGraphPainter::PaintGraphErrors(TGraph *theGraph, Option_t *option)
2521 
2522  Double_t *xline = 0;
2523  Double_t *yline = 0;
2524  Int_t if1 = 0;
2525  Int_t if2 = 0;
2526  Double_t xb[4], yb[4];
2527 
2528  const Int_t kBASEMARKER=8;
2529  Double_t s2x, s2y, symbolsize, sbase;
2530  Double_t x, y, ex, ey, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
2531  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};
2532  static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
2533  Int_t theNpoints = theGraph->GetN();
2534  Double_t *theX = theGraph->GetX();
2535  Double_t *theY = theGraph->GetY();
2536  Double_t *theEX = theGraph->GetEX(); if (!theEX) return;
2537  Double_t *theEY = theGraph->GetEY(); if (!theEY) return;
2538 
2539  if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
2540  Bool_t brackets = kFALSE;
2541  Bool_t braticks = kFALSE;
2542  if (strstr(option,"||") || strstr(option,"[]")) {
2543  brackets = kTRUE;
2544  if (strstr(option,"[]")) braticks = kTRUE;
2545  }
2546  Bool_t endLines = kTRUE;
2547  if (strchr(option,'z')) endLines = kFALSE;
2548  if (strchr(option,'Z')) endLines = kFALSE;
2549  const char *arrowOpt = 0;
2550  if (strchr(option,'>')) arrowOpt = ">";
2551  if (strstr(option,"|>")) arrowOpt = "|>";
2552 
2553  Bool_t axis = kFALSE;
2554  if (strchr(option,'a')) axis = kTRUE;
2555  if (strchr(option,'A')) axis = kTRUE;
2556  if (axis) PaintGraphSimple(theGraph, option);
2557 
2558  Bool_t option0 = kFALSE;
2559  Bool_t option2 = kFALSE;
2560  Bool_t option3 = kFALSE;
2561  Bool_t option4 = kFALSE;
2562  Bool_t option5 = kFALSE;
2563  if (strchr(option,'0')) option0 = kTRUE;
2564  if (strchr(option,'2')) option2 = kTRUE;
2565  if (strchr(option,'3')) option3 = kTRUE;
2566  if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
2567  if (strchr(option,'5')) {option2 = kTRUE; option5 = kTRUE;}
2568 
2569  if (option3) {
2570  xline = new Double_t[2*theNpoints];
2571  yline = new Double_t[2*theNpoints];
2572  if (!xline || !yline) {
2573  Error("Paint", "too many points, out of memory");
2574  return;
2575  }
2576  if1 = 1;
2577  if2 = 2*theNpoints;
2578  }
2579 
2580  theGraph->TAttLine::Modify();
2581 
2582  TArrow arrow;
2583  arrow.SetLineWidth(theGraph->GetLineWidth());
2584  arrow.SetLineColor(theGraph->GetLineColor());
2585  arrow.SetFillColor(theGraph->GetFillColor());
2586 
2587  TBox box;
2588  Double_t x1b,y1b,x2b,y2b;
2589  box.SetLineWidth(theGraph->GetLineWidth());
2590  box.SetLineColor(theGraph->GetLineColor());
2591  box.SetFillColor(theGraph->GetFillColor());
2592  box.SetFillStyle(theGraph->GetFillStyle());
2593 
2594  symbolsize = theGraph->GetMarkerSize();
2595  sbase = symbolsize*kBASEMARKER;
2596  Int_t mark = theGraph->GetMarkerStyle();
2597  Double_t cx = 0;
2598  Double_t cy = 0;
2599  if (mark >= 20 && mark <= 34) {
2600  cx = cxx[mark-20];
2601  cy = cyy[mark-20];
2602  }
2603 
2604  // define the offset of the error bars due to the symbol size
2605  s2x = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
2606  s2y =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
2607  Int_t dxend = Int_t(gStyle->GetEndErrorSize());
2608  tx = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
2609  ty =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
2610  Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
2611 
2612  gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
2613  for (Int_t i=0;i<theNpoints;i++) {
2614  x = gPad->XtoPad(theX[i]);
2615  y = gPad->YtoPad(theY[i]);
2616  if (!option0) {
2617  if (option3) {
2618  if (x < gPad->GetUxmin()) x = gPad->GetUxmin();
2619  if (x > gPad->GetUxmax()) x = gPad->GetUxmax();
2620  if (y < gPad->GetUymin()) y = gPad->GetUymin();
2621  if (y > gPad->GetUymax()) y = gPad->GetUymax();
2622  } else {
2623  if (x < gPad->GetUxmin()) continue;
2624  if (x > gPad->GetUxmax()) continue;
2625  if (y < gPad->GetUymin()) continue;
2626  if (y > gPad->GetUymax()) continue;
2627  }
2628  }
2629  ex = theEX[i];
2630  ey = theEY[i];
2631 
2632  // draw the error rectangles
2633  if (option2) {
2634  x1b = gPad->XtoPad(theX[i] - ex);
2635  y1b = gPad->YtoPad(theY[i] - ey);
2636  x2b = gPad->XtoPad(theX[i] + ex);
2637  y2b = gPad->YtoPad(theY[i] + ey);
2638  if (x1b < gPad->GetUxmin()) x1b = gPad->GetUxmin();
2639  if (x1b > gPad->GetUxmax()) x1b = gPad->GetUxmax();
2640  if (y1b < gPad->GetUymin()) y1b = gPad->GetUymin();
2641  if (y1b > gPad->GetUymax()) y1b = gPad->GetUymax();
2642  if (x2b < gPad->GetUxmin()) x2b = gPad->GetUxmin();
2643  if (x2b > gPad->GetUxmax()) x2b = gPad->GetUxmax();
2644  if (y2b < gPad->GetUymin()) y2b = gPad->GetUymin();
2645  if (y2b > gPad->GetUymax()) y2b = gPad->GetUymax();
2646  if (option5) box.PaintBox(x1b, y1b, x2b, y2b, "l");
2647  else box.PaintBox(x1b, y1b, x2b, y2b);
2648  continue;
2649  }
2650 
2651  // keep points for fill area drawing
2652  if (option3) {
2653  xline[if1-1] = x;
2654  xline[if2-1] = x;
2655  yline[if1-1] = gPad->YtoPad(theY[i] + ey);
2656  yline[if2-1] = gPad->YtoPad(theY[i] - ey);
2657  if1++;
2658  if2--;
2659  continue;
2660  }
2661 
2662  xl1 = x - s2x*cx;
2663  xl2 = gPad->XtoPad(theX[i] - ex);
2664  if (xl1 > xl2) {
2665  if (arrowOpt) {
2666  arrow.PaintArrow(xl1,y,xl2,y,asize,arrowOpt);
2667  } else {
2668  if (!brackets) gPad->PaintLine(xl1,y,xl2,y);
2669  if (endLines) {
2670  if (braticks) {
2671  xb[0] = xl2+tx; yb[0] = y-ty;
2672  xb[1] = xl2; yb[1] = y-ty;
2673  xb[2] = xl2; yb[2] = y+ty;
2674  xb[3] = xl2+tx; yb[3] = y+ty;
2675  gPad->PaintPolyLine(4, xb, yb);
2676  } else {
2677  gPad->PaintLine(xl2,y-ty,xl2,y+ty);
2678  }
2679  }
2680  }
2681  }
2682  xr1 = x + s2x*cx;
2683  xr2 = gPad->XtoPad(theX[i] + ex);
2684  if (xr1 < xr2) {
2685  if (arrowOpt) {
2686  arrow.PaintArrow(xr1,y,xr2,y,asize,arrowOpt);
2687  } else {
2688  if (!brackets) gPad->PaintLine(xr1,y,xr2,y);
2689  if (endLines) {
2690  if (braticks) {
2691  xb[0] = xr2-tx; yb[0] = y-ty;
2692  xb[1] = xr2; yb[1] = y-ty;
2693  xb[2] = xr2; yb[2] = y+ty;
2694  xb[3] = xr2-tx; yb[3] = y+ty;
2695  gPad->PaintPolyLine(4, xb, yb);
2696  } else {
2697  gPad->PaintLine(xr2,y-ty,xr2,y+ty);
2698  }
2699  }
2700  }
2701  }
2702  yup1 = y + s2y*cy;
2703  yup2 = gPad->YtoPad(theY[i] + ey);
2704  if (yup2 > gPad->GetUymax()) yup2 = gPad->GetUymax();
2705  if (yup2 > yup1) {
2706  if (arrowOpt) {
2707  arrow.PaintArrow(x,yup1,x,yup2,asize,arrowOpt);
2708  } else {
2709  if (!brackets) gPad->PaintLine(x,yup1,x,yup2);
2710  if (endLines) {
2711  if (braticks) {
2712  xb[0] = x-tx; yb[0] = yup2-ty;
2713  xb[1] = x-tx; yb[1] = yup2;
2714  xb[2] = x+tx; yb[2] = yup2;
2715  xb[3] = x+tx; yb[3] = yup2-ty;
2716  gPad->PaintPolyLine(4, xb, yb);
2717  } else {
2718  gPad->PaintLine(x-tx,yup2,x+tx,yup2);
2719  }
2720  }
2721  }
2722  }
2723  ylow1 = y - s2y*cy;
2724  ylow2 = gPad->YtoPad(theY[i] - ey);
2725  if (ylow2 < gPad->GetUymin()) ylow2 = gPad->GetUymin();
2726  if (ylow2 < ylow1) {
2727  if (arrowOpt) {
2728  arrow.PaintArrow(x,ylow1,x,ylow2,asize,arrowOpt);
2729  } else {
2730  if (!brackets) gPad->PaintLine(x,ylow1,x,ylow2);
2731  if (endLines) {
2732  if (braticks) {
2733  xb[0] = x-tx; yb[0] = ylow2+ty;
2734  xb[1] = x-tx; yb[1] = ylow2;
2735  xb[2] = x+tx; yb[2] = ylow2;
2736  xb[3] = x+tx; yb[3] = ylow2+ty;
2737  gPad->PaintPolyLine(4, xb, yb);
2738  } else {
2739  gPad->PaintLine(x-tx,ylow2,x+tx,ylow2);
2740  }
2741  }
2742  }
2743  }
2744  }
2745  if (!brackets && !axis) PaintGraphSimple(theGraph, option);
2746  gPad->ResetBit(TGraph::kClipFrame);
2747 
2748  if (option3) {
2749  Int_t logx = gPad->GetLogx();
2750  Int_t logy = gPad->GetLogy();
2751  gPad->SetLogx(0);
2752  gPad->SetLogy(0);
2753  if (option4) PaintGraph(theGraph, 2*theNpoints, xline, yline,"FC");
2754  else PaintGraph(theGraph, 2*theNpoints, xline, yline,"F");
2755  gPad->SetLogx(logx);
2756  gPad->SetLogy(logy);
2757  delete [] xline;
2758  delete [] yline;
2759  }
2760 }
2761 
2762 
2763 ////////////////////////////////////////////////////////////////////////////////
2764 /// [Paint this TGraphPolar with its current attributes.]($GP04)
2765 
2766 void TGraphPainter::PaintGraphPolar(TGraph *theGraph, Option_t* options)
2768 
2769  Int_t ipt, i;
2770  Double_t rwrmin, rwrmax, rwtmin, rwtmax;
2771 
2772  TGraphPolar *theGraphPolar = (TGraphPolar*) theGraph;
2773 
2774  Int_t theNpoints = theGraphPolar->GetN();
2775  Double_t *theX = theGraphPolar->GetX();
2776  Double_t *theY = theGraphPolar->GetY();
2777  Double_t *theEX = theGraphPolar->GetEX();
2778  Double_t *theEY = theGraphPolar->GetEY();
2779 
2780  if (theNpoints<1) return;
2781  TString opt = options;
2782  opt.ToUpper();
2783 
2784  Bool_t nolabel = kFALSE;
2785  if (opt.Contains("N")){
2786  nolabel = kTRUE;
2787  opt.ReplaceAll("N","");
2788  }
2789 
2790  TGraphPolargram *thePolargram = theGraphPolar->GetPolargram();
2791 
2792  // Check for existing TGraphPolargram in the Pad
2793  if (gPad) {
2794  // Existing polargram
2795  if (thePolargram) if (!gPad->FindObject(thePolargram->GetName())) thePolargram=0;
2796  if (!thePolargram) {
2797  // Find any other Polargram in the Pad
2798  TListIter padObjIter(gPad->GetListOfPrimitives());
2799  while (TObject* AnyObj = padObjIter.Next()) {
2800  if (TString(AnyObj->ClassName()).CompareTo("TGraphPolargram",
2801  TString::kExact)==0)
2802  thePolargram = (TGraphPolargram*)AnyObj;
2803  theGraphPolar->SetPolargram(thePolargram);
2804  }
2805  }
2806  }
2807 
2808  // Get new polargram range if necessary.
2809  if (!thePolargram) {
2810  // Get range, initialize with first/last value
2811  rwrmin = theY[0]; rwrmax = theY[theNpoints-1];
2812  rwtmin = theX[0]; rwtmax = theX[theNpoints-1];
2813 
2814  for (ipt = 0; ipt < theNpoints; ipt++) {
2815  // Check for errors if available
2816  if (theEX) {
2817  if (theX[ipt] -theEX[ipt] < rwtmin) rwtmin = theX[ipt]-theEX[ipt];
2818  if (theX[ipt] +theEX[ipt] > rwtmax) rwtmax = theX[ipt]+theEX[ipt];
2819  } else {
2820  if (theX[ipt] < rwtmin) rwtmin=theX[ipt];
2821  if (theX[ipt] > rwtmax) rwtmax=theX[ipt];
2822  }
2823  if (theEY) {
2824  if (theY[ipt] -theEY[ipt] < rwrmin) rwrmin = theY[ipt]-theEY[ipt];
2825  if (theY[ipt] +theEY[ipt] > rwrmax) rwrmax = theY[ipt]+theEY[ipt];
2826  } else {
2827  if (theY[ipt] < rwrmin) rwrmin=theY[ipt];
2828  if (theY[ipt] > rwrmax) rwrmax=theY[ipt];
2829  }
2830  }
2831  // Add radial and Polar margins.
2832  if (rwrmin == rwrmax) rwrmax += 1.;
2833  if (rwtmin == rwtmax) rwtmax += 1.;
2834  Double_t dr = (rwrmax-rwrmin);
2835  Double_t dt = (rwtmax-rwtmin);
2836  rwrmax += 0.1*dr;
2837  rwrmin -= 0.1*dr;
2838 
2839  // Assume equaly spaced points for full 2*Pi.
2840  rwtmax += dt/theNpoints;
2841  } else {
2842  rwrmin = thePolargram->GetRMin();
2843  rwrmax = thePolargram->GetRMax();
2844  rwtmin = thePolargram->GetTMin();
2845  rwtmax = thePolargram->GetTMax();
2846  }
2847 
2848  if ((!thePolargram) || theGraphPolar->GetOptionAxis()) {
2849  // Draw Polar coord system
2850  thePolargram = new TGraphPolargram("Polargram",rwrmin,rwrmax,rwtmin,rwtmax);
2851  theGraphPolar->SetPolargram(thePolargram);
2852  if (opt.Contains("O")) thePolargram->SetBit(TGraphPolargram::kLabelOrtho);
2853  else thePolargram->ResetBit(TGraphPolargram::kLabelOrtho);
2854  if (nolabel) thePolargram->Draw("N");
2855  else thePolargram->Draw("");
2856  theGraphPolar->SetOptionAxis(kFALSE); //Prevent redrawing
2857  }
2858 
2859  // Convert points to polar.
2860  Double_t *theXpol = theGraphPolar->GetXpol();
2861  Double_t *theYpol = theGraphPolar->GetYpol();
2862 
2863  // Project theta in [0,2*Pi] and radius in [0,1].
2864  Double_t radiusNDC = rwrmax-rwrmin;
2865  Double_t thetaNDC = (rwtmax-rwtmin)/(2*TMath::Pi());
2866 
2867  // Draw the error bars.
2868  // Y errors are lines, but X errors are pieces of circles.
2869  if (opt.Contains("E")) {
2870  if (theEY) {
2871  for (i=0; i<theNpoints; i++) {
2872  Double_t eymin, eymax, exmin,exmax;
2873  exmin = (theY[i]-theEY[i]-rwrmin)/radiusNDC*
2874  TMath::Cos((theX[i]-rwtmin)/thetaNDC);
2875  eymin = (theY[i]-theEY[i]-rwrmin)/radiusNDC*
2876  TMath::Sin((theX[i]-rwtmin)/thetaNDC);
2877  exmax = (theY[i]+theEY[i]-rwrmin)/radiusNDC*
2878  TMath::Cos((theX[i]-rwtmin)/thetaNDC);
2879  eymax = (theY[i]+theEY[i]-rwrmin)/radiusNDC*
2880  TMath::Sin((theX[i]-rwtmin)/thetaNDC);
2881  theGraphPolar->TAttLine::Modify();
2882  if (exmin != exmax || eymin != eymax) gPad->PaintLine(exmin,eymin,exmax,eymax);
2883  }
2884  }
2885  if (theEX) {
2886  for (i=0; i<theNpoints; i++) {
2887  Double_t rad = (theY[i]-rwrmin)/radiusNDC;
2888  Double_t phimin = (theX[i]-theEX[i]-rwtmin)/thetaNDC*180/TMath::Pi();
2889  Double_t phimax = (theX[i]+theEX[i]-rwtmin)/thetaNDC*180/TMath::Pi();
2890  theGraphPolar->TAttLine::Modify();
2891  if (phimin != phimax) thePolargram->PaintCircle(0,0,rad,phimin,phimax,0);
2892  }
2893  }
2894  }
2895 
2896  // Draw the graph itself.
2897  if (!(gPad->GetLogx()) && !(gPad->GetLogy())) {
2898  Double_t a, b, c=1, x1, x2, y1, y2, discr, norm1, norm2, xts, yts;
2899  Bool_t previouspointin = kFALSE;
2900  Double_t norm = 0;
2901  Double_t xt = 0;
2902  Double_t yt = 0 ;
2903  Int_t j = -1;
2904  for (i=0; i<theNpoints; i++) {
2905  if (thePolargram->IsRadian()) {c=1;}
2906  if (thePolargram->IsDegree()) {c=180/TMath::Pi();}
2907  if (thePolargram->IsGrad()) {c=100/TMath::Pi();}
2908  xts = xt;
2909  yts = yt;
2910  xt = (theY[i]-rwrmin)/radiusNDC*TMath::Cos(c*(theX[i]-rwtmin)/thetaNDC);
2911  yt = (theY[i]-rwrmin)/radiusNDC*TMath::Sin(c*(theX[i]-rwtmin)/thetaNDC);
2912  norm = sqrt(xt*xt+yt*yt);
2913  // Check if points are in the main circle.
2914  if ( norm <= 1) {
2915  // We check that the previous point was in the circle too.
2916  // We record new point position.
2917  if (!previouspointin) {
2918  j++;
2919  theXpol[j] = xt;
2920  theYpol[j] = yt;
2921  } else {
2922  a = (yt-yts)/(xt-xts);
2923  b = yts-a*xts;
2924  discr = 4*(a*a-b*b+1);
2925  x1 = (-2*a*b+sqrt(discr))/(2*(a*a+1));
2926  x2 = (-2*a*b-sqrt(discr))/(2*(a*a+1));
2927  y1 = a*x1+b;
2928  y2 = a*x2+b;
2929  norm1 = sqrt((x1-xt)*(x1-xt)+(y1-yt)*(y1-yt));
2930  norm2 = sqrt((x2-xt)*(x2-xt)+(y2-yt)*(y2-yt));
2931  previouspointin = kFALSE;
2932  j = 0;
2933  if (norm1 < norm2) {
2934  theXpol[j] = x1;
2935  theYpol[j] = y1;
2936  } else {
2937  theXpol[j] = x2;
2938  theYpol[j] = y2;
2939  }
2940  j++;
2941  theXpol[j] = xt;
2942  theYpol[j] = yt;
2943  PaintGraph(theGraphPolar, j+1, theXpol, theYpol, opt);
2944  }
2945  } else {
2946  // We check that the previous point was in the circle.
2947  // We record new point position
2948  if (j>=1 && !previouspointin) {
2949  a = (yt-theYpol[j])/(xt-theXpol[j]);
2950  b = theYpol[j]-a*theXpol[j];
2951  previouspointin = kTRUE;
2952  discr = 4*(a*a-b*b+1);
2953  x1 = (-2*a*b+sqrt(discr))/(2*(a*a+1));
2954  x2 = (-2*a*b-sqrt(discr))/(2*(a*a+1));
2955  y1 = a*x1+b;
2956  y2 = a*x2+b;
2957  norm1 = sqrt((x1-xt)*(x1-xt)+(y1-yt)*(y1-yt));
2958  norm2 = sqrt((x2-xt)*(x2-xt)+(y2-yt)*(y2-yt));
2959  j++;
2960  if (norm1 < norm2) {
2961  theXpol[j] = x1;
2962  theYpol[j] = y1;
2963  } else {
2964  theXpol[j] = x2;
2965  theYpol[j] = y2;
2966  }
2967  PaintGraph(theGraphPolar, j+1, theXpol, theYpol, opt);
2968  }
2969  j=-1;
2970  }
2971  }
2972  if (j>=1) {
2973  // If the last point is in the circle, we draw the last serie of point.
2974  PaintGraph(theGraphPolar, j+1, theXpol, theYpol, opt);
2975  }
2976  } else {
2977  for (i=0; i<theNpoints; i++) {
2978  theXpol[i] = TMath::Abs((theY[i]-rwrmin)/radiusNDC*TMath::Cos((theX[i]-rwtmin)/thetaNDC)+1);
2979  theYpol[i] = TMath::Abs((theY[i]-rwrmin)/radiusNDC*TMath::Sin((theX[i]-rwtmin)/thetaNDC)+1);
2980  }
2981  PaintGraph(theGraphPolar, theNpoints, theXpol, theYpol,opt);
2982  }
2983 
2984  // Paint the title.
2985 
2986  if (TestBit(TH1::kNoTitle)) return;
2987  Int_t nt = strlen(theGraph->GetTitle());
2988  TPaveText *title = 0;
2989  TObject *obj;
2990  TIter next(gPad->GetListOfPrimitives());
2991  while ((obj = next())) {
2992  if (!obj->InheritsFrom(TPaveText::Class())) continue;
2993  title = (TPaveText*)obj;
2994  if (title->GetName())
2995  if (strcmp(title->GetName(),"title")) {title = 0; continue;}
2996  break;
2997  }
2998  if (nt == 0 || gStyle->GetOptTitle() <= 0) {
2999  if (title) delete title;
3000  return;
3001  }
3002  Double_t ht = gStyle->GetTitleH();
3003  Double_t wt = gStyle->GetTitleW();
3004  if (ht <= 0) ht = 1.1*gStyle->GetTitleFontSize();
3005  if (ht <= 0) ht = 0.05;
3006  if (wt <= 0) {
3007  TLatex l;
3008  l.SetTextSize(ht);
3009  l.SetTitle(theGraph->GetTitle());
3010  // Adjustment in case the title has several lines (#splitline)
3011  ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
3012  Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
3013  wt = TMath::Min(0.7, 0.02+wndc);
3014  }
3015  if (title) {
3016  TText *t0 = (TText*)title->GetLine(0);
3017  if (t0) {
3018  if (!strcmp(t0->GetTitle(),theGraph->GetTitle())) return;
3019  t0->SetTitle(theGraph->GetTitle());
3020  if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
3021  }
3022  return;
3023  }
3024 
3025  Int_t talh = gStyle->GetTitleAlign()/10;
3026  if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
3027  Int_t talv = gStyle->GetTitleAlign()%10;
3028  if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
3029 
3030  Double_t xpos, ypos;
3031  xpos = gStyle->GetTitleX();
3032  ypos = gStyle->GetTitleY();
3033 
3034  if (talh == 2) xpos = xpos-wt/2.;
3035  if (talh == 3) xpos = xpos-wt;
3036  if (talv == 2) ypos = ypos+ht/2.;
3037  if (talv == 1) ypos = ypos+ht;
3038 
3039  TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
3040 
3041  // Box with the histogram title.
3043  ptitle->SetFillStyle(gStyle->GetTitleStyle());
3044  ptitle->SetName("title");
3047  ptitle->SetTextFont(gStyle->GetTitleFont(""));
3048  if (gStyle->GetTitleFont("")%10 > 2)
3049  ptitle->SetTextSize(gStyle->GetTitleFontSize());
3050  ptitle->AddText(theGraph->GetTitle());
3051  ptitle->SetBit(kCanDelete);
3052  ptitle->Draw();
3053  ptitle->Paint();
3054 }
3055 
3056 
3057 ////////////////////////////////////////////////////////////////////////////////
3058 /// Paint this graphQQ. No options for the time being.
3059 
3060 void TGraphPainter::PaintGraphQQ(TGraph *theGraph, Option_t *option)
3062 
3063  TGraphQQ *theGraphQQ = (TGraphQQ*) theGraph;
3064 
3065  Double_t *theX = theGraphQQ->GetX();
3066  Double_t theXq1 = theGraphQQ->GetXq1();
3067  Double_t theXq2 = theGraphQQ->GetXq2();
3068  Double_t theYq1 = theGraphQQ->GetYq1();
3069  Double_t theYq2 = theGraphQQ->GetYq2();
3070  TF1 *theF = theGraphQQ->GetF();
3071 
3072  if (!theX){
3073  Error("TGraphQQ::Paint", "2nd dataset or theoretical function not specified");
3074  return;
3075  }
3076 
3077  if (theF){
3078  theGraphQQ->GetXaxis()->SetTitle("theoretical quantiles");
3079  theGraphQQ->GetYaxis()->SetTitle("data quantiles");
3080  }
3081 
3082  PaintGraphSimple(theGraph,option);
3083 
3084  Double_t xmin = gPad->GetUxmin();
3085  Double_t xmax = gPad->GetUxmax();
3086  Double_t ymin = gPad->GetUymin();
3087  Double_t ymax = gPad->GetUymax();
3088  Double_t yxmin, xymin, yxmax, xymax;
3089  Double_t xqmin = TMath::Max(xmin, theXq1);
3090  Double_t xqmax = TMath::Min(xmax, theXq2);
3091  Double_t yqmin = TMath::Max(ymin, theYq1);
3092  Double_t yqmax = TMath::Min(ymax, theYq2);
3093 
3094  TLine line1, line2, line3;
3095  line1.SetLineStyle(2);
3096  line3.SetLineStyle(2);
3097  yxmin = (theYq2-theYq1)*(xmin-theXq1)/(theXq2-theXq1) + theYq1;
3098  if (yxmin < ymin){
3099  xymin = (theXq2-theXq1)*(ymin-theYq1)/(theYq2-theYq1) + theXq1;
3100  line1.PaintLine(xymin, ymin, xqmin, yqmin);
3101  }
3102  else
3103  line1.PaintLine(xmin, yxmin, xqmin, yqmin);
3104 
3105  line2.PaintLine(xqmin, yqmin, xqmax, yqmax);
3106 
3107  yxmax = (theYq2-theYq1)*(xmax-theXq1)/(theXq2-theXq1) + theYq1;
3108  if (yxmax > ymax){
3109  xymax = (theXq2-theXq1)*(ymax-theYq1)/(theYq2-theYq1) + theXq1;
3110  line3.PaintLine(xqmax, yqmax, xymax, ymax);
3111  }
3112  else
3113  line3.PaintLine(xqmax, yqmax, xmax, yxmax);
3114 }
3115 
3116 
3117 ////////////////////////////////////////////////////////////////////////////////
3118 /// Paint a simple graph, without errors bars.
3119 
3120 void TGraphPainter::PaintGraphSimple(TGraph *theGraph, Option_t *option)
3122 
3123  if (strstr(option,"H") || strstr(option,"h")) {
3124  PaintGrapHist(theGraph, theGraph->GetN(), theGraph->GetX(), theGraph->GetY(), option);
3125  } else {
3126  PaintGraph(theGraph, theGraph->GetN(), theGraph->GetX(), theGraph->GetY(), option);
3127  }
3128 
3129  // Paint associated objects in the list of functions (for instance
3130  // the fit function).
3131  TList *functions = theGraph->GetListOfFunctions();
3132  if (!functions) return;
3133  TObjOptLink *lnk = (TObjOptLink*)functions->FirstLink();
3134  TObject *obj;
3135 
3136  while (lnk) {
3137  obj = lnk->GetObject();
3138  TVirtualPad *padsave = gPad;
3139  if (obj->InheritsFrom(TF1::Class())) {
3140  if (obj->TestBit(TF1::kNotDraw) == 0) obj->Paint("lsame");
3141  } else {
3142  obj->Paint(lnk->GetOption());
3143  }
3144  lnk = (TObjOptLink*)lnk->Next();
3145  padsave->cd();
3146  }
3147  return;
3148 }
3149 
3150 
3151 ////////////////////////////////////////////////////////////////////////////////
3152 /// Paint a polyline with hatches on one side showing an exclusion zone. x and y
3153 /// are the the vectors holding the polyline and n the number of points in the
3154 /// polyline and `w` the width of the hatches. `w` can be negative.
3155 /// This method is not meant to be used directly. It is called automatically
3156 /// according to the line style convention.
3157 
3158 void TGraphPainter::PaintPolyLineHatches(TGraph *theGraph, Int_t n, const Double_t *x, const Double_t *y)
3160 
3161  Int_t i,j,nf;
3162  Double_t w = (theGraph->GetLineWidth()/100)*0.005;
3163 
3164  Double_t *xf = new Double_t[2*n];
3165  Double_t *yf = new Double_t[2*n];
3166  Double_t *xt = new Double_t[n];
3167  Double_t *yt = new Double_t[n];
3168  Double_t x1, x2, y1, y2, x3, y3, xm, ym, a, a1, a2, a3;
3169 
3170  // Compute the gPad coordinates in TRUE normalized space (NDC)
3171  Int_t ix1,iy1,ix2,iy2;
3172  Int_t iw = gPad->GetWw();
3173  Int_t ih = gPad->GetWh();
3174  Double_t x1p,y1p,x2p,y2p;
3175  gPad->GetPadPar(x1p,y1p,x2p,y2p);
3176  ix1 = (Int_t)(iw*x1p);
3177  iy1 = (Int_t)(ih*y1p);
3178  ix2 = (Int_t)(iw*x2p);
3179  iy2 = (Int_t)(ih*y2p);
3180  Double_t wndc = TMath::Min(1.,(Double_t)iw/(Double_t)ih);
3181  Double_t hndc = TMath::Min(1.,(Double_t)ih/(Double_t)iw);
3182  Double_t rh = hndc/(Double_t)ih;
3183  Double_t rw = wndc/(Double_t)iw;
3184  Double_t x1ndc = (Double_t)ix1*rw;
3185  Double_t y1ndc = (Double_t)iy1*rh;
3186  Double_t x2ndc = (Double_t)ix2*rw;
3187  Double_t y2ndc = (Double_t)iy2*rh;
3188 
3189  // Ratios to convert user space in TRUE normalized space (NDC)
3190  Double_t rx1,ry1,rx2,ry2;
3191  gPad->GetRange(rx1,ry1,rx2,ry2);
3192  Double_t rx = (x2ndc-x1ndc)/(rx2-rx1);
3193  Double_t ry = (y2ndc-y1ndc)/(ry2-ry1);
3194 
3195  // The first part of the filled area is made of the graph points.
3196  // Make sure that two adjacent points are different.
3197  xf[0] = rx*(x[0]-rx1)+x1ndc;
3198  yf[0] = ry*(y[0]-ry1)+y1ndc;
3199  nf = 0;
3200  for (i=1; i<n; i++) {
3201  if (x[i]==x[i-1] && y[i]==y[i-1]) continue;
3202  nf++;
3203  xf[nf] = rx*(x[i]-rx1)+x1ndc;
3204  if (xf[i]==xf[i-1]) xf[i] += 0.000001; // add an epsilon to avoid exact vertical lines.
3205  yf[nf] = ry*(y[i]-ry1)+y1ndc;
3206  }
3207 
3208  // For each graph points a shifted points is computed to build up
3209  // the second part of the filled area. First and last points are
3210  // treated as special cases, outside of the loop.
3211  if (xf[1]==xf[0]) {
3212  a = TMath::PiOver2();
3213  } else {
3214  a = TMath::ATan((yf[1]-yf[0])/(xf[1]-xf[0]));
3215  }
3216  if (xf[0]<=xf[1]) {
3217  xt[0] = xf[0]-w*TMath::Sin(a);
3218  yt[0] = yf[0]+w*TMath::Cos(a);
3219  } else {
3220  xt[0] = xf[0]+w*TMath::Sin(a);
3221  yt[0] = yf[0]-w*TMath::Cos(a);
3222  }
3223 
3224  if (xf[nf]==xf[nf-1]) {
3225  a = TMath::PiOver2();
3226  } else {
3227  a = TMath::ATan((yf[nf]-yf[nf-1])/(xf[nf]-xf[nf-1]));
3228  }
3229  if (xf[nf]>=xf[nf-1]) {
3230  xt[nf] = xf[nf]-w*TMath::Sin(a);
3231  yt[nf] = yf[nf]+w*TMath::Cos(a);
3232  } else {
3233  xt[nf] = xf[nf]+w*TMath::Sin(a);
3234  yt[nf] = yf[nf]-w*TMath::Cos(a);
3235  }
3236 
3237  Double_t xi0,yi0,xi1,yi1,xi2,yi2;
3238  for (i=1; i<nf; i++) {
3239  xi0 = xf[i];
3240  yi0 = yf[i];
3241  xi1 = xf[i+1];
3242  yi1 = yf[i+1];
3243  xi2 = xf[i-1];
3244  yi2 = yf[i-1];
3245  if (xi1==xi0) {
3246  a1 = TMath::PiOver2();
3247  } else {
3248  a1 = TMath::ATan((yi1-yi0)/(xi1-xi0));
3249  }
3250  if (xi1<xi0) a1 = a1+3.14159;
3251  if (xi2==xi0) {
3252  a2 = TMath::PiOver2();
3253  } else {
3254  a2 = TMath::ATan((yi0-yi2)/(xi0-xi2));
3255  }
3256  if (xi0<xi2) a2 = a2+3.14159;
3257  x1 = xi0-w*TMath::Sin(a1);
3258  y1 = yi0+w*TMath::Cos(a1);
3259  x2 = xi0-w*TMath::Sin(a2);
3260  y2 = yi0+w*TMath::Cos(a2);
3261  xm = (x1+x2)*0.5;
3262  ym = (y1+y2)*0.5;
3263  if (xm==xi0) {
3264  a3 = TMath::PiOver2();
3265  } else {
3266  a3 = TMath::ATan((ym-yi0)/(xm-xi0));
3267  }
3268  x3 = xi0-w*TMath::Sin(a3+1.57079);
3269  y3 = yi0+w*TMath::Cos(a3+1.57079);
3270  // Rotate (x3,y3) by PI around (xi0,yi0) if it is not on the (xm,ym) side.
3271  if ((xm-xi0)*(x3-xi0)<0 && (ym-yi0)*(y3-yi0)<0) {
3272  x3 = 2*xi0-x3;
3273  y3 = 2*yi0-y3;
3274  }
3275  if ((xm==x1) && (ym==y1)) {
3276  x3 = xm;
3277  y3 = ym;
3278  }
3279  xt[i] = x3;
3280  yt[i] = y3;
3281  }
3282 
3283  // Close the polygon if the first and last points are the same
3284  if (xf[nf]==xf[0] && yf[nf]==yf[0]) {
3285  xm = (xt[nf]+xt[0])*0.5;
3286  ym = (yt[nf]+yt[0])*0.5;
3287  if (xm==xf[0]) {
3288  a3 = TMath::PiOver2();
3289  } else {
3290  a3 = TMath::ATan((ym-yf[0])/(xm-xf[0]));
3291  }
3292  x3 = xf[0]+w*TMath::Sin(a3+1.57079);
3293  y3 = yf[0]-w*TMath::Cos(a3+1.57079);
3294  if ((xm-xf[0])*(x3-xf[0])<0 && (ym-yf[0])*(y3-yf[0])<0) {
3295  x3 = 2*xf[0]-x3;
3296  y3 = 2*yf[0]-y3;
3297  }
3298  xt[nf] = x3;
3299  xt[0] = x3;
3300  yt[nf] = y3;
3301  yt[0] = y3;
3302  }
3303 
3304  // Find the crossing segments and remove the useless ones
3305  Double_t xc, yc, c1, b1, c2, b2;
3306  Bool_t cross = kFALSE;
3307  Int_t nf2 = nf;
3308  for (i=nf2; i>0; i--) {
3309  for (j=i-1; j>0; j--) {
3310  if (xt[i-1]==xt[i] || xt[j-1]==xt[j]) continue;
3311  c1 = (yt[i-1]-yt[i])/(xt[i-1]-xt[i]);
3312  b1 = yt[i]-c1*xt[i];
3313  c2 = (yt[j-1]-yt[j])/(xt[j-1]-xt[j]);
3314  b2 = yt[j]-c2*xt[j];
3315  if (c1 != c2) {
3316  xc = (b2-b1)/(c1-c2);
3317  yc = c1*xc+b1;
3318  if (xc>TMath::Min(xt[i],xt[i-1]) && xc<TMath::Max(xt[i],xt[i-1]) &&
3319  xc>TMath::Min(xt[j],xt[j-1]) && xc<TMath::Max(xt[j],xt[j-1]) &&
3320  yc>TMath::Min(yt[i],yt[i-1]) && yc<TMath::Max(yt[i],yt[i-1]) &&
3321  yc>TMath::Min(yt[j],yt[j-1]) && yc<TMath::Max(yt[j],yt[j-1])) {
3322  nf++; xf[nf] = xt[i]; yf[nf] = yt[i];
3323  nf++; xf[nf] = xc ; yf[nf] = yc;
3324  i = j;
3325  cross = kTRUE;
3326  break;
3327  } else {
3328  continue;
3329  }
3330  } else {
3331  continue;
3332  }
3333  }
3334  if (!cross) {
3335  nf++;
3336  xf[nf] = xt[i];
3337  yf[nf] = yt[i];
3338  }
3339  cross = kFALSE;
3340  }
3341  nf++; xf[nf] = xt[0]; yf[nf] = yt[0];
3342 
3343  // NDC to user coordinates
3344  for (i=0; i<nf+1; i++) {
3345  xf[i] = (1/rx)*(xf[i]-x1ndc)+rx1;
3346  yf[i] = (1/ry)*(yf[i]-y1ndc)+ry1;
3347  }
3348 
3349  // Draw filled area
3350  gPad->PaintFillArea(nf+1,xf,yf);
3351  theGraph->TAttLine::Modify(); // In case of PaintFillAreaHatches
3352 
3353  delete [] xf;
3354  delete [] yf;
3355  delete [] xt;
3356  delete [] yt;
3357 }
3358 
3359 
3360 ////////////////////////////////////////////////////////////////////////////////
3361 /// Paint the statistics box with the fit info.
3362 
3363 void TGraphPainter::PaintStats(TGraph *theGraph, TF1 *fit)
3365 
3366  Int_t dofit;
3367  TPaveStats *stats = 0;
3368  TList *functions = theGraph->GetListOfFunctions();
3369  TIter next(functions);
3370  TObject *obj;
3371  while ((obj = next())) {
3372  if (obj->InheritsFrom(TPaveStats::Class())) {
3373  stats = (TPaveStats*)obj;
3374  break;
3375  }
3376  }
3377 
3378  if (stats) dofit = stats->GetOptFit();
3379  else dofit = gStyle->GetOptFit();
3380 
3381  if (!dofit) fit = 0;
3382  if (!fit) return;
3383  if (dofit == 1) dofit = 111;
3384  Int_t nlines = 0;
3385  Int_t print_fval = dofit%10;
3386  Int_t print_ferrors = (dofit/10)%10;
3387  Int_t print_fchi2 = (dofit/100)%10;
3388  Int_t print_fprob = (dofit/1000)%10;
3389  Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
3390  if (fit) nlinesf += fit->GetNpar();
3391  Bool_t done = kFALSE;
3392  Double_t statw = 1.8*gStyle->GetStatW();
3393  Double_t stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
3394  if (stats) {
3395  stats->Clear();
3396  done = kTRUE;
3397  } else {
3398  stats = new TPaveStats(
3399  gStyle->GetStatX()-statw,
3400  gStyle->GetStatY()-stath,
3401  gStyle->GetStatX(),
3402  gStyle->GetStatY(),"brNDC");
3403 
3404  stats->SetParent(functions);
3405  stats->SetOptFit(dofit);
3406  stats->SetOptStat(0);
3407  stats->SetFillColor(gStyle->GetStatColor());
3408  stats->SetFillStyle(gStyle->GetStatStyle());
3410  stats->SetTextFont(gStyle->GetStatFont());
3411  if (gStyle->GetStatFont()%10 > 2)
3412  stats->SetTextSize(gStyle->GetStatFontSize());
3413  stats->SetFitFormat(gStyle->GetFitFormat());
3414  stats->SetStatFormat(gStyle->GetStatFormat());
3415  stats->SetName("stats");
3416 
3418  stats->SetTextAlign(12);
3419  stats->SetBit(kCanDelete);
3420  stats->SetBit(kMustCleanup);
3421  }
3422 
3423  char t[64];
3424  char textstats[50];
3425  Int_t ndf = fit->GetNDF();
3426  snprintf(textstats,50,"#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
3427  snprintf(t,64,textstats,(Float_t)fit->GetChisquare());
3428  if (print_fchi2) stats->AddText(t);
3429  if (print_fprob) {
3430  snprintf(textstats,50,"Prob = %s%s","%",stats->GetFitFormat());
3431  snprintf(t,64,textstats,(Float_t)TMath::Prob(fit->GetChisquare(),ndf));
3432  stats->AddText(t);
3433  }
3434  if (print_fval || print_ferrors) {
3435  for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
3436  if (print_ferrors) {
3437  snprintf(textstats,50,"%-8s = %s%s #pm %s%s ",fit->GetParName(ipar),"%",stats->GetFitFormat(),"%",stats->GetFitFormat());
3438  snprintf(t,64,textstats,(Float_t)fit->GetParameter(ipar)
3439  ,(Float_t)fit->GetParError(ipar));
3440  } else {
3441  snprintf(textstats,50,"%-8s = %s%s ",fit->GetParName(ipar),"%",stats->GetFitFormat());
3442  snprintf(t,64,textstats,(Float_t)fit->GetParameter(ipar));
3443  }
3444  t[63] = 0;
3445  stats->AddText(t);
3446  }
3447  }
3448 
3449  if (!done) functions->Add(stats);
3450  stats->Paint();
3451 }
3452 
3453 
3454 ////////////////////////////////////////////////////////////////////////////////
3455 /// Smooth a curve given by N points.
3456 ///
3457 /// The original code is from an underlaying routine for Draw based on the
3458 /// CERN GD3 routine TVIPTE:
3459 ///
3460 /// Author - Marlow etc. Modified by - P. Ward Date - 3.10.1973
3461 ///
3462 /// This method draws a smooth tangentially continuous curve through
3463 /// the sequence of data points P(I) I=1,N where P(I)=(X(I),Y(I)).
3464 /// The curve is approximated by a polygonal arc of short vectors.
3465 /// The data points can represent open curves, P(1) != P(N) or closed
3466 /// curves P(2) == P(N). If a tangential discontinuity at P(I) is
3467 /// required, then set P(I)=P(I+1). Loops are also allowed.
3468 ///
3469 /// Reference Marlow and Powell, Harwell report No.R.7092.1972
3470 /// MCCONALOGUE, Computer Journal VOL.13, NO4, NOV1970P p392 6
3471 ///
3472 /// - npoints : Number of data points.
3473 /// - x : Abscissa
3474 /// - y : Ordinate
3475 
3476 void TGraphPainter::Smooth(TGraph *theGraph, Int_t npoints, Double_t *x, Double_t *y, Int_t drawtype)
3478 
3479  Int_t i, k, kp, km, npointsMax, banksize, n2, npt;
3480  Int_t maxiterations, finished;
3481  Int_t jtype, ktype, closed;
3482  Double_t sxmin, sxmax, symin, symax;
3483  Double_t delta;
3484  Double_t xorg, yorg;
3485  Double_t ratio_signs, xratio, yratio;
3486  Int_t flgic, flgis;
3487  Int_t iw, loptx;
3488  Double_t p1, p2, p3, p4, p5, p6;
3489  Double_t w1, w2, w3;
3490  Double_t a, b, c, r, s=0.0, t, z;
3491  Double_t co, so, ct, st, ctu, stu, xnt;
3492  Double_t dx1, dy1, dx2, dy2, dk1, dk2;
3493  Double_t xo, yo, dx, dy, xt, yt;
3494  Double_t xa, xb, ya, yb;
3495  Double_t u1, u2, u3, tj;
3496  Double_t cc, err;
3497  Double_t sb, sth;
3498  Double_t wsign, tsquare, tcube;
3499  c = t = co = so = ct = st = ctu = stu = dx1 = dy1 = dx2 = dy2 = 0;
3500  xt = yt = xa = xb = ya = yb = u1 = u2 = u3 = tj = sb = 0;
3501 
3502  npointsMax = npoints*10;
3503  n2 = npointsMax-2;
3504  banksize = n2;
3505 
3506  Double_t *qlx = new Double_t[npointsMax];
3507  Double_t *qly = new Double_t[npointsMax];
3508  if (!qlx || !qly) {
3509  Error("Smooth", "not enough space in memory");
3510  return;
3511  }
3512 
3513  // Decode the type of curve (drawtype).
3514 
3515  loptx = kFALSE;
3516  jtype = (drawtype%1000)-10;
3517  if (jtype > 0) { ktype = jtype; loptx = kTRUE; }
3518  else ktype = drawtype%1000;
3519 
3520  Double_t ruxmin = gPad->GetUxmin();
3521  Double_t ruymin = gPad->GetUymin();
3522  if (ktype == 3) {
3523  xorg = ruxmin;
3524  yorg = ruymin;
3525  } else {
3526  xorg = TMath::Max((Double_t)0,ruxmin);
3527  yorg = TMath::Min(TMath::Max((Double_t)0,ruymin),gPad->GetUymax());
3528  }
3529 
3530  // delta is the accuracy required in constructing the curve.
3531  // If it is zero then the routine calculates a value otherwise
3532  // it uses this value. (default is 0.0)
3533 
3534  delta = 0.00055;
3535  maxiterations = 20;
3536 
3537  // Scale data to the range 0-ratio_signs in X, 0-1 in Y
3538  // where ratio_signs is the ratio between the number of changes
3539  // of sign in Y divided by the number of changes of sign in X
3540 
3541  sxmin = x[0];
3542  sxmax = x[0];
3543  symin = y[0];
3544  symax = y[0];
3545  Double_t six = 1;
3546  Double_t siy = 1;
3547  for (i=1;i<npoints;i++) {
3548  if (i > 1) {
3549  if ((x[i]-x[i-1])*(x[i-1]-x[i-2]) < 0) six++;
3550  if ((y[i]-y[i-1])*(y[i-1]-y[i-2]) < 0) siy++;
3551  }
3552  if (x[i] < sxmin) sxmin = x[i];
3553  if (x[i] > sxmax) sxmax = x[i];
3554  if (y[i] < symin) symin = y[i];
3555  if (y[i] > symax) symax = y[i];
3556  }
3557  closed = 0;
3558  Double_t dx1n = TMath::Abs(x[npoints-1]-x[0]);
3559  Double_t dy1n = TMath::Abs(y[npoints-1]-y[0]);
3560  if (dx1n < 0.01*(sxmax-sxmin) && dy1n < 0.01*(symax-symin)) closed = 1;
3561  if (sxmin == sxmax) {
3562  xratio = 1;
3563  } else {
3564  if (six > 1) ratio_signs = siy/six;
3565  else ratio_signs = 20;
3566  xratio = ratio_signs/(sxmax-sxmin);
3567  }
3568  if (symin == symax) yratio = 1;
3569  else yratio = 1/(symax-symin);
3570 
3571  qlx[0] = x[0];
3572  qly[0] = y[0];
3573  for (i=0;i<npoints;i++) {
3574  x[i] = (x[i]-sxmin)*xratio;
3575  y[i] = (y[i]-symin)*yratio;
3576  }
3577 
3578  // "finished" is minus one if we must draw a straight line from P(k-1)
3579  // to P(k). "finished" is one if the last call to PaintPolyLine has < n2
3580  // points. "finished" is zero otherwise. npt counts the X and Y
3581  // coordinates in work . When npt=n2 a call to IPL is made.
3582 
3583  finished = 0;
3584  npt = 1;
3585  k = 1;
3586 
3587  // Convert coordinates back to original system
3588 
3589  // Separate the set of data points into arcs P(k-1),P(k).
3590  // Calculate the direction cosines. first consider whether
3591  // there is a continuous tangent at the endpoints.
3592 
3593  if (!closed) {
3594  if (x[0] != x[npoints-1] || y[0] != y[npoints-1]) goto L40;
3595  if (x[npoints-2] == x[npoints-1] && y[npoints-2] == y[npoints-1]) goto L40;
3596  if (x[0] == x[1] && y[0] == y[1]) goto L40;
3597  }
3598  flgic = kFALSE;
3599  flgis = kTRUE;
3600 
3601  // flgic is true if the curve is open and false if it is closed.
3602  // flgis is true in the main loop, but is false if there is
3603  // a deviation from the main loop.
3604 
3605  km = npoints - 1;
3606 
3607  // Calculate direction cosines at P(1) using P(N-1),P(1),P(2).
3608 
3609  goto L100;
3610 L40:
3611  flgic = kTRUE;
3612  flgis = kFALSE;
3613 
3614  // Skip excessive consecutive equal points.
3615 
3616 L50:
3617  if (k >= npoints) {
3618  finished = 1; // Prepare to clear out remaining short vectors before returning
3619  if (npt > 1) goto L310;
3620  goto L390;
3621  }
3622  k++;
3623  if (x[k-1] == x[k-2] && y[k-1] == y[k-2]) goto L50;
3624 L60:
3625  km = k-1;
3626  if (k > npoints) {
3627  finished = 1; // Prepare to clear out remaining short vectors before returning
3628  if (npt > 1) goto L310;
3629  goto L390;
3630  }
3631  if (k < npoints) goto L90;
3632  if (!flgic) { kp = 2; goto L130;}
3633 
3634 L80:
3635  if (flgis) goto L150;
3636 
3637  // Draw a straight line from P(k-1) to P(k).
3638 
3639  finished = -1;
3640  goto L170;
3641 
3642  // Test whether P(k) is a cusp.
3643 
3644 L90:
3645  if (x[k-1] == x[k] && y[k-1] == y[k]) goto L80;
3646 L100:
3647  kp = k+1;
3648  goto L130;
3649 
3650  // Branch if the next section of the curve begins at a cusp.
3651 
3652 L110:
3653  if (!flgis) goto L50;
3654 
3655  // Carry forward the direction cosines from the previous arc.
3656 
3657 L120:
3658  co = ct;
3659  so = st;
3660  k++;
3661  goto L60;
3662 
3663  // Calculate the direction cosines at P(k). If k=1 then
3664  // N-1 is used for k-1. If k=N then 2 is used for k+1.
3665  // direction cosines at P(k) obtained from P(k-1),P(k),P(k+1).
3666 
3667 L130:
3668  dx1 = x[k-1] - x[km-1];
3669  dy1 = y[k-1] - y[km-1];
3670  dk1 = dx1*dx1 + dy1*dy1;
3671  dx2 = x[kp-1] - x[k-1];
3672  dy2 = y[kp-1] - y[k-1];
3673  dk2 = dx2*dx2 + dy2*dy2;
3674  ctu = dx1*dk2 + dx2*dk1;
3675  stu = dy1*dk2 + dy2*dk1;
3676  xnt = ctu*ctu + stu*stu;
3677 
3678  // If both ctu and stu are zero,then default.This can
3679  // occur when P(k)=P(k+1). I.E. A loop.
3680 
3681  if (xnt < 1.E-25) {
3682  ctu = dy1;
3683  stu =-dx1;
3684  xnt = dk1;
3685  }
3686  // Normalise direction cosines.
3687 
3688  ct = ctu/TMath::Sqrt(xnt);
3689  st = stu/TMath::Sqrt(xnt);
3690  if (flgis) goto L160;
3691 
3692  // Direction cosines at P(k-1) obtained from P(k-1),P(k),P(k+1).
3693 
3694  w3 = 2*(dx1*dy2-dx2*dy1);
3695  co = ctu+w3*dy1;
3696  so = stu-w3*dx1;
3697  xnt = 1/TMath::Sqrt(co*co+so*so);
3698  co = co*xnt;
3699  so = so*xnt;
3700  flgis = kTRUE;
3701  goto L170;
3702 
3703  // Direction cosines at P(k) obtained from P(k-2),P(k-1),P(k).
3704 
3705 L150:
3706  w3 = 2*(dx1*dy2-dx2*dy1);
3707  ct = ctu-w3*dy2;
3708  st = stu+w3*dx2;
3709  xnt = 1/TMath::Sqrt(ct*ct+st*st);
3710  ct = ct*xnt;
3711  st = st*xnt;
3712  flgis = kFALSE;
3713  goto L170;
3714 L160:
3715  if (k <= 1) goto L120;
3716 
3717  // For the arc between P(k-1) and P(k) with direction cosines co,
3718  // so and ct,st respectively, calculate the coefficients of the
3719  // parametric cubic represented by X(t) and Y(t) where
3720  // X(t)=xa*t**3 + xb*t**2 + co*t + xo
3721  // Y(t)=ya*t**3 + yb*t**2 + so*t + yo
3722 
3723 L170:
3724  xo = x[k-2];
3725  yo = y[k-2];
3726  dx = x[k-1] - xo;
3727  dy = y[k-1] - yo;
3728 
3729  // Initialise the values of X(TI),Y(TI) in xt and yt respectively.
3730 
3731  xt = xo;
3732  yt = yo;
3733  if (finished < 0) { // Draw a straight line between (xo,yo) and (xt,yt)
3734  xt += dx;
3735  yt += dy;
3736  goto L300;
3737  }
3738  c = dx*dx+dy*dy;
3739  a = co+ct;
3740  b = so+st;
3741  r = dx*a+dy*b;
3742  t = c*6/(TMath::Sqrt(r*r+2*(7-co*ct-so*st)*c)+r);
3743  tsquare = t*t;
3744  tcube = t*tsquare;
3745  xa = (a*t-2*dx)/tcube;
3746  xb = (3*dx-(co+a)*t)/tsquare;
3747  ya = (b*t-2*dy)/tcube;
3748  yb = (3*dy-(so+b)*t)/tsquare;
3749 
3750  // If the curve is close to a straight line then use a straight
3751  // line between (xo,yo) and (xt,yt).
3752 
3753  if (.75*TMath::Max(TMath::Abs(dx*so-dy*co),TMath::Abs(dx*st-dy*ct)) <= delta) {
3754  finished = -1;
3755  xt += dx;
3756  yt += dy;
3757  goto L300;
3758  }
3759 
3760  // Calculate a set of values 0 == t(0).LTCT(1) < ... < t(M)=TC
3761  // such that polygonal arc joining X(t(J)),Y(t(J)) (J=0,1,..M)
3762  // is within the required accuracy of the curve
3763 
3764  tj = 0;
3765  u1 = ya*xb-yb*xa;
3766  u2 = yb*co-xb*so;
3767  u3 = so*xa-ya*co;
3768 
3769  // Given t(J), calculate t(J+1). The values of X(t(J)),
3770  // Y(t(J)) t(J) are contained in xt,yt and tj respectively.
3771 
3772 L180:
3773  s = t - tj;
3774  iw = -2;
3775 
3776  // Define iw here later.
3777 
3778  p1 = (2*u1)*tj-u3;
3779  p2 = (u1*tj-u3)*3*tj+u2;
3780  p3 = 3*tj*ya+yb;
3781  p4 = (p3+yb)*tj+so;
3782  p5 = 3*tj*xa+xb;
3783  p6 = (p5+xb)*tj+co;
3784 
3785  // Test D(tj,THETA). A is set to (Y(tj+s)-Y(tj))/s.b is
3786  // set to (X(tj+s)-X(tj))/s.
3787 
3788  cc = 0.8209285;
3789  err = 0.1209835;
3790 L190:
3791  iw -= 2;
3792 L200:
3793  a = (s*ya+p3)*s+p4;
3794  b = (s*xa+p5)*s+p6;
3795 
3796  // Set z to PSI(D/delta)-cc.
3797 
3798  w1 = -s*(s*u1+p1);
3799  w2 = s*s*u1-p2;
3800  w3 = 1.5*w1+w2;
3801 
3802  // Set the estimate of (THETA-tj)/s.Then set the numerator
3803  // of the expression (EQUATION 4.4)/s. Then set the square
3804  // of D(tj,tj+s)/delta. Then replace z by PSI(D/delta)-cc.
3805 
3806  if (w3 > 0) wsign = TMath::Abs(w1);
3807  else wsign = -TMath::Abs(w1);
3808  sth = 0.5+wsign/(3.4*TMath::Abs(w1)+5.2*TMath::Abs(w3));
3809  z = s*sth*(s-s*sth)*(w1*sth+w1+w2);
3810  z = z*z/((a*a+b*b)*(delta*delta));
3811  z = (z+2.642937)*z/((.3715652*z+3.063444)*z+.2441889)-cc;
3812 
3813  // Branch if z has been calculated
3814 
3815  if (iw > 0) goto L250;
3816  if (z > err) goto L240;
3817  goto L220;
3818 L210:
3819  iw -= 2;
3820 L220:
3821  if (iw+2 == 0) goto L190;
3822  if (iw+2 > 0) goto L290;
3823 
3824  // Last part of arc.
3825 
3826 L230:
3827  xt = x[k-1];
3828  yt = y[k-1];
3829  s = 0;
3830  goto L300;
3831 
3832  // z(s). find a value of s where 0 <= s <= sb such that
3833  // TMath::Abs(z(s)) < err
3834 
3835 L240:
3836  kp = 0;
3837  c = z;
3838  sb = s;
3839 L250:
3840  theGraph->Zero(kp,0,sb,err,s,z,maxiterations);
3841  if (kp == 2) goto L210;
3842  if (kp > 2) {
3843  Error("Smooth", "Attempt to plot outside plot limits");
3844  goto L230;
3845  }
3846  if (iw > 0) goto L200;
3847 
3848  // Set z=z(s) for s=0.
3849 
3850  if (iw < 0) {
3851  z = -cc;
3852  iw = 0;
3853  goto L250;
3854  }
3855 
3856  // Set z=z(s) for s=sb.
3857 
3858  z = c;
3859  iw = 1;
3860  goto L250;
3861 
3862  // Update tj,xt and yt.
3863 
3864 L290:
3865  xt = xt + s*b;
3866  yt = yt + s*a;
3867  tj = s + tj;
3868 
3869  // Convert coordinates to original system
3870 
3871 L300:
3872  qlx[npt] = sxmin + xt/xratio;
3873  qly[npt] = symin + yt/yratio;
3874  npt++;
3875 
3876  // If a fill area must be drawn and if the banks LX and
3877  // LY are too small they are enlarged in order to draw
3878  // the filled area in one go.
3879 
3880  if (npt < banksize) goto L320;
3881  if (drawtype >= 1000 || ktype > 1) {
3882  Int_t newsize = banksize + n2;
3883  Double_t *qtemp = new Double_t[banksize];
3884  for (i=0;i<banksize;i++) qtemp[i] = qlx[i];
3885  delete [] qlx;
3886  qlx = new Double_t[newsize];
3887  for (i=0;i<banksize;i++) qlx[i] = qtemp[i];
3888  for (i=0;i<banksize;i++) qtemp[i] = qly[i];
3889  delete [] qly;
3890  qly = new Double_t[newsize];
3891  for (i=0;i<banksize;i++) qly[i] = qtemp[i];
3892  delete [] qtemp;
3893  banksize = newsize;
3894  goto L320;
3895  }
3896 
3897  // Draw the graph
3898 
3899 L310:
3900  if (drawtype >= 1000) {
3901  gPad->PaintFillArea(npt,qlx,qly, "B");
3902  } else {
3903  if (ktype > 1) {
3904  if (!loptx) {
3905  qlx[npt] = qlx[npt-1];
3906  qlx[npt+1] = qlx[0];
3907  qly[npt] = yorg;
3908  qly[npt+1] = yorg;
3909  } else {
3910  qlx[npt] = xorg;
3911  qlx[npt+1] = xorg;
3912  qly[npt] = qly[npt-1];
3913  qly[npt+1] = qly[0];
3914  }
3915  gPad->PaintFillArea(npt+2,qlx,qly);
3916  }
3917  if (TMath::Abs(theGraph->GetLineWidth())>99) PaintPolyLineHatches(theGraph, npt, qlx, qly);
3918  gPad->PaintPolyLine(npt,qlx,qly);
3919  }
3920  npt = 1;
3921  qlx[0] = sxmin + xt/xratio;
3922  qly[0] = symin + yt/yratio;
3923 L320:
3924  if (finished > 0) goto L390;
3925  if (finished < 0) { finished = 0; goto L110;}
3926  if (s > 0) goto L180;
3927  goto L110;
3928 
3929  // Convert coordinates back to original system
3930 
3931 L390:
3932  for (i=0;i<npoints;i++) {
3933  x[i] = sxmin + x[i]/xratio;
3934  y[i] = symin + y[i]/yratio;
3935  }
3936 
3937  delete [] qlx;
3938  delete [] qly;
3939 }
3940 
3941 ////////////////////////////////////////////////////////////////////////////////
3942 /// Static function to set `fgMaxPointsPerLine` for graph painting. When graphs
3943 /// are painted with lines, they are split into chunks of length `fgMaxPointsPerLine`.
3944 /// This allows to paint line with an "infinite" number of points. In some case
3945 /// this "chunks painting" technic may create artefacts at the chunk's boundaries.
3946 /// For instance when zooming deeply in a PDF file. To avoid this effect it might
3947 /// be necessary to increase the chunks' size using this function:
3948 /// `TGraphPainter::SetMaxPointsPerLine(20000)`.
3949 
3952  fgMaxPointsPerLine = maxp;
3953  if (maxp < 50) fgMaxPointsPerLine = 50;
3954 }
virtual Bool_t IsEditable() const
Definition: TGraph.h:163
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Double_t GetYq2() const
Definition: TGraphQQ.h:45
virtual Double_t GetMaximumStored() const
Definition: TH1.h:293
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:49
Color_t GetStatColor() const
Definition: TStyle.h:257
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition: TH1.cxx:7664
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition: TStyle.cxx:843
virtual void Paint(Option_t *option="")
Control routine to paint any kind of histograms.
Definition: TH1.cxx:5538
Color_t GetLabelColor(Option_t *axis="X") const
Return the label color number in the axis.
Definition: TStyle.cxx:743
float xmin
Definition: THbookFile.cxx:93
void SetOptFit(Int_t fit=1)
Set the fit option.
Definition: TPaveStats.cxx:294
Double_t * GetEX() const
Definition: TGraphErrors.h:68
virtual void SetName(const char *name="")
Definition: TPave.h:76
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
Definition: TPaveText.cxx:211
virtual Double_t * GetEX() const
Definition: TGraph.h:142
virtual void SetMaximum(Double_t maximum=-1111)
Definition: TH1.h:399
Float_t GetLabelSize(Option_t *axis="X") const
Return label size.
Definition: TStyle.cxx:779
static double p3(double t, double a, double b, double c, double d)
virtual Int_t DistancetoPrimitiveHelper(TGraph *theGraph, Int_t px, Int_t py)
Compute distance from point px,py to a graph.
virtual void SetLimits(Double_t xmin, Double_t xmax)
Definition: TAxis.h:160
virtual void ExecuteEventHelper(TGraph *theGraph, Int_t event, Int_t px, Int_t py)
Execute action corresponding to one event.
Double_t GetRMin()
Color_t GetTitleTextColor() const
Definition: TStyle.h:272
void PaintPolyLineHatches(TGraph *theGraph, Int_t n, const Double_t *x, const Double_t *y)
Paint a polyline with hatches on one side showing an exclusion zone.
void Smooth(TGraph *theGraph, Int_t npoints, Double_t *x, Double_t *y, Int_t drawtype)
Smooth a curve given by N points.
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Computes distance from point (px,py) to the object.
Definition: TObject.cxx:246
float Float_t
Definition: RtypesCore.h:53
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition: TH1.cxx:8051
return c
const char Option_t
Definition: RtypesCore.h:62
static Int_t fgMaxPointsPerLine
Definition: TGraphPainter.h:60
Color_t GetAxisColor(Option_t *axis="X") const
Return the axis color number in the axis.
Definition: TStyle.cxx:723
return c1
Definition: legend1.C:41
float ymin
Definition: THbookFile.cxx:93
void PaintCircle(Double_t x, Double_t y, Double_t r, Double_t phimin, Double_t phimax, Double_t theta)
This is simplified from TEllipse::PaintEllipse.
virtual Double_t * GetEYlow() const
Definition: TGraph.h:147
Create a Box.
Definition: TBox.h:36
double Axis_t
Definition: RtypesCore.h:72
virtual Double_t GetMinimumStored() const
Definition: TH1.h:297
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
R__EXTERN TStyle * gStyle
Definition: TStyle.h:418
#define mark(osub)
Definition: triangle.c:1206
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
THist< 1, float, THistStatContent, THistStatUncertainty > TH1F
Definition: THist.hxx:302
TH1 * h
Definition: legend2.C:5
virtual Double_t * GetEXhighd() const
Definition: TGraph.h:149
void Draw(Option_t *options="")
Draw Polargram.
TList * GetListOfFunctions() const
Definition: TGraph.h:127
TAxis * GetYaxis() const
Get y axis of the graph.
Definition: TGraph.cxx:1596
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
Definition: TPaveText.cxx:160
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1102
virtual Double_t * GetEY() const
Definition: TGraph.h:143
virtual void SetMinimum(Double_t minimum=-1111)
Definition: TH1.h:400
#define gROOT
Definition: TROOT.h:364
Float_t GetEndErrorSize() const
Definition: TStyle.h:187
Basic string class.
Definition: TString.h:137
tomato 1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:575
void PaintStats(TGraph *theGraph, TF1 *fit)
Paint the statistics box with the fit info.
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1089
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:44
void SetOptionAxis(Bool_t opt)
Definition: TGraphPolar.h:58
The histogram statistics painter class.
Definition: TPaveStats.h:20
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition: TF1.cxx:1642
int nbins[3]
void PaintGraphPolar(TGraph *theGraph, Option_t *option)
[Paint this TGraphPolar with its current attributes.]($GP04)
Float_t GetTitleY() const
Definition: TStyle.h:281
static void SetMaxPointsPerLine(Int_t maxp=50)
Static function to set fgMaxPointsPerLine for graph painting.
const char * Class
Definition: TXMLSetup.cxx:64
virtual ~TGraphPainter()
Destructor.
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
Double_t * gxworkl
const char * GetFitFormat() const
Definition: TStyle.h:201
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:41
Style_t GetLabelFont(Option_t *axis="X") const
Return label font.
Definition: TStyle.cxx:755
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition: TMath.cxx:624
Iterator of linked list.
Definition: TList.h:187
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:501
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
Int_t GetOptFit() const
Return the fit option.
Definition: TPaveStats.cxx:257
if object in a list can be deleted
Definition: TObject.h:56
This class allows to draw quantile-quantile plots.
Definition: TGraphQQ.h:20
TGraphPainter()
Default constructor.
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:37
Double_t GetTMin()
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition: TAttText.h:51
Int_t GetTitleAlign()
Definition: TStyle.h:270
double sqrt(double)
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition: TF1.cxx:1602
Double_t GetXmin() const
Definition: TAxis.h:139
static const double x2[5]
Double_t GetYsize()
Return size of the formula along Y in pad coordinates.
Definition: TLatex.cxx:2594
void PaintGraphAsymmErrors(TGraph *theGraph, Option_t *option)
Paint this TGraphAsymmErrors with its current attributes.
virtual void DrawPanelHelper(TGraph *theGraph)
Display a panel with all histogram drawing options.
Double_t x[n]
Definition: legend1.C:17
Float_t GetTitleFontSize() const
Definition: TStyle.h:274
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
TArrow * arrow
virtual void Paint(Option_t *option="")
Paint this pavetext with its current attributes.
Definition: TPaveText.cxx:392
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
Definition: TPaveStats.cxx:312
Double_t GetXq2() const
Definition: TGraphQQ.h:43
Double_t GetXq1() const
Definition: TGraphQQ.h:42
To draw Mathematical Formula.
Definition: TLatex.h:25
Int_t GetOptFit() const
Definition: TStyle.h:244
Double_t Log10(Double_t x)
Definition: TMath.h:529
void Zero(Int_t &k, Double_t AZ, Double_t BZ, Double_t E2, Double_t &X, Double_t &Y, Int_t maxiterations)
Find zero of a continuous function.
Definition: TGraph.cxx:2411
const Int_t kMaxPixel
Definition: GuiTypes.h:370
static double p2(double t, double a, double b, double c)
TGraphPolargram * GetPolargram()
Definition: TGraphPolar.h:48
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:38
virtual void Clear(Option_t *option="")
Clear all lines in this pavetext.
Definition: TPaveText.cxx:186
Base class for several text objects.
Definition: TText.h:33
Float_t GetStatX() const
Definition: TStyle.h:264
Float_t GetTitleX() const
Definition: TStyle.h:280
virtual void Show()
Bool_t IsInside(T xp, T yp, Int_t np, T *x, T *y)
Definition: TMath.h:1043
Float_t GetBarWidth() const
Definition: TStyle.h:185
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:59
Style_t GetStatStyle() const
Definition: TStyle.h:262
void SetLabelSize(Float_t labelsize)
Definition: TGaxis.h:114
Bool_t GetOptionAxis()
Definition: TGraphPolar.h:51
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition: TAttText.h:47
virtual void PaintGrapHist(TGraph *theGraph, Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
This is a service method used by THistPainter to paint 1D histograms.
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition: TObject.cxx:400
virtual char * GetObjectInfoHelper(TGraph *theGraph, Int_t px, Int_t py) const
A doubly linked list.
Definition: TList.h:47
virtual void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Draw this line with new coordinates.
Definition: TLine.cxx:380
virtual const char * GetParName(Int_t ipar) const
Definition: TF1.h:370
void PaintHelper(TGraph *theGraph, Option_t *option)
Paint a any kind of TGraph.
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to a line.
Definition: TH1.cxx:2589
virtual Double_t * GetEYhighd() const
Definition: TGraph.h:151
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:46
To draw a polar graph.
Definition: TGraphPolar.h:31
float ymax
Definition: THbookFile.cxx:93
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition: TGaxis.cxx:742
void PaintGraphErrors(TGraph *theGraph, Option_t *option)
[Paint this TGraphErrors with its current attributes.]($GP03)
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:557
TRandom2 r(17)
Double_t GetXsize()
Return size of the formula along X in pad coordinates.
Definition: TLatex.cxx:2507
Float_t GetTitleH() const
Definition: TStyle.h:283
void PaintGraphQQ(TGraph *theGraph, Option_t *option)
Paint this graphQQ. No options for the time being.
Double_t * gywork
Style_t GetStatFont() const
Definition: TStyle.h:260
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:42
Float_t GetStatY() const
Definition: TStyle.h:265
Float_t GetStatW() const
Definition: TStyle.h:266
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:488
void PaintGraphBentErrors(TGraph *theGraph, Option_t *option)
[Paint this TGraphBentErrors with its current attributes.]($GP03)
virtual void PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Float_t arrowsize=0.05, Option_t *option=">")
Draw this arrow.
Definition: TArrow.cxx:173
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
char * Form(const char *fmt,...)
A simple line.
Definition: TLine.h:33
Double_t E()
Definition: TMath.h:54
Int_t GetN() const
Definition: TGraph.h:133
TLine * l
Definition: textangle.C:4
To draw polar axis.
The axis painter class.
Definition: TGaxis.h:30
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:45
TAxis * GetYaxis()
Definition: TH1.h:325
Double_t * GetEY() const
Definition: TGraphErrors.h:69
Double_t * gyworkl
static double p1(double t, double a, double b)
float xmax
Definition: THbookFile.cxx:93
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Definition: TPaveStats.cxx:286
virtual const char * GetFitFormat() const
Definition: TPaveStats.h:37
Double_t GetTMax()
don&#39;t draw stats box
Definition: TH1.h:172
don&#39;t draw the histogram title
Definition: TH1.h:177
if object destructor must call RecursiveRemove()
Definition: TObject.h:57
virtual void PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option="")
Draw this box with new coordinates.
Definition: TBox.cxx:627
Double_t GetMaximum() const
Definition: TGraph.h:152
#define gVirtualX
Definition: TVirtualX.h:362
Define a Frame.
Definition: TFrame.h:21
Double_t Cos(Double_t)
Definition: TMath.h:424
Color_t GetTitleFillColor() const
Definition: TStyle.h:271
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition: TH1.cxx:7749
TAxis * GetXaxis() const
Get x axis of the graph.
Definition: TGraph.cxx:1586
Double_t * GetX() const
Definition: TGraph.h:140
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:39
Double_t Pi()
Definition: TMath.h:44
virtual Double_t * GetEXlowd() const
Definition: TGraph.h:148
void ComputeLogs(Int_t npoints, Int_t opt)
Compute the logarithm of global variables gxwork and gywork according to the value of Options and put...
Width_t GetTitleBorderSize() const
Definition: TStyle.h:275
Float_t GetTitleW() const
Definition: TStyle.h:282
Double_t GetChisquare() const
Definition: TF1.h:336
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition: TObject.cxx:564
virtual Double_t * GetEYlowd() const
Definition: TGraph.h:150
void SetLabelOffset(Float_t labeloffset)
Definition: TGaxis.h:113
return c2
Definition: legend2.C:14
static const double x1[5]
A Pave (see TPave) with text, lines or/and boxes inside.
Definition: TPaveText.h:27
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
TH1F * GetHistogram() const
Returns a pointer to the histogram used to draw the axis Takes into account the two following cases...
Definition: TGraph.cxx:1466
void SetDrawBorder(Int_t drawborder=1)
Definition: TStyle.h:333
Double_t * gxwork
double Double_t
Definition: RtypesCore.h:55
virtual Double_t * GetEXlow() const
Definition: TGraph.h:145
unsigned long ULong_t
Definition: RtypesCore.h:51
Int_t GetDrawBorder() const
Definition: TStyle.h:186
Double_t y[n]
Definition: legend1.C:17
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:35
Double_t ey[n]
Definition: legend1.C:17
Int_t DistancetoLine(Int_t px, Int_t py, Double_t xp1, Double_t yp1, Double_t xp2, Double_t yp2)
Compute distance from point px,py to a line.
Definition: TAttLine.cxx:196
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
Abstract base class used by ROOT graphics editor.
virtual void PaintGraph(TGraph *theGraph, Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
[Control function to draw a graph.]($GP01)
Width_t GetStatBorderSize() const
Definition: TStyle.h:259
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:48
Double_t GetRMax()
Mother of all ROOT objects.
Definition: TObject.h:37
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
Float_t GetStatFontSize() const
Definition: TStyle.h:261
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:460
Double_t PiOver2()
Definition: TMath.h:46
virtual Int_t GetNpar() const
Definition: TF1.h:349
Double_t * GetY() const
Definition: TGraph.h:141
Float_t GetTickLength(Option_t *axis="X") const
Return tick length.
Definition: TStyle.cxx:819
virtual void Add(TObject *obj)
Definition: TList.h:81
virtual Double_t GetParameter(Int_t ipar) const
Definition: TF1.h:359
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Float_t GetStatH() const
Definition: TStyle.h:267
1-Dim function class
Definition: TF1.h:149
A Graph is a graphics object made of two arrays X and Y with npoints each.
Definition: TGraph.h:53
Double_t Sin(Double_t)
Definition: TMath.h:421
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
void SetTickSize(Float_t ticksize)
Definition: TGaxis.h:125
Float_t GetLabelOffset(Option_t *axis="X") const
Return label offset.
Definition: TStyle.cxx:767
#define snprintf
Definition: civetweb.c:822
Double_t * GetXpol()
Return points in polar coordinates.
#define gPad
Definition: TVirtualPad.h:289
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition: TAttText.h:49
The graph painter class.
Definition: TGraphPainter.h:31
virtual void SetHistogram(TH1F *h)
Definition: TGraph.h:178
virtual void Paint(Option_t *option="")
Paint the pave stat.
Definition: TPaveStats.cxx:320
Float_t GetBarOffset() const
Definition: TStyle.h:184
Style_t GetTitleStyle() const
Definition: TStyle.h:273
void ResetBit(UInt_t f)
Definition: TObject.h:156
Definition: first.py:1
Double_t GetYq1() const
Definition: TGraphQQ.h:44
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:36
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition: TAttText.h:52
Color_t GetStatTextColor() const
Definition: TStyle.h:258
virtual Double_t * GetEYhigh() const
Definition: TGraph.h:146
virtual void ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
Compute the x/y range of the points in this graph.
Definition: TGraph.cxx:647
Int_t GetNdivisions(Option_t *axis="X") const
Return number of divisions.
Definition: TStyle.cxx:711
Draw all kinds of Arrows.
Definition: TArrow.h:35
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
const Bool_t kTRUE
Definition: Rtypes.h:91
Double_t * GetYpol()
Return points in polar coordinates.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
Double_t GetMinimum() const
Definition: TGraph.h:153
double norm(double *x, double *p)
Definition: unuranDistr.cxx:40
TF1 * GetF() const
Definition: TGraphQQ.h:46
Double_t GetXmax() const
Definition: TAxis.h:140
Double_t ex[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
Line Attributes class.
Definition: TAttLine.h:24
virtual Double_t * GetEXhigh() const
Definition: TGraph.h:144
void PaintGraphSimple(TGraph *theGraph, Option_t *option)
Paint a simple graph, without errors bars.
virtual void SetBorderSize(Int_t bordersize=4)
Definition: TPave.h:74
const char * GetStatFormat() const
Definition: TStyle.h:263
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
void SetParent(TObject *obj)
Definition: TPaveStats.h:54
void SetOptStat(Int_t stat=1)
Set the stat option.
Definition: TPaveStats.cxx:303
Int_t GetOptTitle() const
Definition: TStyle.h:246
static const double x3[11]
Double_t ATan(Double_t)
Definition: TMath.h:451
void SetPolargram(TGraphPolargram *p)
Definition: TGraphPolar.h:59