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