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