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