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