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