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