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