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