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