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