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