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