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