Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, 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 <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TCanvasImp.h"
36#include "TPad.h"
37#include "TPaveStats.h"
38#include "TFrame.h"
39#include "TLatex.h"
40#include "TPolyLine.h"
41#include "TPoints.h"
42#include "TStyle.h"
43#include "TGraph.h"
44#include "TMultiGraph.h"
45#include "TPie.h"
46#include "TGaxis.h"
47#include "TColor.h"
49#include "TGraph2D.h"
50#include "TGraph2DPainter.h"
51#include "TGraphDelaunay2D.h"
52#include "TView.h"
53#include "TMath.h"
54#include "TRandom2.h"
55#include "TObjArray.h"
56#define ROOT_Hoption_cxx
57#include "Hoption.h"
58#define ROOT_Hparam_cxx
59#include "Hparam.h"
60#include "TPluginManager.h"
61#include "TPaletteAxis.h"
62#include "TCrown.h"
63#include "TArrow.h"
64#include "TVirtualPadPainter.h"
65#include "TVirtualPadEditor.h"
66#include "TEnv.h"
67#include "TPoint.h"
68#include "TImage.h"
69#include "TCandle.h"
70#include "strlcpy.h"
71
72/*! \class THistPainter
73 \ingroup Histpainter
74 \brief The histogram painter class. Implements all histograms' drawing's options.
75
76- [Introduction](\ref HP00)
77- [Histograms' plotting options](\ref HP01)
78 - [Options supported for 1D and 2D histograms](\ref HP01a)
79 - [Options supported for 1D histograms](\ref HP01b)
80 - [Options supported for 2D histograms](\ref HP01c)
81 - [Options supported for 3D histograms](\ref HP01d)
82 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
83- [Setting the Style](\ref HP02)
84- [Setting line, fill, marker, and text attributes](\ref HP03)
85- [Setting Tick marks on the histogram axis](\ref HP04)
86- [Giving titles to the X, Y and Z axis](\ref HP05)
87- [The option SAME](\ref HP060)
88 - [Limitations](\ref HP060a)
89- [Colors automatically picked in palette](\ref HP061)
90- [Superimposing two histograms with different scales in the same pad](\ref HP06)
91- [Statistics Display](\ref HP07)
92- [Fit Statistics](\ref HP08)
93- [The error bars options](\ref HP09)
94- [The bar chart option](\ref HP100)
95- [The BAR and HBAR options](\ref HP10)
96- [The SCATter plot option (legacy draw option)](\ref HP11)
97- [The ARRow option](\ref HP12)
98- [The BOX option](\ref HP13)
99- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
100- [The CANDLE and VIOLIN options](\ref HP140)
101 - [The CANDLE option](\ref HP140a)
102 - [The VIOLIN option](\ref HP140b)
103- [The TEXT and TEXTnn Option](\ref HP15)
104- [The CONTour options](\ref HP16)
105 - [The LIST option](\ref HP16a)
106 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
107- [The LEGO options](\ref HP17)
108- [The SURFace options](\ref HP18)
109- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
110- [Base line for bar-charts and lego plots](\ref HP20)
111- [TH2Poly Drawing](\ref HP20a)
112- [The SPEC option](\ref HP21)
113- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
114- [Setting the color palette](\ref HP23)
115- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
116- [Drawing options for 3D histograms](\ref HP25)
117- [Drawing option for histograms' stacks](\ref HP26)
118- [Drawing of 3D implicit functions](\ref HP27)
119- [Associated functions drawing](\ref HP28)
120- [Drawing using OpenGL](\ref HP29)
121 - [General information: plot types and supported options](\ref HP29a)
122 - [TH3 as color boxes](\ref HP290)
123 - [TH3 as boxes (spheres)](\ref HP29b)
124 - [TH3 as iso-surface(s)](\ref HP29c)
125 - [TF3 (implicit function)](\ref HP29d)
126 - [Parametric surfaces](\ref HP29e)
127 - [Interaction with the plots](\ref HP29f)
128 - [Selectable parts](\ref HP29g)
129 - [Rotation and zooming](\ref HP29h)
130 - [Panning](\ref HP29i)
131 - [Box cut](\ref HP29j)
132 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
133 - [Surface with option GLSURF](\ref HP29l)
134 - [TF3](\ref HP29m)
135 - [Box](\ref HP29n)
136 - [Iso](\ref HP29o)
137 - [Parametric plot](\ref HP29p)
138- [Highlight mode for histogram](\ref HP30)
139 - [Highlight mode and user function](\ref HP30a)
140
141
142\anchor HP00
143## Introduction
144
145
146Histograms are drawn via the `THistPainter` class. Each histogram has a
147pointer to its own painter (to be usable in a multithreaded program). When the
148canvas has to be redrawn, the `Paint` function of each objects in the
149pad is called. In case of histograms, `TH1::Paint` invokes directly
150`THistPainter::Paint`.
151
152To draw a histogram `h` it is enough to do:
153
154 h->Draw();
155
156`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
157be drawn, the `Draw()` method can be invoked with an option. For instance
158to draw a 2D histogram as a lego plot it is enough to do:
159
160 h->Draw("lego");
161
162`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
163
164When the `Draw()` method of a histogram is called for the first time
165(`TH1::Draw`), it creates a `THistPainter` object and saves a
166pointer to this "painter" as a data member of the histogram. The
167`THistPainter` class specializes in the drawing of histograms. It is
168separated from the histogram so that one can have histograms without the
169graphics overhead, for example in a batch program. Each histogram having its own
170painter (rather than a central singleton painter painting all histograms), allows
171two histograms to be drawn in two threads without overwriting the painter's
172values.
173
174When a displayed histogram is filled again, there is no need to call the
175`Draw()` method again; the image will be refreshed the next time the
176pad will be updated.
177
178A pad is updated after one of these three actions:
179
1801. a carriage control on the ROOT command line,
1812. a click inside the pad,
1823. a call to `TPad::Update`.
183
184
185By default a call to `TH1::Draw()` clears the pad of all objects
186before drawing the new image of the histogram. One can use the `SAME`
187option to leave the previous display intact and superimpose the new histogram.
188The same histogram can be drawn with different graphics options in different
189pads.
190
191When a displayed histogram is deleted, its image is automatically removed
192from the pad.
193
194To create a copy of the histogram when drawing it, one can use
195`TH1::DrawClone()`. This will clone the histogram and allow to change
196and delete the original one without affecting the clone.
197
198
199\anchor HP01
200### Histograms' plotting options
201
202
203Most options can be concatenated with or without spaces or commas, for example:
204
205 h->Draw("E1 SAME");
206
207The options are not case sensitive:
208
209 h->Draw("e1 same");
210
211
212The default drawing option can be set with `TH1::SetOption` and retrieve
213using `TH1::GetOption`:
214
215 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
216 root [1] h->Draw("E"); // Draw "h" using error bars
217 root [3] h->SetOption("E"); // Change the default drawing option for "h"
218 root [4] h->Draw(); // Draw "h" using error bars
219 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
220 (const Option_t* 0xa3ff948)"E"
221
222
223\anchor HP01a
224#### Options supported for 1D and 2D histograms
225
226| Option | Description |
227|----------|-------------------------------------------------------------------|
228| "E" | Draw error bars. |
229| "AXIS" | Draw only axis. |
230| "AXIG" | Draw only grid (if the grid is requested). |
231| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
232| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
233| "SAME" | Superimpose on previous picture in the same pad. |
234| "SAMES" | Same as "SAME" and draw the statistics box|
235| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
236| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
237| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
238| "LEGO" | Draw a lego plot with hidden line removal. |
239| "LEGO1" | Draw a lego plot with hidden surface removal. |
240| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
241| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
242| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
243| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
244| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
245| "X+" | The X-axis is drawn on the top side of the plot. |
246| "Y+" | The Y-axis is drawn on the right side of the plot. |
247| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
248
249
250\anchor HP01b
251#### Options supported for 1D histograms
252
253| Option | Description |
254|----------|-------------------------------------------------------------------|
255| " " | Default. |
256| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
257| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
258| "B" | Bar chart option.|
259| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
260| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
261| "C" | Draw a smooth Curve through the histogram bins.|
262| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
263| "E1" | Draw error bars with perpendicular lines at the edges.|
264| "E2" | Draw error bars with rectangles.|
265| "E3" | Draw a fill area through the end points of the vertical error bars.|
266| "E4" | Draw a smoothed filled area through the end points of the error bars.|
267| "E5" | Like E3 but ignore the bins with 0 contents.|
268| "E6" | Like E4 but ignore the bins with 0 contents.|
269| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
270| "L" | Draw a line through the bin contents.|
271| "P" | Draw current marker at each bin except empty bins.|
272| "P*" | Draw a star marker at each bin except empty bins.|
273| "P0" | Draw current marker at each bin including empty bins.|
274| "PIE" | Draw histogram as a Pie Chart.|
275| "*H" | Draw histogram with a * at each bin.|
276| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
277
278
279
280\anchor HP01c
281#### Options supported for 2D histograms
282
283| Option | Description |
284|--------------|------------------------------------------------------------------|
285| " " | Default (color plot).|
286| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
287| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
288| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
289| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
290| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
291| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
292| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
293| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
294| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
295| "CANDLE" | Draw a candle plot along X axis.|
296| "CANDLEX" | Same as "CANDLE".|
297| "CANDLEY" | Draw a candle plot along Y axis.|
298| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
299| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
300| "VIOLIN" | Draw a violin plot along X axis.|
301| "VIOLINX" | Same as "VIOLIN".|
302| "VIOLINY" | Draw a violin plot along Y axis.|
303| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
304| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
305| "CONT" | Draw a contour plot (same as CONT0).|
306| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
307| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
308| "CONT2" | Draw a contour plot using the same line style for all contours.|
309| "CONT3" | Draw a contour plot using fill area colors.|
310| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
311| "LIST" | Generate a list of TGraph objects for each contour.|
312| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
313| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
314| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
315| "POL" | Use Polar coordinates. The visible X range mapped on the angle and the visible Y coordinate on the radius.|
316| "POLF" | Fixed Polar coordinates. The histogram X coordinate mapped on the angle and the Y coordinate on the radius.|
317| "POLN" | Natural Polar coordinates. The X coordinate directly represent angle in radian and the Y coordinate is the radius.|
318| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
319| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
320| "SURF" | Draw a surface plot with hidden line removal.|
321| "SURF1" | Draw a surface plot with hidden surface removal.|
322| "SURF2" | Draw a surface plot using colors to show the cell contents.|
323| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
324| "SURF4" | Draw a surface using Gouraud shading.|
325| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
326| "AITOFF" | Draw a contour via an AITOFF projection.|
327| "MERCATOR" | Draw a contour via an Mercator projection.|
328| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
329| "PARABOLIC" | Draw a contour via an Parabolic projection.|
330| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
331| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
332| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
333| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
334| "A" | With LEGO or SURFACE, suppress the axis.|
335| "SCAT" | Draw a scatter-plot (legacy draw option).|
336| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
337
338
339
340\anchor HP01d
341#### Options supported for 3D histograms
342
343| Option | Description |
344|----------|-------------------------------------------------------------------|
345| " " | Default (color plot).|
346| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
347| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
348| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
349| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
350| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
351| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
352| "LEGO" | Same as `BOX`.|
353
354\anchor HP01e
355#### Options supported for histograms' stacks (`THStack`)
356
357| Option | Description |
358|------------|-----------------------------------------------------------------|
359| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
360| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
361| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
362| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
363| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
364| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
365| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
366| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
367
368
369
370\anchor HP02
371### Setting the Style
372
373
374Histograms use the current style (`gStyle`). When one changes the current
375style and would like to propagate the changes to the histogram,
376`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
377each histogram is needed.
378
379To force all the histogram to use the current style use:
380
381 gROOT->ForceStyle();
382
383All the histograms read after this call will use the current style.
384
385
386\anchor HP03
387### Setting line, fill, marker, and text attributes
388
389
390The histogram classes inherit from the attribute classes:
391`TAttLine`, `TAttFill` and `TAttMarker`.
392See the description of these classes for the list of options.
393
394
395\anchor HP04
396### Setting Tick marks on the histogram axis
397
398
399The `TPad::SetTicks` method specifies the type of tick marks on the axis.
400If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
401
402 tx = 1; tick marks on top side are drawn (inside)
403 tx = 2; tick marks and labels on top side are drawn
404 ty = 1; tick marks on right side are drawn (inside)
405 ty = 2; tick marks and labels on right side are drawn
406
407By default only the left Y axis and X bottom axis are drawn
408(`tx = ty = 0`)
409
410`TPad::SetTicks(tx,ty)` allows to set these options.
411See also The `TAxis` functions to set specific axis attributes.
412
413In case multiple color filled histograms are drawn on the same pad, the fill
414area may hide the axis tick marks. One can force a redraw of the axis over all
415the histograms by calling:
416
417 gPad->RedrawAxis();
418
419
420\anchor HP05
421### Giving titles to the X, Y and Z axis
422
423
424 h->GetXaxis()->SetTitle("X axis title");
425 h->GetYaxis()->SetTitle("Y axis title");
426
427The histogram title and the axis titles can be any `TLatex` string.
428The titles are part of the persistent histogram.
429
430
431\anchor HP060
432### The option "SAME"
433
434
435By default, when an histogram is drawn, the current pad is cleared before
436drawing. In order to keep the previous drawing and draw on top of it the
437option `SAME` should be use. The histogram drawn with the option
438`SAME` uses the coordinates system available in the current pad.
439
440This option can be used alone or combined with any valid drawing option but
441some combinations must be use with care.
442
443\anchor HP060a
444#### Limitations
445
446- It does not work when combined with the `LEGO` and `SURF` options unless the
447 histogram plotted with the option `SAME` has exactly the same
448 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
449 lego plots [histograms' stacks](\ref HP26) should be used.
450
451
452\anchor HP061
453### Colors automatically picked in palette
454
455\since **ROOT version 6.09/01**
456
457When several histograms are painted in the same canvas thanks to the option "SAME"
458or via a `THStack` it might be useful to have an easy and automatic way to choose
459their color. The simplest way is to pick colors in the current active color
460palette. Palette coloring for histogram is activated thanks to the options `PFC`
461(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
462When one of these options is given to `TH1::Draw` the histogram get its color
463from the current color palette defined by `gStyle->SetPalette(...)`. The color
464is determined according to the number of objects having palette coloring in
465the current pad.
466
467Begin_Macro(source)
468../../../tutorials/hist/hist005_TH1_palettecolor.C
469End_Macro
470
471Begin_Macro(source)
472../../../tutorials/hist/hist027_THStack_palette_color.C
473End_Macro
474
475Begin_Macro(source)
476../../../tutorials/hist/hist025_THStack_2d_palette_color.C
477End_Macro
478
479\anchor HP06
480### Superimposing two histograms with different scales in the same pad
481
482
483The following example creates two histograms, the second histogram is the bins
484integral of the first one. It shows a procedure to draw the two histograms in
485the same pad and it draws the scale of the second histogram using a new vertical
486axis on the right side. See also the tutorial `transpad.C` for a variant
487of this example.
488
489Begin_Macro(source)
490{
491 auto c1 = new TCanvas("c1","c1",600,400);
492 // create/fill draw h1
493 gStyle->SetOptStat(kFALSE);
494 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
495 Int_t i;
496 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
497 h1->Draw();
498 c1->Update();
499
500 // create hint1 filled with the bins integral of h1
501 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
502 float sum = 0.f;
503 for (i=1;i<=100;i++) {
504 sum += h1->GetBinContent(i);
505 hint1->SetBinContent(i,sum);
506 }
507
508 // scale hint1 to the pad coordinates
509 float rightmax = 1.1*hint1->GetMaximum();
510 float scale = gPad->GetUymax()/rightmax;
511 hint1->SetLineColor(kRed);
512 hint1->Scale(scale);
513 hint1->Draw("same");
514
515 // draw an axis on the right side
516 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
517 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
518 axis->SetLineColor(kRed);
519 axis->SetTextColor(kRed);
520 axis->Draw();
521}
522End_Macro
523
524
525\anchor HP07
526### Statistics Display
527
528
529The type of information shown in the histogram statistics box can be selected
530with:
531
532 gStyle->SetOptStat(mode);
533
534The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
535
536 mode = ksiourmen (default = 000001111)
537 k = 1; kurtosis printed
538 k = 2; kurtosis and kurtosis error printed
539 s = 1; skewness printed
540 s = 2; skewness and skewness error printed
541 i = 1; integral of bins printed
542 i = 2; integral of bins with option "width" printed
543 o = 1; number of overflows printed
544 u = 1; number of underflows printed
545 r = 1; standard deviation printed
546 r = 2; standard deviation and standard deviation error printed
547 m = 1; mean value printed
548 m = 2; mean and mean error values printed
549 e = 1; number of entries printed
550 n = 1; name of histogram is printed
551
552For example:
553
554 gStyle->SetOptStat(11);
555
556displays only the name of histogram and the number of entries, whereas:
557
558 gStyle->SetOptStat(1101);
559
560displays the name of histogram, mean value and standard deviation.
561
562<b>WARNING 1:</b> never do:
563
564 gStyle->SetOptStat(0001111);
565
566but instead do:
567
568 gStyle->SetOptStat(1111);
569
570because `0001111` will be taken as an octal number!
571
572<b>WARNING 2:</b> for backward compatibility with older versions
573
574 gStyle->SetOptStat(1);
575
576is taken as:
577
578 gStyle->SetOptStat(1111)
579
580To print only the name of the histogram do:
581
582 gStyle->SetOptStat(1000000001);
583
584<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
585(10000) or overflow (100000), the statistics box will show all combinations
586of underflow/overflows and not just one single number.
587
588The parameter mode can be any combination of the letters `kKsSiIourRmMen`
589
590 k : kurtosis printed
591 K : kurtosis and kurtosis error printed
592 s : skewness printed
593 S : skewness and skewness error printed
594 i : integral of bins printed
595 I : integral of bins with option "width" printed
596 o : number of overflows printed
597 u : number of underflows printed
598 r : standard deviation printed
599 R : standard deviation and standard deviation error printed
600 m : mean value printed
601 M : mean value mean error values printed
602 e : number of entries printed
603 n : name of histogram is printed
604
605For example, to print only name of histogram and number of entries do:
606
607 gStyle->SetOptStat("ne");
608
609To print only the name of the histogram do:
610
611 gStyle->SetOptStat("n");
612
613The default value is:
614
615 gStyle->SetOptStat("nemr");
616
617When a histogram is painted, a `TPaveStats` object is created and added
618to the list of functions of the histogram. If a `TPaveStats` object
619already exists in the histogram list of functions, the existing object is just
620updated with the current histogram parameters.
621
622Once a histogram is painted, the statistics box can be accessed using
623`h->FindObject("stats")`. In the command line it is enough to do:
624
625 Root > h->Draw()
626 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
627
628because after `h->Draw()` the histogram is automatically painted. But
629in a script file the painting should be forced using `gPad->Update()`
630in order to make sure the statistics box is created:
631
632 h->Draw();
633 gPad->Update();
634 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
635
636Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
637
638When a histogram is drawn with the option `SAME`, the statistics box
639is not drawn. To force the statistics box drawing with the option
640`SAME`, the option `SAMES` must be used.
641If the new statistics box hides the previous statistics box, one can change
642its position with these lines (`h` being the pointer to the histogram):
643
644 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
645 Root > st->SetX1NDC(newx1); //new x start position
646 Root > st->SetX2NDC(newx2); //new x end position
647
648To change the type of information for an histogram with an existing
649`TPaveStats` one should do:
650
651 st->SetOptStat(mode);
652
653Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
654(see above).
655
656One can delete the statistics box for a histogram `TH1* h` with:
657
658 h->SetStats(0)
659
660and activate it again with:
661
662 h->SetStats(1).
663
664Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
665`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
666
667
668\anchor HP08
669### Fit Statistics
670
671
672The type of information about fit parameters printed in the histogram statistics
673box can be selected via the parameter mode. The parameter mode can be
674`= pcev` (default `= 0111`)
675
676 p = 1; print Probability
677 c = 1; print Chisquare/Number of degrees of freedom
678 e = 1; print errors (if e=1, v must be 1)
679 v = 1; print name/values of parameters
680
681Example:
682
683 gStyle->SetOptFit(1011);
684
685print fit probability, parameter names/values and errors.
686
6871. When `v = 1` is specified, only the non-fixed parameters are shown.
6882. When `v = 2` all parameters are shown.
689
690Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
691to `gStyle->SetOptFit(111)`
692
693
694\anchor HP09
695### The error bars options
696
697
698| Option | Description |
699|----------|-------------------------------------------------------------------|
700| "E" | Default. Shows only the error bars, not a marker.|
701| "E1" | Small lines are drawn at the end of the error bars.|
702| "E2" | Error rectangles are drawn.|
703| "E3" | A filled area is drawn through the end points of the vertical error bars.|
704| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
705| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
706| "E5" | Like E3 but ignore the bins with 0 contents.|
707| "E6" | Like E4 but ignore the bins with 0 contents.|
708| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
709
710Begin_Macro(source)
711{
712 auto c1 = new TCanvas("c1","c1",600,400);
713 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
714 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
715 gStyle->SetEndErrorSize(3);
716 gStyle->SetErrorX(1.);
717 he->SetMarkerStyle(20);
718 he->Draw("E1");
719}
720End_Macro
721
722The options "E3" and "E4" draw an error band through the end points of the
723vertical error bars. With "E4" the error band is smoothed. Because of the
724smoothing algorithm used some artefacts may appear at the end of the band
725like in the following example. In such cases "E3" should be used instead
726of "E4".
727
728Begin_Macro(source)
729{
730 auto ce4 = new TCanvas("ce4","ce4",600,400);
731 ce4->Divide(2,1);
732 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
733 Int_t i;
734 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
735 he4->SetFillColor(kRed);
736 he4->GetXaxis()->SetRange(40,48);
737 ce4->cd(1);
738 he4->Draw("E4");
739 ce4->cd(2);
740 auto he3 = (TH1F*)he4->DrawClone("E3");
741 he3->SetTitle("Distribution drawn option E3");
742}
743End_Macro
744
7452D histograms can be drawn with error bars as shown is the following example:
746
747Begin_Macro(source)
748{
749 auto c2e = new TCanvas("c2e","c2e",600,400);
750 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
751 float px, py;
752 for (Int_t i = 0; i < 25000; i++) {
753 gRandom->Rannor(px,py);
754 h2e->Fill(px,5*py);
755 }
756 h2e->Draw("E");
757}
758End_Macro
759
760
761\anchor HP100
762### The bar chart option
763
764
765The option "B" allows to draw simple vertical bar charts.
766The bar width is controlled with `TH1::SetBarWidth()`,
767and the bar offset within the bin, with `TH1::SetBarOffset()`.
768These two settings are useful to draw several histograms on the
769same plot as shown in the following example:
770
771Begin_Macro(source)
772{
773 int i;
774 const Int_t nx = 8;
775 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
776 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
777 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
778
779 auto cb = new TCanvas("cb","cb",600,400);
780 cb->SetGrid();
781
782 gStyle->SetHistMinimumZero();
783
784 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
785 h1b->SetFillColor(4);
786 h1b->SetBarWidth(0.4);
787 h1b->SetBarOffset(0.1);
788 h1b->SetStats(0);
789 h1b->SetMinimum(-5);
790 h1b->SetMaximum(5);
791
792 for (i=1; i<=nx; i++) {
793 h1b->SetBinContent(i, d_35_0[i-1]);
794 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
795 }
796
797 h1b->Draw("b");
798
799 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
800 h2b->SetFillColor(38);
801 h2b->SetBarWidth(0.4);
802 h2b->SetBarOffset(0.5);
803 h2b->SetStats(0);
804 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
805
806 h2b->Draw("b same");
807}
808End_Macro
809
810
811\anchor HP10
812### The "BAR" and "HBAR" options
813
814
815When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
816bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
817An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
818`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
819
820- The bar is filled with the histogram fill color.
821- The left side of the bar is drawn with a light fill color.
822- The right side of the bar is drawn with a dark fill color.
823- The percentage of the bar drawn with either the light or dark color is:
824 - 0% for option "(h)bar" or "(h)bar0"
825 - 10% for option "(h)bar1"
826 - 20% for option "(h)bar2"
827 - 30% for option "(h)bar3"
828 - 40% for option "(h)bar4"
829
830When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
831
832Begin_Macro(source)
833../../../tutorials/hist/hist006_TH1_bar_charts.C
834End_Macro
835
836To control the bar width (default is the bin width) `TH1::SetBarWidth()`
837should be used.
838
839To control the bar offset (default is 0) `TH1::SetBarOffset()` should
840be used.
841
842These two parameters are useful when several histograms are plotted using
843the option `SAME`. They allow to plot the histograms next to each other.
844
845
846\anchor HP11
847### The SCATter plot option (legacy draw option)
848
849\attention
850Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8513D histograms. The new default option is `COL` (heat-map).
852
853
854For each cell (i,j) a number of points proportional to the cell content is
855drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
856`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
857If option is of the form `scat=ff`, (eg `scat=1.8`,
858`scat=1e-3`), then `ff` is used as a scale factor to compute the
859number of dots. `scat=1` is the default.
860
861By default the scatter plot is painted with a "dot marker" which not scalable
862(see the `TAttMarker` documentation). To change the marker size, a scalable marker
863type should be used. For instance a circle (marker style 20).
864
865Begin_Macro(source)
866{
867 auto c1 = new TCanvas("c1","c1",600,400);
868 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
869 float px, py;
870 for (Int_t i = 0; i < 25000; i++) {
871 gRandom->Rannor(px,py);
872 hscat->Fill(px,5*py);
873 hscat->Fill(3+0.5*px,2*py-10.);
874 }
875 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
876}
877End_Macro
878
879
880\anchor HP12
881### The ARRow option
882
883
884Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
885The orientation of the arrow follows the cell gradient.
886
887Begin_Macro(source)
888{
889 auto c1 = new TCanvas("c1","c1",600,400);
890 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
891 harr->SetLineColor(kRed);
892 float px, py;
893 for (Int_t i = 0; i < 25000; i++) {
894 gRandom->Rannor(px,py);
895 harr->Fill(px,5*py);
896 harr->Fill(3+0.5*px,2*py-10.,0.1);
897 }
898 harr->Draw("ARR");
899}
900End_Macro
901
902\since **ROOT version 6.17/01**
903
904The option `ARR` can be combined with the option `COL` or `COLZ`.
905
906Begin_Macro(source)
907{
908 auto c1 = new TCanvas("c1","c1",600,400);
909 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
910 harr->SetStats(0);
911 float px, py;
912 for (Int_t i = 0; i < 25000; i++) {
913 gRandom->Rannor(px,py);
914 harr->Fill(px,5*py);
915 harr->Fill(3+0.5*px,2*py-10.,0.1);
916 }
917 harr->Draw("ARR COLZ");
918}
919End_Macro
920
921
922\anchor HP13
923### The BOX option
924
925
926For each cell (i,j) a box is drawn. The size (surface) of the box is
927proportional to the absolute value of the cell content.
928The cells with a negative content are drawn with a `X` on top of the box.
929
930Begin_Macro(source)
931{
932 auto c1 = new TCanvas("c1","c1",600,400);
933 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
934 hbox->SetFillColor(42);
935 hbox->Fill(0.5, 0.5, 1.);
936 hbox->Fill(0.5, 1.5, 4.);
937 hbox->Fill(0.5, 2.5, 3.);
938 hbox->Fill(1.5, 0.5, 2.);
939 hbox->Fill(1.5, 1.5, 12.);
940 hbox->Fill(1.5, 2.5, -6.);
941 hbox->Fill(2.5, 0.5, -4.);
942 hbox->Fill(2.5, 1.5, 6.);
943 hbox->Fill(2.5, 2.5, 0.5);
944 hbox->Draw("BOX");
945}
946End_Macro
947
948With option `BOX1` a button is drawn for each cell with surface
949proportional to content's absolute value. A sunken button is drawn for
950negative values a raised one for positive.
951
952Begin_Macro(source)
953{
954 auto c1 = new TCanvas("c1","c1",600,400);
955 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
956 hbox1->SetFillColor(42);
957 hbox1->Fill(0.5, 0.5, 1.);
958 hbox1->Fill(0.5, 1.5, 4.);
959 hbox1->Fill(0.5, 2.5, 3.);
960 hbox1->Fill(1.5, 0.5, 2.);
961 hbox1->Fill(1.5, 1.5, 12.);
962 hbox1->Fill(1.5, 2.5, -6.);
963 hbox1->Fill(2.5, 0.5, -4.);
964 hbox1->Fill(2.5, 1.5, 6.);
965 hbox1->Fill(2.5, 2.5, 0.5);
966 hbox1->Draw("BOX1");
967}
968End_Macro
969
970When the option `SAME` (or "SAMES") is used with the option `BOX`,
971the boxes' sizes are computed taking the previous plots into account. The range
972along the Z axis is imposed by the first plot (the one without option
973`SAME`); therefore the order in which the plots are done is relevant.
974
975Begin_Macro(source)
976{
977 auto c1 = new TCanvas("c1","c1",600,400);
978 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
979 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
980 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
981 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
982 for (Int_t i=0;i<1000;i++) {
983 double x,y;
984 gRandom->Rannor(x,y);
985 if (x>0 && y>0) hb1->Fill(x,y,4);
986 if (x<0 && y<0) hb2->Fill(x,y,3);
987 if (x>0 && y<0) hb3->Fill(x,y,2);
988 if (x<0 && y>0) hb4->Fill(x,y,1);
989 }
990 hb1->SetFillColor(1);
991 hb2->SetFillColor(2);
992 hb3->SetFillColor(3);
993 hb4->SetFillColor(4);
994 hb1->Draw("box");
995 hb2->Draw("box same");
996 hb3->Draw("box same");
997 hb4->Draw("box same");
998}
999End_Macro
1000
1001\since **ROOT version 6.17/01:**
1002
1003Sometimes the change of the range of the Z axis is unwanted, in which case, one
1004can use `SAME0` (or `SAMES0`) option to opt out of this change.
1005
1006Begin_Macro(source)
1007{
1008 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1009 auto hf = (TH2F*)h2->Clone("hf");
1010 h2->SetBit(TH1::kNoStats);
1011 hf->SetBit(TH1::kNoStats);
1012 h2->Fill(5,22);
1013 h2->Fill(5,23);
1014 h2->Fill(6,22);
1015 h2->Fill(6,23);
1016 hf->Fill(6,23);
1017 hf->Fill(6,23);
1018 hf->Fill(6,23);
1019 hf->Fill(6,23);
1020 hf->Fill(5,23);
1021
1022 auto hf_copy1 = hf->Clone("hf_copy1");
1023 TLatex lt;
1024
1025 auto cx = new TCanvas(); cx->Divide(2,1);
1026
1027 cx->cd(1);
1028 h2->Draw("box");
1029 hf->Draw("text colz same");
1030 lt.DrawLatexNDC(0.3,0.5,"SAME");
1031
1032 cx->cd(2);
1033 h2->Draw("box");
1034 hf_copy1->Draw("text colz same0");
1035 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1036}
1037End_Macro
1038
1039
1040\anchor HP14
1041### The COLor option (default for 2D histograms)
1042
1043The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1044This data visualization technique is often called a heat map (or heat-map).
1045
1046The color table used is defined in the current style.
1047
1048If the histogram's minimum and maximum are the same (flat histogram), the
1049mapping on colors is not possible, therefore nothing is painted. To paint a
1050flat histogram it is enough to set the histogram minimum
1051(`TH1::SetMinimum()`) different from the bins' content.
1052
1053The default number of color levels used to paint the cells is 20.
1054It can be changed with `TH1::SetContour()` or
1055`TStyle::SetNumberContours()`. The higher this number is, the smoother
1056is the color change between cells.
1057
1058The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1059
1060All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1061not painted unless some bins have a negative content because in that case the null bins
1062might be not empty.
1063
1064`TProfile2D` histograms are handled differently because, for this type of 2D
1065histograms, it is possible to know if an empty bin has been filled or not. So even
1066if all the bins' contents are positive some empty bins might be painted. And vice versa,
1067if some bins have a negative content some empty bins might be not painted.
1068
1069Combined with the option `COL`, the option `Z` allows to
1070display the color palette defined by `gStyle->SetPalette()`.
1071
1072In the following example, the histogram has only positive bins; the empty
1073bins (containing 0) are not drawn.
1074
1075Begin_Macro(source)
1076{
1077 auto c1 = new TCanvas("c1","c1",600,400);
1078 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1079 float px, py;
1080 for (Int_t i = 0; i < 25000; i++) {
1081 gRandom->Rannor(px,py);
1082 hcol1->Fill(px,5*py);
1083 }
1084 hcol1->Draw("COLZ");
1085}
1086End_Macro
1087
1088In the first plot of following example, the histogram has some negative bins;
1089the empty bins (containing 0) are drawn. In some cases one wants to not draw
1090empty bins (containing 0) of histograms having a negative minimum. The option
1091`1`, used to produce the second plot in the following picture, allows to do that.
1092
1093Begin_Macro(source)
1094{
1095 auto c1 = new TCanvas("c1","c1",600,600);
1096 c1->Divide(1,2);
1097 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1098 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1099 float px, py;
1100 for (Int_t i = 0; i < 25000; i++) {
1101 gRandom->Rannor(px,py);
1102 hcol23->Fill(px,5*py);
1103 hcol24->Fill(px,5*py);
1104 }
1105 hcol23->Fill(0.,0.,-200.);
1106 hcol24->Fill(0.,0.,-200.);
1107 c1->cd(1); hcol23->Draw("COLZ");
1108 c1->cd(2); hcol24->Draw("COLZ1");
1109}
1110End_Macro
1111
1112When the maximum of the histogram is set to a smaller value than the real maximum,
1113 the bins having a content between the new maximum and the real maximum are
1114painted with the color corresponding to the new maximum.
1115
1116When the minimum of the histogram is set to a greater value than the real minimum,
1117 the bins having a value between the real minimum and the new minimum are not drawn
1118 unless the option `0` is set.
1119In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1120 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1121 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1122 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1123(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1124
1125The following example illustrates the option `0` combined with the option `COL`.
1126
1127Begin_Macro(source)
1128{
1129 auto c1 = new TCanvas("c1","c1",600,600);
1130 c1->Divide(1,2);
1131 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1132 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1133 float px, py;
1134 for (Int_t i = 0; i < 25000; i++) {
1135 gRandom->Rannor(px,py);
1136 hcol21->Fill(px,5*py);
1137 hcol22->Fill(px,5*py);
1138 }
1139 hcol21->SetBit(TH1::kNoStats);
1140 hcol22->SetBit(TH1::kNoStats);
1141 c1->cd(1); hcol21->Draw("COLZ");
1142 c1->cd(2); hcol22->Draw("COLZ0");
1143 hcol21->SetMaximum(100);
1144 hcol21->SetMinimum(40);
1145 hcol22->SetMaximum(100);
1146 hcol22->SetMinimum(40);
1147}
1148End_Macro
1149
1150Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1151but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1152clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1153if the set minimum is not negative.
1154
1155\since **ROOT version 6.09/01:**
1156
1157When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1158are computed taking the previous plots into account. The range along the Z axis
1159is imposed by the first plot (the one without option SAME); therefore the order
1160in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1161`SAME0` (or `SAMES0`) to opt out of this imposition.
1162
1163Begin_Macro(source)
1164{
1165 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1166 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1167 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1168 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1169 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1170 h1->SetBit(TH1::kNoStats);
1171 for (Int_t i=0;i<5000;i++) {
1172 double x,y;
1173 gRandom->Rannor(x,y);
1174 if(x>0 && y>0) h1->Fill(x,y,4);
1175 if(x<0 && y<0) h2->Fill(x,y,3);
1176 if(x>0 && y<0) h3->Fill(x,y,2);
1177 if(x<0 && y>0) h4->Fill(x,y,1);
1178 }
1179 h1->Draw("colz");
1180 h2->Draw("col same");
1181 h3->Draw("col same");
1182 h4->Draw("col same");
1183}
1184End_Macro
1185
1186The option `COL` can be combined with the option `POL`:
1187
1188Begin_Macro(source)
1189{
1190 auto c1 = new TCanvas("c1","c1",600,400);
1191 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1192 float px, py;
1193 for (Int_t i = 0; i < 25000; i++) {
1194 gRandom->Rannor(px,py);
1195 hcol1->Fill(px,py);
1196 }
1197 hcol1->Draw("COLZPOL");
1198}
1199End_Macro
1200
1201\since **ROOT version 6.07/03:**
1202
1203A second rendering technique is also available with the COL2 and COLZ2 options.
1204
1205These options provide potential performance improvements compared to the standard
1206COL option. The performance comparison of the COL2 to the COL option depends on
1207the histogram and the size of the rendering region in the current pad. In general,
1208a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1209faster with the COL option.
1210
1211However, for larger histograms (approx. more than 100 bins per axis)
1212that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1213For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1214faster with the COL2 option.
1215
1216The COL2 option will also scale its performance based on the size of the
1217pixmap the histogram image is being rendered into. It also is much better optimized for
1218sessions where the user is forwarding X11 windows through an `ssh` connection.
1219
1220For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1221and COLZ options. There is one major difference and that concerns the treatment of
1222bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1223
1224COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1225graphics file format like PostScript or PDF (an empty image will be generated). It can
1226be saved only in bitmap files like PNG format for instance.
1227
1228
1229\anchor HP140
1230### The CANDLE and VIOLIN options
1231
1232The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1233implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1234the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1235vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1236(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1237
1238Instead of using the predefined representations, the candle and violin parameters can be
1239changed individually. In that case the option have the following form:
1240
1241 CANDLEX(<option-string>)
1242 CANDLEY(<option-string>)
1243 VIOLINX(<option-string>)
1244 VIOLINY(<option-string>).
1245
1246All zeros at the beginning of `option-string` can be omitted.
1247
1248`option-string` consists eight values, defined as follow:
1249
1250 "CANDLEX(zhpawMmb)"
1251
1252Where:
1253
1254 - `b = 0`; no box drawn
1255 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1256 makes sense in the very most cases to always draw the box
1257 - `b = 2`; draw a filled box with border
1258
1259 - `m = 0`; no median drawn
1260 - `m = 1`; median is drawn as a line
1261 - `m = 2`; median is drawn with errors (notches)
1262 - `m = 3`; median is drawn as a circle
1263
1264 - `M = 0`; no mean drawn
1265 - `M = 1`; mean is drawn as a dashed line
1266 - `M = 3`; mean is drawn as a circle
1267
1268 - `w = 0`; no whisker drawn
1269 - `w = 1`; whisker is drawn to end of distribution.
1270 - `w = 2`; whisker is drawn to max 1.5*iqr
1271
1272 - `a = 0`; no anchor drawn
1273 - `a = 1`; the anchors are drawn
1274
1275 - `p = 0`; no points drawn
1276 - `p = 1`; only outliers are drawn
1277 - `p = 2`; all datapoints are drawn
1278 - `p = 3`: all datapoints are drawn scattered
1279
1280 - `h = 0`; no histogram is drawn
1281 - `h = 1`; histogram at the left or bottom side is drawn
1282 - `h = 2`; histogram at the right or top side is drawn
1283 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1284
1285 - `z = 0`; no zero indicator line is drawn
1286 - `z = 1`; zero indicator line is drawn.
1287
1288As one can see all individual options for both candle and violin plots can be accessed by this
1289mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1290meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1291vice versa, if you wish.
1292
1293Using a logarithmic x- or y-axis is possible for candle and violin charts.
1294
1295\since **ROOT version 6.11/01**
1296
1297a logarithmic z-axis is possible, too but will only affect violin charts of course.
1298
1299\anchor HP140a
1300#### The CANDLE option
1301
1302<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1303a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1304way to describe graphically a data distribution (D) with only five numbers:
1305
1306 1. The minimum value of the distribution D (bottom or left whisker).
1307 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1308 3. The median (M): 50% of the data points in D are less than M.
1309 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1310 5. The maximum value of the distribution D (top or right whisker).
1311
1312In this implementation a TH2 is considered as a collection of TH1 along
1313X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1314Each TH1 is represented as one candle.
1315
1316Begin_Macro(source)
1317../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1318End_Macro
1319
1320The candle reduces the information coming from a whole distribution into few values.
1321Independently from the number of entries or the significance of the underlying distribution
1322a candle will always look like a candle. So candle plots should be used carefully in
1323particular with unknown distributions. The definition of a candle is based on
1324__unbinned data__. Here, candles are created from binned data. Because of this, the
1325deviation is connected to the bin width used. The calculation of the quantiles
1326normally done on unbinned data also. Because data are binned, this will
1327only work the best possible way within the resolution of one bin
1328
1329Because of all these facts one should take care that:
1330
1331 - there are enough points per candle
1332 - the bin width is small enough (more bins will increase the maximum
1333 available resolution of the quantiles although there will be some
1334 bins with no entries)
1335 - never make a candle-plot if the underlying distribution is double-distributed
1336 - only create candles of distributions that are more-or-less gaussian (the
1337 MPV should be not too far away from the mean).
1338
1339#### What a candle is made of
1340
1341\since **ROOT version 6.07/05**
1342
1343##### The box
1344The box displays the position of the inter-quantile-range of the underlying
1345distribution. The box contains 25% of the distribution below the median
1346and 25% of the distribution above the median. If the underlying distribution is large
1347enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1348(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1349the position of the box can be modified by SetBarWidth() and SetBarOffset().
1350The +-25% quantiles are calculated by the GetQuantiles() methods.
1351
1352\since **ROOT version 6.11/01**
1353
1354Using the static function TCandle::SetBoxRange(double) the box definition will be
1355overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1356to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1357The static function will affect all candle-charts in the running program.
1358Default is 0.5.
1359
1360Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1361whole candle) can be influenced. Deactivated, the width is constant (to be set by
1362SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1363amount of data in the corresponding candle, the maximum width can be influenced by
1364SetBarWidth(). The static function will affect all candle-charts in the running program.
1365Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1366supported, yet
1367
1368##### The Median
1369For a sorted list of numbers, the median is the value in the middle of the list.
1370E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1371because it is in the middle of the list. If the number of entries is even the
1372average of the two values in the middle will be used. As histograms are binned
1373data, the situation is a bit more complex. The following example shows this:
1374
1375~~~ {.cpp}
1376void quantiles() {
1377 auto h = new TH1I("h","h",10,0,10);
1378 //h->Fill(3);
1379 //h->Fill(3);
1380 h->Fill(4);
1381 h->Draw();
1382 double p = 0.;
1383 double q = 0.;
1384 h->GetQuantiles(1,&q,&p);
1385
1386 cout << "Median is: " << q << std::endl;
1387}
1388~~~
1389
1390Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1391the example will return a calculated median of 4.5, because that's the bin center
1392of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1393commented out, it will return 3.75, because the algorithm tries to evenly distribute
1394the individual values of a bin with bin content > 0. It means the sorted list
1395would be "3.25, 3.75, 4.5".
1396
1397The consequence is a median of 3.75. This shows how important it is to use a
1398small enough bin-width when using candle-plots on binned data.
1399If the distribution is large enough and gaussian shaped the median will be exactly
1400equal to the mean.
1401The median can be shown as a line or as a circle or not shown at all.
1402
1403In order to show the significance of the median notched candle plots apply a "notch" or
1404narrowing of the box around the median. The significance is defined by
1405\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1406(where iqr is the size of the box and N is the number of entries of the whole
1407distribution). Candle plots like these are usually called "notched candle plots".
1408
1409In case the significance of the median is greater that the size of the box, the
1410box will have an unnatural shape. Usually it means the chart has not enough data,
1411or that representing this uncertainty is not useful
1412
1413##### The Mean
1414The mean can be drawn as a dashed line or as a circle or not drawn at all.
1415The mean is the arithmetic average of the values in the distribution.
1416It is calculated using GetMean(). Because histograms are
1417binned data, the mean value can differ from a calculation on the raw-data.
1418If the distribution is large enough and gaussian shaped the mean will be
1419exactly the median.
1420
1421##### The Whiskers
1422The whiskers represent the part of the distribution not covered by the box.
1423The upper 25% and the lower 25% of the distribution are located within the whiskers.
1424Two representations are available.
1425
1426 - A simple one (using w=1) defining the lower whisker from the lowest data value
1427 to the bottom of the box, and the upper whisker from the top of the box to the
1428 highest data value. In this representation the whisker-lines are dashed.
1429 - A more complex one having a further restriction. The whiskers are still connected
1430 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1431 be that the outermost part of the underlying distribution will not be covered
1432 by the whiskers. Usually these missing parts will be represented by the outliers
1433 (see points). Of course the upper and the lower whisker may differ in length.
1434 In this representation the whiskers are drawn as solid lines.
1435
1436\since **ROOT version 6.11/01**
1437
1438Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1439will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1440the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1441that candle. The static function will affect all candle-charts in the running program.
1442Default is 1.
1443
1444If the distribution is large enough and gaussian shaped, the maximum length of
1445the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14461.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1447(see picture above). In that case 99.3% of the total distribution will be covered
1448by the box and the whiskers, whereas 0.7% are represented by the outliers.
1449
1450##### The Anchors
1451The anchors have no special meaning in terms of statistical calculation. They mark
1452the end of the whiskers and they have the width of the box. Both representation
1453with and without anchors are common.
1454
1455##### The Points
1456Depending on the configuration the points can have different meanings:
1457 - If p=1 the points represent the outliers. If they are shown, it means
1458 some parts of the underlying distribution are not covered by the whiskers.
1459 This can only occur when the whiskers are set to option w=2. Here the whiskers
1460 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1461 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1462 - If p=2 all points in the distribution will be painted as crosses. This is
1463 useful for small datasets only (up to 10 or 20 points per candle).
1464 The outliers are shown along the candle. Because the underlying distribution
1465 is binned, is frequently occurs that a bin contains more than one value.
1466 Because of this the points will be randomly scattered within their bin along
1467 the candle axis. If the bin content for a bin is exactly 1 (usually
1468 this happens for the outliers) if will be drawn in the middle of the bin along
1469 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1470 on very large datasets scaling will be performed automatically. In that case one
1471 would loose all outliers because they have usually a bin content of 1 (and a
1472 bin content between 0 and 1 after the scaling). Because of this all bin contents
1473 between 0 and 1 - after the scaling - will be forced to be 1.
1474 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1475 one can show all values as a scatter plot instead by choosing p=3. The points will be
1476 drawn as dots and will be scattered within the width of the candle. The color
1477 of the points will be the color of the candle-chart.
1478
1479##### Other Options
1480Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1481with a histogram.
1482
1483#### How to use the candle-plots drawing option
1484
1485There are six predefined candle-plot representations:
1486
1487 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1488 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1489 It is a good compromise
1490 - "CANDLEX3": Like candle2 but with a mean as a circle.
1491 It is easier to distinguish mean and median
1492 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1493 (notched candle plots).
1494 For bigger datasets per candle
1495 - "CANDLEX5": Like candle2 but showing all data points.
1496 For very small datasets
1497 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1498 For huge datasets
1499
1500
1501The following picture shows how the six predefined representations look.
1502
1503Begin_Macro
1504{
1505 auto c1 = new TCanvas("c1","c1",700,800);
1506 c1->Divide(2,3);
1507 gStyle->SetOptStat(kFALSE);
1508
1509 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1510 float px, py;
1511 for (Int_t i = 0; i < 15000; i++) {
1512 gRandom->Rannor(px,py);
1513 hcandle->Fill(px,5*py);
1514 }
1515 hcandle->SetMarkerSize(0.5);
1516
1517 TH2F *h2;
1518 for (Int_t i=1; i<7; i++) {
1519 c1->cd(i);
1520 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1521 h2->SetTitle(Form("CANDLE%d",i));
1522 }
1523}
1524End_Macro
1525
1526
1527#### Example 1
1528Box and improved whisker, no mean, no median, no anchor no outliers
1529
1530 h1->Draw("CANDLEX(2001)");
1531
1532#### Example 2
1533A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1534
1535 h1->Draw("CANDLEX(112111)");
1536
1537#### Example 3
1538The following example shows how several candle plots can be super-imposed using
1539the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1540Also the color, the line width, the size of the points and so on can be changed by the
1541standard attribute setting methods such as SetLineColor() SetLineWidth().
1542
1543Begin_Macro(source)
1544../../../tutorials/hist/hist049_Graphics_candle_plot.C
1545End_Macro
1546
1547\anchor HP140b
1548#### The VIOLIN option
1549
1550<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1551that also encodes the pdf information at each point.
1552
1553
1554Quartiles and mean are also represented at each point, with a marker
1555and two lines.
1556
1557In this implementation a TH2 is considered as a collection of TH1 along
1558X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1559
1560#### What a violin is made of
1561
1562\since **ROOT version 6.09/02**
1563
1564##### The histogram
1565The histogram is typically drawn to both directions with respect to the middle-line of the
1566corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1567one side (h=1, or h=2).
1568The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1569histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1570be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1571A solid fill style is recommended.
1572
1573\since **ROOT version 6.11/01**
1574
1575Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1576violin can be influenced. Activated, the height of the bins of the individual violins will be
1577scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1578Deactivated, the height of the bin with the maximum content of each individual violin is
1579set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1580in the running program. Default is true. Scaling between multiple violin-charts
1581(using "same" or THStack) is not supported, yet.
1582
1583##### The zero indicator line
1584Typical for violin charts is a line in the background over the whole histogram indicating
1585the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1586will always be the same as the fill-color of the histogram.
1587
1588##### The Mean
1589The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1590
1591##### Whiskers
1592The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1593difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1594the whiskers will be forced to be solid (usually hashed)
1595
1596##### Points
1597The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1598better whisker definition (w=2) and outliers (p=1).
1599
1600##### Other options
1601It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1602including a box-plot.
1603
1604#### How to use the violin-plots drawing option
1605
1606There are two predefined violin-plot representations:
1607 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1608 zero indicator line)
1609 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1610
1611A solid fill style is recommended for this plot (as opposed to a hollow or
1612hashed style).
1613
1614Begin_Macro(source)
1615{
1616 auto c1 = new TCanvas("c1","c1",600,400);
1617 Int_t nx(6), ny(40);
1618 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1619 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1620 TF1 f1("f1", "gaus", +0,0 +4.0);
1621 double x,y;
1622 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1623 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1624 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1625 for(Int_t i=0; i<10000; ++i){
1626 x = xc;
1627 y = f1.GetRandom();
1628 hviolin->Fill(x, y);
1629 }
1630 }
1631 hviolin->SetFillColor(kGray);
1632 hviolin->SetMarkerStyle(20);
1633 hviolin->SetMarkerSize(0.5);
1634 hviolin->Draw("VIOLIN");
1635 c1->Update();
1636}
1637End_Macro
1638
1639The next example illustrates a time development of a certain value:
1640
1641Begin_Macro(source)
1642../../../tutorials/hist/hist047_Graphics_candle_decay.C
1643End_Macro
1644
1645
1646\anchor HP15
1647### The TEXT and TEXTnn Option
1648
1649
1650For each bin the content is printed. The text attributes are:
1651
1652- text font = current TStyle font (`gStyle->SetTextFont()`).
1653- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1654 with the option `TEXT` the marker size can be changed with
1655 `h->SetMarkerSize(markersize)`).
1656- text color = marker color.
1657
1658By default the format `g` is used. This format can be redefined
1659by calling `gStyle->SetPaintTextFormat()`.
1660
1661It is also possible to use `TEXTnn` in order to draw the text with
1662the angle `nn` (`0 < nn <= 90`).
1663
1664For 2D histograms the text is plotted in the center of each non empty cells.
1665It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1666or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1667position equal to the bin content.
1668
1669For 2D histograms when the option "E" (errors) is combined with the option
1670text ("TEXTE"), the error for each bin is also printed.
1671
1672Begin_Macro(source)
1673{
1674 auto c01 = new TCanvas("c01","c01",700,400);
1675 c01->Divide(2,1);
1676 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1677 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1678 float px, py;
1679 for (Int_t i = 0; i < 25000; i++) {
1680 gRandom->Rannor(px,py);
1681 htext1->Fill(px,0.1);
1682 htext2->Fill(px,5*py,0.1);
1683 }
1684 gStyle->SetPaintTextFormat("4.1f m");
1685 htext2->SetMarkerSize(1.8);
1686 c01->cd(1);
1687 htext2->Draw("TEXT45");
1688 c01->cd(2);
1689 htext1->Draw();
1690 htext1->Draw("HIST TEXT0 SAME");
1691}
1692End_Macro
1693
1694\since **ROOT version 6.07/07:**
1695
1696In case several histograms are drawn on top ot each other (using option `SAME`),
1697the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1698text position in each cell, in percentage of the bin width.
1699
1700Begin_Macro(source)
1701{
1702 auto c03 = new TCanvas("c03","c03",700,400);
1703 gStyle->SetOptStat(0);
1704 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1705 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1706 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1707 float px, py;
1708 for (Int_t i = 0; i < 25000; i++) {
1709 gRandom->Rannor(px,py);
1710 htext3->Fill(4*px,20*py,0.1);
1711 htext4->Fill(4*px,20*py,0.5);
1712 htext5->Fill(4*px,20*py,1.0);
1713 }
1714 htext4->SetMarkerSize(1.8);
1715 htext5->SetMarkerSize(1.8);
1716 htext5->SetMarkerColor(kRed);
1717 htext4->SetBarOffset(0.2);
1718 htext5->SetBarOffset(-0.2);
1719 htext3->Draw("COL");
1720 htext4->Draw("TEXT SAME");
1721 htext5->Draw("TEXT SAME");
1722}
1723End_Macro
1724
1725In the case of profile histograms it is possible to print the number
1726of entries instead of the bin content. It is enough to combine the
1727option "E" (for entries) with the option "TEXT".
1728
1729Begin_Macro(source)
1730{
1731 auto c02 = new TCanvas("c02","c02",700,400);
1732 c02->Divide(2,1);
1733 gStyle->SetPaintTextFormat("g");
1734
1735 auto profile = new TProfile("profile","profile",10,0,10);
1736 profile->SetMarkerSize(2.2);
1737 profile->Fill(0.5,1);
1738 profile->Fill(1.5,2);
1739 profile->Fill(2.5,3);
1740 profile->Fill(3.5,4);
1741 profile->Fill(4.5,5);
1742 profile->Fill(5.5,5);
1743 profile->Fill(6.5,4);
1744 profile->Fill(7.5,3);
1745 profile->Fill(8.5,2);
1746 profile->Fill(9.5,1);
1747 c02->cd(1); profile->Draw("HIST TEXT0");
1748 c02->cd(2); profile->Draw("HIST TEXT0E");
1749}
1750End_Macro
1751
1752\anchor HP16
1753### The CONTour options
1754
1755
1756The following contour options are supported:
1757
1758| Option | Description |
1759|----------|-----------------------------------------------------------------------------|
1760| "CONT" | Draw a contour plot (same as CONT0). |
1761| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1762| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1763| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1764| "CONT3" | Draw a contour plot using the same line style for all contours. |
1765| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1766
1767
1768The following example shows a 2D histogram plotted with the option
1769`CONTZ`. The option `CONT` draws a contour plot using surface
1770colors to distinguish contours. Combined with the option `CONT` (or
1771`CONT0`), the option `Z` allows to display the color palette
1772defined by `gStyle->SetPalette()`.
1773
1774Begin_Macro(source)
1775{
1776 auto c1 = new TCanvas("c1","c1",600,400);
1777 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1778 float px, py;
1779 for (Int_t i = 0; i < 25000; i++) {
1780 gRandom->Rannor(px,py);
1781 hcontz->Fill(px-1,5*py);
1782 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1783 }
1784 hcontz->Draw("CONTZ");
1785}
1786End_Macro
1787
1788The following example shows a 2D histogram plotted with the option
1789`CONT1Z`. The option `CONT1` draws a contour plot using the
1790line colors to distinguish contours. Combined with the option `CONT1`,
1791the option `Z` allows to display the color palette defined by
1792`gStyle->SetPalette()`.
1793
1794Begin_Macro(source)
1795{
1796 auto c1 = new TCanvas("c1","c1",600,400);
1797 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1798 float px, py;
1799 for (Int_t i = 0; i < 25000; i++) {
1800 gRandom->Rannor(px,py);
1801 hcont1->Fill(px-1,5*py);
1802 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1803 }
1804 hcont1->Draw("CONT1Z");
1805}
1806End_Macro
1807
1808The following example shows a 2D histogram plotted with the option
1809`CONT2`. The option `CONT2` draws a contour plot using the
1810line styles (1 to 5) to distinguish contours.
1811
1812Begin_Macro(source)
1813{
1814 auto c1 = new TCanvas("c1","c1",600,400);
1815 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1816 float px, py;
1817 for (Int_t i = 0; i < 25000; i++) {
1818 gRandom->Rannor(px,py);
1819 hcont2->Fill(px-1,5*py);
1820 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1821 }
1822 hcont2->Draw("CONT2");
1823}
1824End_Macro
1825
1826The following example shows a 2D histogram plotted with the option
1827`CONT3`. The option `CONT3` draws contour plot using the same line style for
1828all contours.
1829
1830Begin_Macro(source)
1831{
1832 auto c1 = new TCanvas("c1","c1",600,400);
1833 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1834 float px, py;
1835 for (Int_t i = 0; i < 25000; i++) {
1836 gRandom->Rannor(px,py);
1837 hcont3->Fill(px-1,5*py);
1838 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1839 }
1840 hcont3->SetLineStyle(kDotted);
1841 hcont3->Draw("CONT3");
1842}
1843End_Macro
1844
1845The following example shows a 2D histogram plotted with the option
1846`CONT4`. The option `CONT4` draws a contour plot using surface
1847colors to distinguish contours (`SURF` option at theta = 0). Combined
1848with the option `CONT` (or `CONT0`), the option `Z`
1849allows to display the color palette defined by `gStyle->SetPalette()`.
1850
1851Begin_Macro(source)
1852{
1853 auto c1 = new TCanvas("c1","c1",600,400);
1854 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1855 float px, py;
1856 for (Int_t i = 0; i < 25000; i++) {
1857 gRandom->Rannor(px,py);
1858 hcont4->Fill(px-1,5*py);
1859 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1860 }
1861 hcont4->Draw("CONT4Z");
1862}
1863End_Macro
1864
1865The default number of contour levels is 20 equidistant levels and can be changed
1866with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1867
1868\anchor HP16a
1869#### The LIST option
1870
1871When option `LIST` is specified together with option
1872`CONT`, the points used to draw the contours are saved in
1873`TGraph` objects:
1874
1875 h->Draw("CONT LIST");
1876 gPad->Update();
1877
1878The contour are saved in `TGraph` objects once the pad is painted.
1879Therefore to use this functionality in a macro, `gPad->Update()`
1880should be performed after the histogram drawing. Once the list is
1881built, the contours are accessible in the following way:
1882
1883 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1884 Int_t ncontours = contours->GetSize();
1885 TList *list = (TList*)contours->At(i);
1886
1887Where `i` is a contour number, and list contains a list of
1888`TGraph` objects.
1889For one given contour, more than one disjoint polyline may be generated.
1890The number of TGraphs per contour is given by:
1891
1892 list->GetSize();
1893
1894To access the first graph in the list one should do:
1895
1896 TGraph *gr1 = (TGraph*)list->First();
1897
1898
1899The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1900
1901Begin_Macro(source)
1902../../../tutorials/hist/hist102_TH2_contour_list.C
1903End_Macro
1904
1905\anchor HP16b
1906#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1907
1908The following options select the `CONT4` option and are useful for
1909sky maps or exposure maps (earth.C).
1910
1911| Option | Description |
1912|--------------|---------------------------------------------------------------|
1913| "AITOFF" | Draw a contour via an AITOFF projection.|
1914| "MERCATOR" | Draw a contour via an Mercator projection.|
1915| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1916| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1917
1918Begin_Macro(source)
1919../../../tutorials/visualisation/graphics/earth.C
1920End_Macro
1921
1922
1923\anchor HP17
1924### The LEGO options
1925
1926
1927In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1928is proportional to the cell content. The lego aspect is control with the
1929following options:
1930
1931| Option | Description |
1932|----------|-------------------------------------------------------------------|
1933| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1934| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1935| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1936| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1937| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1938| "0" | When used with any LEGO option, the empty bins are not drawn.|
1939
1940
1941See the limitations with [the option "SAME"](\ref HP060a).
1942
1943Line attributes can be used in lego plots to change the edges' style.
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO`. The option `LEGO` draws a lego plot using the hidden
1947lines removal technique.
1948
1949Begin_Macro(source)
1950{
1951 auto c2 = new TCanvas("c2","c2",600,400);
1952 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1953 float px, py;
1954 for (Int_t i = 0; i < 25000; i++) {
1955 gRandom->Rannor(px,py);
1956 hlego->Fill(px-1,5*py);
1957 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1958 }
1959 hlego->Draw("LEGO");
1960}
1961End_Macro
1962
1963The following example shows a 2D histogram plotted with the option
1964`LEGO1`. The option `LEGO1` draws a lego plot using the
1965hidden surface removal technique. Combined with any `LEGOn` option, the
1966option `0` allows to not drawn the empty bins.
1967
1968Begin_Macro(source)
1969{
1970 auto c2 = new TCanvas("c2","c2",600,400);
1971 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1972 float px, py;
1973 for (Int_t i = 0; i < 25000; i++) {
1974 gRandom->Rannor(px,py);
1975 hlego1->Fill(px-1,5*py);
1976 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1977 }
1978 hlego1->SetFillColor(kYellow);
1979 hlego1->Draw("LEGO1 0");
1980}
1981End_Macro
1982
1983The following example shows a 2D histogram plotted with the option
1984`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1985draws a lego plot using the hidden surface removal technique but doesn't draw
1986the border lines of each individual lego-bar. This is very useful for histograms
1987having many bins. With such histograms the option `LEGO1` gives a black
1988image because of the border lines. This option also works with stacked legos.
1989
1990Begin_Macro(source)
1991{
1992 auto c2 = new TCanvas("c2","c2",600,400);
1993 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1994 float px, py;
1995 for (Int_t i = 0; i < 25000; i++) {
1996 gRandom->Rannor(px,py);
1997 hlego3->Fill(px-1,5*py);
1998 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1999 }
2000 hlego3->SetFillColor(kRed);
2001 hlego3->Draw("LEGO3");
2002}
2003End_Macro
2004
2005The following example shows a 2D histogram plotted with the option
2006`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2007show the cell contents. Combined with the option `LEGO2`, the option
2008`Z` allows to display the color palette defined by
2009`gStyle->SetPalette()`.
2010
2011Begin_Macro(source)
2012{
2013 auto c2 = new TCanvas("c2","c2",600,400);
2014 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2015 float px, py;
2016 for (Int_t i = 0; i < 25000; i++) {
2017 gRandom->Rannor(px,py);
2018 hlego2->Fill(px-1,5*py);
2019 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2020 }
2021 hlego2->Draw("LEGO2Z");
2022}
2023End_Macro
2024
2025
2026
2027\anchor HP18
2028### The "SURFace" options
2029
2030
2031In a surface plot, cell contents are represented as a mesh.
2032The height of the mesh is proportional to the cell content.
2033
2034| Option | Description |
2035|----------|-------------------------------------------------------------------|
2036| "SURF" | Draw a surface plot using the hidden line removal technique.|
2037| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2038| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2039| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2040| "SURF4" | Draw a surface using the Gouraud shading technique.|
2041| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2042| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2043| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2044
2045
2046
2047See the limitations with [the option "SAME"](\ref HP060a).
2048
2049The following example shows a 2D histogram plotted with the option
2050`SURF`. The option `SURF` draws a lego plot using the hidden
2051lines removal technique.
2052
2053Begin_Macro(source)
2054{
2055 auto c2 = new TCanvas("c2","c2",600,400);
2056 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2057 float px, py;
2058 for (Int_t i = 0; i < 25000; i++) {
2059 gRandom->Rannor(px,py);
2060 hsurf->Fill(px-1,5*py);
2061 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2062 }
2063 hsurf->Draw("SURF");
2064}
2065End_Macro
2066
2067The following example shows a 2D histogram plotted with the option
2068`SURF1`. The option `SURF1` draws a surface plot using the
2069hidden surface removal technique. Combined with the option `SURF1`,
2070the option `Z` allows to display the color palette defined by
2071`gStyle->SetPalette()`.
2072
2073Begin_Macro(source)
2074{
2075 auto c2 = new TCanvas("c2","c2",600,400);
2076 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2077 float px, py;
2078 for (Int_t i = 0; i < 25000; i++) {
2079 gRandom->Rannor(px,py);
2080 hsurf1->Fill(px-1,5*py);
2081 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2082 }
2083 hsurf1->Draw("SURF1");
2084}
2085End_Macro
2086
2087The following example shows a 2D histogram plotted with the option
2088`SURF2`. The option `SURF2` draws a surface plot using colors
2089to show the cell contents. Combined with the option `SURF2`, the option
2090`Z` allows to display the color palette defined by
2091`gStyle->SetPalette()`.
2092
2093Begin_Macro(source)
2094{
2095 auto c2 = new TCanvas("c2","c2",600,400);
2096 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2097 float px, py;
2098 for (Int_t i = 0; i < 25000; i++) {
2099 gRandom->Rannor(px,py);
2100 hsurf2->Fill(px-1,5*py);
2101 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2102 }
2103 hsurf2->Draw("SURF2");
2104}
2105End_Macro
2106
2107The following example shows a 2D histogram plotted with the option
2108`SURF3`. The option `SURF3` draws a surface plot using the
2109hidden line removal technique with, in addition, a filled contour view drawn on the
2110top. Combined with the option `SURF3`, the option `Z` allows
2111to display the color palette defined by `gStyle->SetPalette()`.
2112
2113Begin_Macro(source)
2114{
2115 auto c2 = new TCanvas("c2","c2",600,400);
2116 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2117 float px, py;
2118 for (Int_t i = 0; i < 25000; i++) {
2119 gRandom->Rannor(px,py);
2120 hsurf3->Fill(px-1,5*py);
2121 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2122 }
2123 hsurf3->Draw("SURF3");
2124}
2125End_Macro
2126
2127The following example shows a 2D histogram plotted with the option
2128`SURF4`. The option `SURF4` draws a surface using the Gouraud
2129shading technique.
2130
2131Begin_Macro(source)
2132{
2133 auto c2 = new TCanvas("c2","c2",600,400);
2134 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2135 float px, py;
2136 for (Int_t i = 0; i < 25000; i++) {
2137 gRandom->Rannor(px,py);
2138 hsurf4->Fill(px-1,5*py);
2139 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2140 }
2141 hsurf4->SetFillColor(kOrange);
2142 hsurf4->Draw("SURF4");
2143}
2144End_Macro
2145
2146The following example shows a 2D histogram plotted with the option
2147`SURF5 CYL`. Combined with the option `SURF5`, the option
2148`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2149
2150Begin_Macro(source)
2151{
2152 auto c2 = new TCanvas("c2","c2",600,400);
2153 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2154 float px, py;
2155 for (Int_t i = 0; i < 25000; i++) {
2156 gRandom->Rannor(px,py);
2157 hsurf5->Fill(px-1,5*py);
2158 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2159 }
2160 hsurf5->Draw("SURF5 CYL");
2161}
2162End_Macro
2163
2164The following example shows a 2D histogram plotted with the option
2165`SURF7`. The option `SURF7` draws a surface plot using the
2166hidden surfaces removal technique with, in addition, a line contour view drawn on the
2167top. Combined with the option `SURF7`, the option `Z` allows
2168to display the color palette defined by `gStyle->SetPalette()`.
2169
2170Begin_Macro(source)
2171{
2172 auto c2 = new TCanvas("c2","c2",600,400);
2173 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2174 float px, py;
2175 for (Int_t i = 0; i < 25000; i++) {
2176 gRandom->Rannor(px,py);
2177 hsurf7->Fill(px-1,5*py);
2178 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2179 }
2180 hsurf7->Draw("SURF7");
2181}
2182End_Macro
2183
2184As shown in the following example, when a contour plot is painted on top of a
2185surface plot using the option `SAME`, the contours appear in 3D on the
2186surface.
2187
2188Begin_Macro(source)
2189{
2190 auto c20=new TCanvas("c20","c20",600,400);
2191 int NBins = 50;
2192 double d = 2;
2193 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2194 for (int bx = 1; bx <= NBins; ++bx) {
2195 for (int by = 1; by <= NBins; ++by) {
2196 double x = hsc->GetXaxis()->GetBinCenter(bx);
2197 double y = hsc->GetYaxis()->GetBinCenter(by);
2198 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2199 }
2200 }
2201 hsc->Draw("surf2");
2202 hsc->Draw("CONT1 SAME");
2203}
2204End_Macro
2205
2206
2207\anchor HP19
2208### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2209
2210
2211Legos and surfaces plots are represented by default in Cartesian coordinates.
2212Combined with any `LEGOn` or `SURFn` options the following
2213options allow to draw a lego or a surface in other coordinates systems.
2214
2215| Option | Description |
2216|----------|-------------------------------------------------------------------|
2217| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2218| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2219| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2220| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2221
2222
2223
2224<b>WARNING:</b> Axis are not drawn with these options.
2225
2226The following example shows the same histogram as a lego plot is the four
2227different coordinates systems.
2228
2229Begin_Macro(source)
2230{
2231 auto c3 = new TCanvas("c3","c3",600,400);
2232 c3->Divide(2,2);
2233 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2234 float px, py;
2235 for (Int_t i = 0; i < 25000; i++) {
2236 gRandom->Rannor(px,py);
2237 hlcc->Fill(px-1,5*py);
2238 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2239 }
2240 hlcc->SetFillColor(kYellow);
2241 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2242 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2243 hlpc->SetTitle("Polar coordinates");
2244 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2245 hlsc->SetTitle("Spherical coordinates");
2246 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2247 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2248}
2249End_Macro
2250
2251The following example shows the same histogram as a surface plot is the four different coordinates systems.
2252
2253Begin_Macro(source)
2254{
2255 auto c4 = new TCanvas("c4","c4",600,400);
2256 c4->Divide(2,2);
2257 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2258 float px, py;
2259 for (Int_t i = 0; i < 25000; i++) {
2260 gRandom->Rannor(px,py);
2261 hscc->Fill(px-1,5*py);
2262 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2263 }
2264 c4->cd(1); hscc->Draw("SURF1 CYL");
2265 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2266 hspc->SetTitle("Polar coordinates");
2267 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2268 hssc->SetTitle("Spherical coordinates");
2269 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2270 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2271}
2272End_Macro
2273
2274
2275\anchor HP20
2276### Base line for bar-charts and lego plots
2277
2278
2279By default the base line used to draw the boxes for bar-charts and lego plots is
2280the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2281option or with the command:
2282
2283 gStyle->SetHistMinimumZero();
2284
2285Begin_Macro(source)
2286{
2287 auto c5 = new TCanvas("c5","c5",700,400);
2288 c5->Divide(2,1);
2289 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2290 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2291 Int_t i;
2292 double x,y;
2293 hz1->SetFillColor(kBlue);
2294 hz2->SetFillColor(kBlue);
2295 for (i=0;i<10000;i++) {
2296 x = gRandom->Gaus(0,1);
2297 y = gRandom->Gaus(0,1);
2298 if (x>0) {
2299 hz1->Fill(x,1);
2300 hz2->Fill(x,y,1);
2301 } else {
2302 hz1->Fill(x,-1);
2303 hz2->Fill(x,y,-2);
2304 }
2305 }
2306 c5->cd(1); hz1->Draw("bar2 min0");
2307 c5->cd(2); hz2->Draw("lego1 min0");
2308}
2309End_Macro
2310
2311This option also works for horizontal plots. The example given in the section
2312["The bar chart option"](\ref HP100) appears as follow:
2313
2314Begin_Macro(source)
2315{
2316 int i;
2317 const Int_t nx = 8;
2318 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2319 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2320 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2321
2322 auto cbh = new TCanvas("cbh","cbh",400,600);
2323 cbh->SetGrid();
2324
2325 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2326 h1bh->SetFillColor(4);
2327 h1bh->SetBarWidth(0.4);
2328 h1bh->SetBarOffset(0.1);
2329 h1bh->SetStats(0);
2330 h1bh->SetMinimum(-5);
2331 h1bh->SetMaximum(5);
2332
2333 for (i=1; i<=nx; i++) {
2334 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2335 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2336 }
2337
2338 h1bh->Draw("hbar min0");
2339
2340 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2341 h2bh->SetFillColor(38);
2342 h2bh->SetBarWidth(0.4);
2343 h2bh->SetBarOffset(0.5);
2344 h2bh->SetStats(0);
2345 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2346
2347 h2bh->Draw("hbar min0 same");
2348}
2349End_Macro
2350
2351
2352\anchor HP20a
2353### TH2Poly Drawing
2354
2355
2356The following options are supported:
2357
2358| Option | Description |
2359|----------|-------------------------------------------------------------------|
2360| "SCAT" | Draw a scatter plot (legacy draw option).|
2361| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2362| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2363| "0" | When used with any COL options, the empty bins are not drawn.|
2364| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2365| "TEXTN" | Draw bin names as text.|
2366| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2367| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2368| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2369| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2370
2371
2372
2373`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2374shapes. The bins are defined as graphs. The following macro is a very simple
2375example showing how to book a TH2Poly and draw it.
2376
2377Begin_Macro(source)
2378{
2379 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2380 auto h2p = new TH2Poly();
2381 h2p->SetName("h2poly_name");
2382 h2p->SetTitle("h2poly_title");
2383 double px1[] = {0, 5, 6};
2384 double py1[] = {0, 0, 5};
2385 double px2[] = {0, -1, -1, 0};
2386 double py2[] = {0, 0, -1, 3};
2387 double px3[] = {4, 3, 0, 1, 2.4};
2388 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2389 h2p->AddBin(3, px1, py1);
2390 h2p->AddBin(4, px2, py2);
2391 h2p->AddBin(5, px3, py3);
2392 h2p->Fill(0.1, 0.01, 3);
2393 h2p->Fill(-0.5, -0.5, 7);
2394 h2p->Fill(-0.7, -0.5, 1);
2395 h2p->Fill(1, 3, 1.5);
2396 double fx[] = {0.1, -0.5, -0.7, 1};
2397 double fy[] = {0.01, -0.5, -0.5, 3};
2398 double fw[] = {3, 1, 1, 1.5};
2399 h2p->FillN(4, fx, fy, fw);
2400 h2p->Draw("col");
2401}
2402End_Macro
2403
2404Rectangular bins are a frequent case. The special version of
2405the `AddBin` method allows to define them more easily like
2406shown in the following example (hist037_TH2Poly_boxes.C).
2407
2408Begin_Macro(source)
2409../../../tutorials/hist/hist037_TH2Poly_boxes.C
2410End_Macro
2411
2412One `TH2Poly` bin can be a list of polygons. Such bins are defined
2413by calling `AddBin` with a `TMultiGraph`. The following example
2414shows a such case:
2415
2416Begin_Macro(source)
2417{
2418 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2419
2420 Int_t i, bin;
2421 const Int_t nx = 48;
2422 const char *states [nx] = {
2423 "alabama", "arizona", "arkansas", "california",
2424 "colorado", "connecticut", "delaware", "florida",
2425 "georgia", "idaho", "illinois", "indiana",
2426 "iowa", "kansas", "kentucky", "louisiana",
2427 "maine", "maryland", "massachusetts", "michigan",
2428 "minnesota", "mississippi", "missouri", "montana",
2429 "nebraska", "nevada", "new_hampshire", "new_jersey",
2430 "new_mexico", "new_york", "north_carolina", "north_dakota",
2431 "ohio", "oklahoma", "oregon", "pennsylvania",
2432 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2433 "texas", "utah", "vermont", "virginia",
2434 "washington", "west_virginia", "wisconsin", "wyoming"
2435 };
2436 Double_t pop[nx] = {
2437 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2438 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2439 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2440 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2441 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2442 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2443 };
2444
2445 Double_t lon1 = -130;
2446 Double_t lon2 = -65;
2447 Double_t lat1 = 24;
2448 Double_t lat2 = 50;
2449 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2450
2451 TFile::SetCacheFileDir(".");
2452 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2453
2454 TMultiGraph *mg;
2455 TKey *key;
2456 TIter nextkey(gDirectory->GetListOfKeys());
2457 while ((key = (TKey*)nextkey())) {
2458 TObject *obj = key->ReadObj();
2459 if (obj->InheritsFrom("TMultiGraph")) {
2460 mg = (TMultiGraph*)obj;
2461 bin = p->AddBin(mg);
2462 }
2463 }
2464
2465 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2466
2467 gStyle->SetOptStat(11);
2468 p->Draw("COLZ L");
2469}
2470End_Macro
2471
2472`TH2Poly` histograms can also be plotted using the GL interface using
2473the option "GLLEGO".
2474
2475\since **ROOT version 6.09/01**
2476
2477In some cases it can be useful to not draw the empty bins. the option "0"
2478combined with the option "COL" and "COLZ" allows to do that.
2479
2480Begin_Macro(source)
2481{
2482 auto chc = new TCanvas("chc","chc",600,400);
2483
2484 auto hc = new TH2Poly();
2485 hc->Honeycomb(0,0,.1,25,25);
2486 hc->SetName("hc");
2487 hc->SetTitle("Option COLZ 0");
2488 TRandom ran;
2489 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2490 hc->Draw("colz 0");
2491}
2492End_Macro
2493
2494\anchor HP21
2495### The SPEC option
2496
2497
2498This option allows to use the `TSpectrum2Painter` tools. See the full
2499documentation in `TSpectrum2Painter::PaintSpectrum`.
2500
2501
2502\anchor HP22
2503### Option "Z" : Adding the color palette on the right side of the pad
2504
2505
2506When this option is specified, a color palette with an axis indicating the value
2507of the corresponding color is drawn on the right side of the picture. In case,
2508not enough space is left, one can increase the size of the right margin by
2509calling `TPad::SetRightMargin()`. The attributes used to display the
2510palette axis values are taken from the Z axis of the object. For example, to
2511set the labels size on the palette axis do:
2512
2513 hist->GetZaxis()->SetLabelSize().
2514
2515<b>WARNING:</b> The palette axis is always drawn vertically.
2516
2517
2518\anchor HP23
2519### Setting the color palette
2520
2521
2522To change the color palette `TStyle::SetPalette` should be used, eg:
2523
2524 gStyle->SetPalette(ncolors,colors);
2525
2526For example the option `COL` draws a 2D histogram with cells
2527represented by a box filled with a color index which is a function
2528of the cell content.
2529If the cell content is N, the color index used will be the color number
2530in `colors[N]`, etc. If the maximum cell content is greater than
2531`ncolors`, all cell contents are scaled to `ncolors`.
2532
2533If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2534defined. This palette is recommended for pads, labels ...
2535
2536`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2537Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2538palette.
2539
2540Other pre-defined palettes with 255 colors are available when `colors == 0`.
2541The following value of `ncolors` give access to:
2542
2543
2544 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2545 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2546 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2547 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2548yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2549Radiator palette is used.
2550
2551
2552If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2553
2554The default palette defines:
2555
2556- index 0 to 9 : shades of grey
2557- index 10 to 19 : shades of brown
2558- index 20 to 29 : shades of blue
2559- index 30 to 39 : shades of red
2560- index 40 to 49 : basic colors
2561
2562The color numbers specified in the palette can be viewed by selecting
2563the item `colors` in the `VIEW` menu of the canvas tool bar.
2564The red, green, and blue components of a color can be changed thanks to
2565`TColor::SetRGB()`.
2566
2567\since **ROOT version 6.19/01**
2568
2569As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2570points as controlled by SetNdivisions.
2571If option "CJUST" is given labels and ticks are justified at the
2572color boundaries defined by the contour levels.
2573For more details see `TPaletteAxis`
2574
2575\anchor HP24
2576### Drawing a sub-range of a 2D histogram; the [cutg] option
2577
2578
2579Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2580histogram. One must create a graphical cut (mouse or C++) and specify the name
2581of the cut between `[]` in the `Draw()` option.
2582For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2583
2584 myhist->Draw("surf1 [cutg]");
2585
2586To invert the cut, it is enough to put a `-` in front of its name:
2587
2588 myhist->Draw("surf1 [-cutg]");
2589
2590It is possible to apply several cuts (`,` means logical AND):
2591
2592 myhist->Draw("surf1 [cutg1,cutg2]");
2593
2594Begin_Macro(source)
2595../../../tutorials/fit/fit2a.C
2596End_Macro
2597
2598\anchor HP25
2599### Drawing options for 3D histograms
2600
2601
2602| Option | Description |
2603|----------|-------------------------------------------------------------------|
2604| "SCAT" | Draw a scatter plot (legacy draw option).|
2605| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2606| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2607| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2608| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2609| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2610| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2611
2612Note that instead of `BOX` one can also use `LEGO`.
2613
2614By default, 3D histograms are drawn as a colored box plots.
2615
2616The following example shows a 3D histogram plotted as a scatter plot.
2617
2618Begin_Macro(source)
2619{
2620 auto c06 = new TCanvas("c06","c06",600,400);
2621 gStyle->SetOptStat(kFALSE);
2622 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2623 double x, y, z;
2624 for (Int_t i=0;i<10000;i++) {
2625 gRandom->Rannor(x, y);
2626 z = x*x + y*y;
2627 h3scat->Fill(x,y,z);
2628 }
2629 h3scat->Draw("SCAT"); // This a legacy draw option
2630}
2631End_Macro
2632
2633The following example shows a 3D histogram plotted with the option `BOX`.
2634
2635Begin_Macro(source)
2636{
2637 auto c16 = new TCanvas("c16","c16",600,400);
2638 gStyle->SetOptStat(kFALSE);
2639 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2640 double x, y, z;
2641 for (Int_t i=0;i<10000;i++) {
2642 gRandom->Rannor(x, y);
2643 z = x*x + y*y;
2644 h3box->Fill(x,y,z);
2645 }
2646 h3box->Draw("BOX");
2647}
2648End_Macro
2649
2650The following example shows a 3D histogram plotted with the option `BOX1`.
2651
2652Begin_Macro(source)
2653{
2654 auto c36 = new TCanvas("c36","c36",600,400);
2655 gStyle->SetOptStat(kFALSE);
2656 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2657 double x, y, z;
2658 for (Int_t i=0;i<10000;i++) {
2659 gRandom->Rannor(x, y);
2660 z = abs(sin(x)/x + cos(y)*y);
2661 h3box->Fill(x,y,z);
2662 }
2663 h3box->SetFillColor(9);
2664 h3box->Draw("BOX1");
2665}
2666End_Macro
2667
2668The following example shows a 3D histogram plotted with the option `BOX2`.
2669
2670Begin_Macro(source)
2671{
2672 auto c56 = new TCanvas("c56","c56",600,400);
2673 gStyle->SetOptStat(kFALSE);
2674 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2675 double x, y, z;
2676 for (Int_t i=0;i<10000;i++) {
2677 gRandom->Rannor(x, y);
2678 z = abs(sin(x)/x + cos(y)*y);
2679 h3box->Fill(x,y,z);
2680 }
2681 h3box->Draw("BOX2 Z");
2682}
2683End_Macro
2684
2685The following example shows a 3D histogram plotted with the option `BOX3`.
2686
2687Begin_Macro(source)
2688{
2689 auto c46 = new TCanvas("c46","c46",600,400);
2690 c46->SetFillColor(38);
2691 gStyle->SetOptStat(kFALSE);
2692 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2693 double x, y, z;
2694 for (Int_t i=0;i<10000;i++) {
2695 gRandom->Rannor(x, y);
2696 z = x*x + y*y;
2697 h3box->Fill(x,y,z);
2698 }
2699 h3box->Draw("BOX3");
2700}
2701End_Macro
2702
2703For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2704to the absolute value of the bin content. The bins with a negative content are
2705drawn with a X on each face of the box as shown in the following example:
2706
2707Begin_Macro(source)
2708{
2709 auto c = new TCanvas("c","c",600,400);
2710 gStyle->SetOptStat(kFALSE);
2711 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2712 h3box->Fill(0., 2., 2., 10.);
2713 h3box->Fill(2., 2., 2., 5.);
2714 h3box->Fill(2., 2., .5, 2.);
2715 h3box->Fill(2., 2., 3., -1.);
2716 h3box->Fill(3., 2., 2., -10.);
2717 h3box->SetFillColor(8);
2718 h3box->Draw("box1");
2719}
2720End_Macro
2721
2722The following example shows a 3D histogram plotted with the option `ISO`.
2723
2724Begin_Macro(source)
2725{
2726 auto c26 = new TCanvas("c26","c26",600,400);
2727 gStyle->SetOptStat(kFALSE);
2728 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2729 double x, y, z;
2730 for (Int_t i=0;i<10000;i++) {
2731 gRandom->Rannor(x, y);
2732 z = x*x + y*y;
2733 h3iso->Fill(x,y,z);
2734 }
2735 h3iso->SetFillColor(kCyan);
2736 h3iso->Draw("ISO");
2737}
2738End_Macro
2739
2740
2741\anchor HP26
2742### Drawing option for histograms' stacks
2743
2744
2745Stacks of histograms are managed with the `THStack`. A `THStack`
2746is a collection of `TH1` (or derived) objects. For painting only the
2747`THStack` containing `TH1` only or
2748`THStack` containing `TH2` only will be considered.
2749
2750By default, histograms are shown stacked:
2751
27521. The first histogram is paint.
27532. The sum of the first and second, etc...
2754
2755If the option `NOSTACK` is specified, the histograms are all paint in
2756the same pad as if the option `SAME` had been specified. This allows to
2757compute X and Y scales common to all the histograms, like
2758`TMultiGraph` does for graphs.
2759
2760If the option `PADS` is specified, the current pad/canvas is subdivided into
2761a number of pads equal to the number of histograms and each histogram is paint
2762into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2763`n` columns, automatically calculating the number of rows.
2764
2765The following example shows various types of stacks (hist023_THStack_simple.C).
2766
2767Begin_Macro(source)
2768../../../tutorials/hist/hist023_THStack_simple.C
2769End_Macro
2770
2771The option `nostackb` allows to draw the histograms next to each
2772other as bar charts:
2773
2774Begin_Macro(source)
2775{
2776 auto cst0 = new TCanvas("cst0","cst0",600,400);
2777 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2778
2779 auto h1 = new TH1F("h1","h1",10,-4,4);
2780 h1->FillRandom("gaus",20000);
2781 h1->SetFillColor(kRed);
2782 hs->Add(h1);
2783
2784 auto h2 = new TH1F("h2","h2",10,-4,4);
2785 h2->FillRandom("gaus",15000);
2786 h2->SetFillColor(kBlue);
2787 hs->Add(h2);
2788
2789 auto h3 = new TH1F("h3","h3",10,-4,4);
2790 h3->FillRandom("gaus",10000);
2791 h3->SetFillColor(kGreen);
2792 hs->Add(h3);
2793
2794 hs->Draw("nostackb");
2795 hs->GetXaxis()->SetNdivisions(-10);
2796 cst0->SetGridx();
2797}
2798End_Macro
2799
2800If at least one of the histograms in the stack has errors, the whole stack is
2801visualized by default with error bars. To visualize it without errors the
2802option `HIST` should be used.
2803
2804Begin_Macro(source)
2805{
2806 auto cst1 = new TCanvas("cst1","cst1",700,400);
2807 cst1->Divide(2,1);
2808
2809 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2810 hst11->Sumw2();
2811 hst11->FillRandom("gaus", 1000);
2812 hst11->SetFillColor(kViolet);
2813 hst11->SetLineColor(kViolet);
2814
2815 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2816 hst12->FillRandom("gaus", 500);
2817 hst12->SetFillColor(kBlue);
2818 hst12->SetLineColor(kBlue);
2819
2820 THStack st1("st1", "st1");
2821 st1.Add(hst11);
2822 st1.Add(hst12);
2823
2824 cst1->cd(1); st1.Draw();
2825 cst1->cd(2); st1.Draw("hist");
2826}
2827End_Macro
2828
2829\anchor HP27
2830### Drawing of 3D implicit functions
2831
2832
28333D implicit functions (`TF3`) can be drawn as iso-surfaces.
2834The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2835In the following example the options "FB" and "BB" suppress the
2836"Front Box" and "Back Box" around the plot.
2837
2838Begin_Macro(source)
2839{
2840 auto c2 = new TCanvas("c2","c2",600,400);
2841 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2842 f3->SetClippingBoxOn(0,0,0);
2843 f3->SetFillColor(30);
2844 f3->SetLineColor(15);
2845 f3->Draw("FBBB");
2846}
2847End_Macro
2848
2849
2850\anchor HP28
2851### Associated functions drawing
2852
2853
2854An associated function is created by `TH1::Fit`. More than on fitted
2855function can be associated with one histogram (see `TH1::Fit`).
2856
2857A `TF1` object `f1` can be added to the list of associated
2858functions of an histogram `h` without calling `TH1::Fit`
2859simply doing:
2860
2861 h->GetListOfFunctions()->Add(f1);
2862
2863or
2864
2865 h->GetListOfFunctions()->Add(f1,someoption);
2866
2867To retrieve a function by name from this list, do:
2868
2869 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2870
2871or
2872
2873 TF1 *f1 = h->GetFunction(name);
2874
2875Associated functions are automatically painted when an histogram is drawn.
2876To avoid the painting of the associated functions the option `HIST`
2877should be added to the list of the options used to paint the histogram.
2878
2879
2880\anchor HP29
2881### Drawing using OpenGL
2882
2883
2884The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2885graphics library. The plotting options start with `GL` keyword.
2886In addition, in order to inform canvases that OpenGL should be used to render
28873D representations, the following option should be set:
2888
2889 gStyle->SetCanvasPreferGL(true);
2890
2891
2892\anchor HP29a
2893#### General information: plot types and supported options
2894
2895The following types of plots are provided:
2896
2897For lego plots the supported options are:
2898
2899| Option | Description |
2900|----------|-------------------------------------------------------------------|
2901| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2902| "GLLEGO2"| Bins with color levels.|
2903| "GLLEGO3"| Cylindrical bars.|
2904
2905
2906
2907Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2908In polar only Z axis can be logarithmic, in cylindrical only Y.
2909
2910For surface plots (`TF2` and `TH2`) the supported options are:
2911
2912| Option | Description |
2913|-----------|------------------------------------------------------------------|
2914| "GLSURF" | Draw a surface.|
2915| "GLSURF1" | Surface with color levels|
2916| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2917| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2918| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2919
2920
2921
2922The surface painting in cartesian coordinates supports logarithmic scales along
2923X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2924in cylindrical coordinates only the Y axis.
2925
2926Additional options to SURF and LEGO - Coordinate systems:
2927
2928| Option | Description |
2929|----------|-------------------------------------------------------------------|
2930| " " | Default, cartesian coordinates system.|
2931| "POL" | Polar coordinates system.|
2932| "CYL" | Cylindrical coordinates system.|
2933| "SPH" | Spherical coordinates system.|
2934
2935
2936
2937\anchor HP290
2938#### TH3 as color boxes
2939
2940The supported option is:
2941
2942| Option | Description |
2943|----------|-------------------------------------------------------------------|
2944| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2945
2946
2947
2948\anchor HP29b
2949#### TH3 as boxes (spheres)
2950
2951The supported options are:
2952
2953| Option | Description |
2954|----------|-------------------------------------------------------------------|
2955| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2956| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2957
2958
2959
2960\anchor HP29c
2961#### TH3 as iso-surface(s)
2962
2963The supported option is:
2964
2965| Option | Description |
2966|----------|-------------------------------------------------------------------|
2967| "GLISO" | TH3 is drawn using iso-surfaces.|
2968
2969
2970
2971\anchor HP29d
2972#### TF3 (implicit function)
2973
2974The supported option is:
2975
2976| Option | Description |
2977|----------|-------------------------------------------------------------------|
2978| "GL" | Draw a TF3.|
2979
2980
2981
2982\anchor HP29e
2983#### Parametric surfaces
2984
2985glparametric.C shows how to create parametric equations and visualize the surface.
2986
2987\anchor HP29f
2988#### Interaction with the plots
2989
2990All the interactions are implemented via standard methods
2991`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2992interactions with the OpenGL plots are possible only when the mouse cursor is
2993in the plot's area (the plot's area is the part of a the pad occupied by
2994gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2995pad interaction is performed.
2996
2997\anchor HP29g
2998#### Selectable parts
2999
3000Different parts of the plot can be selected:
3001
3002- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
3003 if the dynamic slicing by this plane is supported, and it's highlighted in red,
3004 if the dynamic slicing is not supported.
3005- The plot itself:
3006 On surfaces, the selected surface is outlined in red. (TF3 and
3007 ISO are not outlined). On lego plots, the selected bin is
3008 highlighted. The bin number and content are displayed in pad's
3009 status bar. In box plots, the box or sphere is highlighted and
3010 the bin info is displayed in pad's status bar.
3011
3012
3013\anchor HP29h
3014#### Rotation and zooming
3015
3016
3017- Rotation:
3018 When the plot is selected, it can be rotated by pressing and
3019 holding the left mouse button and move the cursor.
3020- Zoom/Unzoom:
3021 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3022
3023
3024\anchor HP29i
3025#### Panning
3026
3027The selected plot can be moved in a pad's area by pressing and
3028holding the left mouse button and the shift key.
3029
3030\anchor HP29j
3031#### Box cut
3032
3033Surface, iso, box, TF3 and parametric painters support box cut by
3034pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3035area. That will display a transparent box, cutting away part of the
3036surface (or boxes) in order to show internal part of plot. This box
3037can be moved inside the plot's area (the full size of the box is
3038equal to the plot's surrounding box) by selecting one of the box
3039cut axes and pressing the left mouse button to move it.
3040
3041\anchor HP29k
3042#### Plot specific interactions (dynamic slicing etc.)
3043
3044Currently, all gl-plots support some form of slicing. When back plane
3045is selected (and if it's highlighted in green) you can press and hold
3046left mouse button and shift key and move this back plane inside
3047plot's area, creating the slice. During this "slicing" plot becomes
3048semi-transparent. To remove all slices (and projected curves for
3049surfaces) double click with left mouse button in a plot's area.
3050
3051\anchor HP29l
3052#### Surface with option "GLSURF"
3053
3054The surface profile is displayed on the slicing plane.
3055The profile projection is drawn on the back plane
3056by pressing `'p'` or `'P'` key.
3057
3058\anchor HP29m
3059#### TF3
3060
3061The contour plot is drawn on the slicing plane. For TF3 the color
3062scheme can be changed by pressing 's' or 'S'.
3063
3064\anchor HP29n
3065#### Box
3066
3067The contour plot corresponding to slice plane position is drawn in real time.
3068
3069\anchor HP29o
3070#### Iso
3071
3072Slicing is similar to "GLBOX" option.
3073
3074\anchor HP29p
3075#### Parametric plot
3076
3077No slicing. Additional keys: 's' or 'S' to change color scheme -
3078about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3079increase number of polygons ('l' for "level" of details), 'w' or 'W'
3080to show outlines ('w' for "wireframe").
3081
3082\anchor HP30
3083#### Highlight mode for histogram
3084
3085\since **ROOT version 6.15/01**
3086
3087\image html hlHisto3_top.gif "Highlight mode"
3088
3089Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3090highlight mode is on, mouse movement over the bin will be represented
3091graphically. Bin will be highlighted as "bin box" (presented by box
3092object). Moreover, any highlight (change of bin) emits signal
3093`TCanvas::Highlighted()` which allows the user to react and call their own
3094function. For a better understanding see also the tutorial `hist043` to `hist046`
3095located in `$ROOTSYS/tutorials/hist/`.
3096
3097Highlight mode is switched on/off by `TH1::SetHighlight()` function
3098or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3099whether the highlight mode enabled or disabled, default it is disabled.
3100
3101~~~ {.cpp}
3102 root [0] .x $ROOTSYS/tutorials/hsimple.C
3103 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3104 root [2] hpx->IsHighlight()
3105 (bool) true
3106~~~
3107
3108\image html hlsimple_nofun.gif "Highlight mode for histogram"
3109
3110\anchor HP30a
3111#### Highlight mode and user function
3112
3113The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3114emitted if there is a highlight bin and call user function via signal
3115and slot communication mechanism. `TCanvas::Highlighted()` is similar
3116`TCanvas::Picked()`
3117
3118- when selected object (histogram as a whole) is different from previous
3119then emit `Picked()` signal
3120- when selected (highlighted) bin from histogram is different from previous
3121then emit `Highlighted()` signal
3122
3123Any user function (or functions) has to be defined
3124`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3125In example (see below) has name `PrintInfo()`. All parameters of user
3126function are taken from
3127
3128 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3129
3130- `pad` is pointer to pad with highlighted histogram
3131- `obj` is pointer to highlighted histogram
3132- `x` is highlighted x bin for 1D histogram
3133- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3134
3135Example how to create a connection from any `TCanvas` object to a user
3136`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3137
3138 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3139 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3140
3141or use non-static "simplified" function
3142`TCanvas::HighlightConnect(const char *slot)`
3143
3144 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3145
3146NOTE the signal and slot string must have a form
3147"(TVirtualPad*,TObject*,Int_t,Int_t)"
3148
3149 root [0] .x $ROOTSYS/tutorials/hsimple.C
3150 root [1] hpx->SetHighlight(kTRUE)
3151 root [2] .x hlprint.C
3152
3153file `hlprint.C`
3154~~~ {.cpp}
3155void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3156{
3157 auto h = (TH1F *)obj;
3158 if (!h->IsHighlight()) // after highlight disabled
3159 h->SetTitle("highlight disable");
3160 else
3161 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3162 h->GetBinCenter(x), h->GetBinContent(x)));
3163 pad->Update();
3164}
3165
3166void hlprint()
3167{
3168 if (!gPad) return;
3169 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3170}
3171~~~
3172
3173\image html hlsimple.gif "Highlight mode and simple user function"
3174
3175For more complex demo please see for example tree200_temperature.C file.
3176
3177*/
3178
3180
3183
3184const Int_t kNMAX = 2000;
3185
3186const Int_t kMAXCONTOUR = 104;
3188
3189static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3190
3212
3213
3214////////////////////////////////////////////////////////////////////////////////
3215/// Default constructor.
3216
3218{
3219 fH = nullptr;
3220 fXaxis = nullptr;
3221 fYaxis = nullptr;
3222 fZaxis = nullptr;
3223 fFunctions = nullptr;
3224 fNcuts = 0;
3225 fStack = nullptr;
3226 fShowProjection = 0;
3227 fShowProjection2 = 0;
3228 fShowOption = "";
3229 for (int i=0; i<kMaxCuts; i++) {
3230 fCuts[i] = nullptr;
3231 fCutsOpt[i] = 0;
3232 }
3233 fXHighlightBin = -1;
3234 fYHighlightBin = -1;
3235 fCurrentF3 = nullptr;
3236
3237 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3238 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3239 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3240 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3241 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3242 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3243 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3244 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3245 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3246 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3247 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3248 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3249 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3250 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3251 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3252 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3253 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3254 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3255 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3256 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3257 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3258}
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// destructor.
3262
3266
3267////////////////////////////////////////////////////////////////////////////////
3268/// Compute the distance from the point px,py to a line.
3269///
3270/// Compute the closest distance of approach from point px,py to elements of
3271/// an histogram. The distance is computed in pixels units.
3272///
3273/// Algorithm: Currently, this simple model computes the distance from the mouse
3274/// to the histogram contour only.
3275
3277{
3278
3279 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3280
3281 const Int_t big = 9999;
3282 const Int_t kMaxDiff = 7;
3283
3284 if (fPie)
3285 return fPie->DistancetoPrimitive(px, py);
3286
3287 Double_t x = gPad->AbsPixeltoX(px);
3288 Double_t x1 = gPad->AbsPixeltoX(px+1);
3289
3290 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3291 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3292 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3293 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3294 Int_t curdist = big;
3295 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3296 Bool_t dsame;
3297 TObject *PadPointer = gPad->GetPadPointer();
3298 if (!PadPointer) return 0;
3299 TString doption = PadPointer->GetDrawOption();
3300 Double_t factor = 1;
3301 if (fH->GetNormFactor() != 0) {
3302 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3303 }
3304 // return if point is not in the histogram area
3305
3306 // If a 3D view exists, check distance to axis
3307 TView *view = gPad->GetView();
3308 Int_t d1,d2,d3;
3309 if (view && Hoption.Contour != 14) {
3310 Double_t ratio;
3311 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3312 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3313 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3314 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3315 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3316 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3317 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3318 goto FUNCTIONS;
3319 }
3320 // check if point is close to an axis
3321 doption.ToLower();
3322 dsame = kFALSE;
3323 if (doption.Contains("same")) dsame = kTRUE;
3324
3325 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3326 if (doption.Contains("y+")) {
3327 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3328 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3329 if (!dsame) {
3330 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3331 else gPad->SetSelected(fXaxis);
3332 return 0;
3333 }
3334 }
3335 } else {
3336 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3337 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3338 if (!dsame) {
3339 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3340 else gPad->SetSelected(fXaxis);
3341 return 0;
3342 }
3343 }
3344 }
3345
3346 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3347 if (doption.Contains("x+")) {
3348 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3349 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3350 if (!dsame) {
3351 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3352 else gPad->SetSelected(fYaxis);
3353 return 0;
3354 }
3355 }
3356 } else {
3357 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3358 if (yxaxis < puymin) yxaxis = puymin;
3359 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3360 if (!dsame) {
3361 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3362 else gPad->SetSelected(fYaxis);
3363 return 0;
3364 }
3365 }
3366 }
3367
3368 if (fH->IsHighlight()) { // only if highlight is enable
3369 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3370 HighlightBin(px, py);
3371 }
3372
3373 // if object is 2D or 3D return this object
3374 if (fH->GetDimension() == 2) {
3375 if (fH->InheritsFrom(TH2Poly::Class())) {
3376 TH2Poly *th2 = (TH2Poly*)fH;
3378 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3379 Double_t pxu = gPad->AbsPixeltoX(px);
3380 Double_t pyu = gPad->AbsPixeltoY(py);
3381 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3382 curdist = big;
3383 goto FUNCTIONS;
3384 } else {
3385 Int_t bin = th2->FindBin(pxu, pyu);
3386 if (bin>0) curdist = 1;
3387 else curdist = big;
3388 goto FUNCTIONS;
3389 }
3390 }
3391 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3392 if ( px > puxmin + delta2
3393 && px < puxmax - delta2
3394 && py > puymax + delta2
3395 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3396 }
3397
3398 // point is inside histogram area. Find channel number
3399 if (gPad->IsVertical()) {
3400 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3401 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3402 Double_t binval = factor*fH->GetBinContent(bin);
3403 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3404 if (binval == 0 && pybin < puymin) pybin = 10000;
3405 // special case if more than one bin for the pixel
3406 if (binsup-bin>1) {
3407 Double_t binvalmin, binvalmax;
3408 binvalmin=binval;
3409 binvalmax=binval;
3410 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3411 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3412 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3413 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3414 }
3415 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3416 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3417 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3418 }
3419 if (bin != binsup) { // Mouse on bin border
3420 Double_t binsupval = factor*fH->GetBinContent(binsup);
3421 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3422 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3423 }
3424 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3425 } else {
3426 Double_t y = gPad->AbsPixeltoY(py);
3427 Double_t y1 = gPad->AbsPixeltoY(py+1);
3428 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3429 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3430 Double_t binval = factor*fH->GetBinContent(bin);
3431 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3432 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3433 // special case if more than one bin for the pixel
3434 if (binsup-bin>1) {
3435 Double_t binvalmin, binvalmax;
3436 binvalmin=binval;
3437 binvalmax=binval;
3438 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3439 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3440 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3441 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3442 }
3443 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3444 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3445 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3446 }
3447 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3448 }
3449 // Loop on the list of associated functions and user objects
3450FUNCTIONS:
3451 TObject *f;
3452 TIter next(fFunctions);
3453 while ((f = (TObject*) next())) {
3454 Int_t dist;
3455 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3456 else dist = f->DistancetoPrimitive(px,py);
3457 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3458 }
3459 return curdist;
3460}
3461
3462////////////////////////////////////////////////////////////////////////////////
3463/// Display a panel with all histogram drawing options.
3464
3466{
3467
3468 gCurrentHist = fH;
3469 if (!gPad) {
3470 Error("DrawPanel", "need to draw histogram first");
3471 return;
3472 }
3474 editor->Show();
3475 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3476 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3477}
3478
3480protected:
3481 Int_t px1 = 0, py1 = 0;
3482 Double_t fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
3483
3484public:
3486 {
3487 px1 = px;
3488 py1 = py;
3489 fX1 = fX2 = parent.PadtoX(parent.AbsPixeltoX(px));
3490 fY1 = fY2 = parent.PadtoY(parent.AbsPixeltoY(py));
3491 }
3492
3493 void MovePoint(TVirtualPad &parent, Int_t px, Int_t py)
3494 {
3495 if (TMath::Abs(px1 - px) > 5 && TMath::Abs(py1 - py) > 5) {
3496 fX2 = parent.PadtoX(parent.AbsPixeltoX(px));
3497 fY2 = parent.PadtoY(parent.AbsPixeltoY(py));
3498 const char *opt = parent.OpaqueMoving() ? "izoombox" : "ilzoombox";
3499 parent.PaintBox(fX1, fY1, fX2, fY2, opt);
3500 parent.UpdateAsync();
3501 }
3502 }
3503
3504 void ChangeRange(TAxis *xaxis, TAxis *yaxis)
3505 {
3510 if (x1 < x2 && y1 < y2) {
3511 xaxis->SetRangeUser(x1, x2);
3512 yaxis->SetRangeUser(y1, y2);
3513 }
3514 }
3515
3516};
3517
3519public:
3521 Double_t xlow = 0, xup = 1, y0 = 0, factor = 1.;
3522};
3523
3524////////////////////////////////////////////////////////////////////////////////
3525/// Execute the actions corresponding to `event`.
3526///
3527/// This function is called when a histogram is clicked with the locator at
3528/// the pixel position px,py.
3529
3531{
3532 if (!gPad || !gPad->IsEditable())
3533 return;
3534
3535 if (fPie) {
3536 fPie->ExecuteEvent(event, px, py);
3537 return;
3538 }
3539
3540 auto &parent = *gPad;
3541
3542 // come here if we have a lego/surface in the pad
3543 TView *view = parent.GetView();
3544
3545 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3546 view->ExecuteRotateView(event, px, py);
3547 return;
3548 }
3549 Bool_t opaque = parent.OpaqueMoving();
3550
3551 TAxis *xaxis = fH->GetXaxis();
3552 TAxis *yaxis = fH->GetYaxis();
3553 Int_t dimension = fH->GetDimension();
3554
3555 // In case of option SAME the axis must be the ones of the first drawn histogram
3556 TString hopt = fH->GetDrawOption();
3557 hopt.ToLower();
3558 if (hopt.Index("same") >= 0) {
3559 TIter next(parent.GetListOfPrimitives());
3560 while (auto obj = next()) {
3561 if (auto h1 = dynamic_cast<TH1 *>(obj)) {
3562 xaxis = h1->GetXaxis();
3563 yaxis = h1->GetYaxis();
3564 break;
3565 }
3566 }
3567 }
3568
3569 auto zoombox = parent.GetInteractive<TZoomInteractive>(this);
3570 auto h1edit = parent.GetInteractive<TEditInteractive>(this);
3571
3572 switch (event) {
3573
3574 case kButton1Down:
3575 if (dimension == 2)
3576 zoombox = parent.MakeInteractive<TZoomInteractive>(this, parent, px, py);
3577 // No break !!!
3578
3579 case kMouseMotion:
3580
3581 if (fShowProjection) {
3582 ShowProjection3(px,py);
3583 break;
3584 }
3585
3586 parent.SetCursor(kPointer);
3587 if ((dimension == 1) && gROOT->GetEditHistograms()) {
3588 h1edit = parent.MakeInteractive<TEditInteractive>(this);
3589
3590 Double_t baroffset = Hoption.Bar ? fH->GetBarOffset() : 0;
3591 Double_t barwidth = Hoption.Bar ? fH->GetBarWidth() : 1;
3592 h1edit->bin = fXaxis->FindFixBin(parent.PadtoX(parent.AbsPixeltoX(px)));
3593 Double_t binwidth = fXaxis->GetBinWidth(h1edit->bin);
3594 h1edit->xlow = fXaxis->GetBinLowEdge(h1edit->bin) + baroffset*binwidth;
3595 h1edit->xup = h1edit->xlow + barwidth*binwidth;
3596 h1edit->y0 = fH->GetBinContent(h1edit->bin);
3597 h1edit->factor = fH->GetNormFactor() / fH->GetSumOfWeights();
3598 if (!h1edit->factor)
3599 h1edit->factor = 1.;
3600
3601 parent.SetCursor(kArrowVer);
3602 }
3603
3604 break;
3605
3606 case kButton1Motion:
3607
3608 if ((dimension == 1) && h1edit) {
3609 Double_t yup = parent.PadtoY(parent.AbsPixeltoY(py)) / h1edit->factor;
3610 fH->SetBinContent(h1edit->bin, yup);
3611
3612 if (!opaque) {
3613 parent.PaintBox(parent.XtoPad(h1edit->xlow), parent.YtoPad(h1edit->y0), parent.XtoPad(h1edit->xup), parent.YtoPad(yup), "ilh1edit"); // Draw the new box
3614 parent.UpdateAsync();
3615 } else
3616 parent.Modified();
3617 }
3618
3619 if (zoombox && dimension == 2)
3620 zoombox->MovePoint(*gPad, px, py);
3621
3622 break;
3623
3624 case kWheelUp:
3625
3626 if (dimension == 2) {
3627 Int_t bin1 = TMath::Max(xaxis->GetFirst() + 1, 1);
3628 Int_t bin2 = TMath::Min(xaxis->GetLast() - 1, xaxis->GetNbins());
3629 if (bin2 > bin1)
3630 xaxis->SetRange(bin1, bin2);
3631 bin1 = TMath::Max(yaxis->GetFirst() + 1, 1);
3632 bin2 = TMath::Min(yaxis->GetLast() - 1, yaxis->GetNbins());
3633 if (bin2 > bin1)
3634 yaxis->SetRange(bin1,bin2);
3635 }
3636 parent.Modified();
3637 parent.Update();
3638
3639 break;
3640
3641 case kWheelDown:
3642
3643 if (dimension == 2) {
3644 Int_t bin1 = TMath::Max(xaxis->GetFirst() - 1, 1);
3645 Int_t bin2 = TMath::Min(xaxis->GetLast() + 1, xaxis->GetNbins());
3646 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3647 if (bin2 > bin1)
3648 xaxis->SetRange(bin1, bin2);
3649 if (resetXaxisRange)
3651 bin1 = TMath::Max(yaxis->GetFirst() - 1, 1);
3652 bin2 = TMath::Min(yaxis->GetLast() + 1, yaxis->GetNbins());
3653 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3654 if (bin2 > bin1)
3655 yaxis->SetRange(bin1, bin2);
3656 if (resetYaxisRange)
3658 }
3659 parent.Modified();
3660 parent.Update();
3661
3662 break;
3663
3664 case kButton1Up:
3665 if ((dimension == 1) && h1edit) {
3666 PaintInit(); // recalculate Hparam structure and recalculate range
3667 // might resize pad pixmap so should be called before any paint routine
3669 }
3670 if ((dimension == 2) && zoombox)
3671 zoombox->ChangeRange(xaxis, yaxis);
3672 parent.FreeInteractive(this); // remove interactive object
3673 parent.Modified();
3674
3675 break;
3676
3677 case kButton1Locate:
3678
3679 ExecuteEvent(kButton1Down, px, py);
3680
3681 while (true) {
3682 px = py = 0;
3683 event = parent.GetCanvasImp()->RequestLocator(px, py);
3684
3686
3687 if (event != -1) { // button is released
3688 ExecuteEvent(kButton1Up, px, py);
3689 return;
3690 }
3691 }
3692 }
3693}
3694
3695////////////////////////////////////////////////////////////////////////////////
3696/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3697
3699{
3700 // Check if fH contains a TGraphDelaunay2D
3701 TList *hl = fH->GetListOfFunctions();
3702 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3703 // try with the old painter
3704 TGraphDelaunay *dtOld = nullptr;
3705 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3706
3707 if (!dt && !dtOld) return nullptr;
3708
3709 gCurrentHist = fH;
3710
3711 if (!fGraph2DPainter)
3712 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3713
3714 return fGraph2DPainter->GetContourList(contour);
3715}
3716
3717////////////////////////////////////////////////////////////////////////////////
3718/// Display the histogram info (bin number, contents, integral up to bin
3719/// corresponding to cursor position px,py.
3720
3722{
3723
3724 if (!gPad) return (char*)"";
3725
3726 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3727 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3728 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3729 TString drawOption = fH->GetDrawOption();
3730 drawOption.ToLower();
3731 Double_t xmin, xmax, uxmin,uxmax;
3732 Double_t ymin, ymax, uymin,uymax;
3733 if (fH->GetDimension() == 2) {
3734 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3735 uxmin=gPad->GetUxmin();
3736 uxmax=gPad->GetUxmax();
3739 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3740 uymin=gPad->GetUymin();
3741 uymax=gPad->GetUymax();
3744 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3745 }
3746 }
3747 Int_t binx,biny,binmin=0,binx1;
3748 if (gPad->IsVertical()) {
3749 binx = fXaxis->FindFixBin(x);
3750 if (drawOption.Index("same") >= 0) {
3751 TH1 *h1;
3752 TIter next(gPad->GetListOfPrimitives());
3753 while ((h1 = (TH1 *)next())) {
3754 if (!h1->InheritsFrom(TH1::Class())) continue;
3755 binmin = h1->GetXaxis()->GetFirst();
3756 break;
3757 }
3758 } else {
3759 binmin = fXaxis->GetFirst();
3760 }
3761 binx1 = fXaxis->FindFixBin(x1);
3762 // special case if more than 1 bin in x per pixel
3763 if (binx1-binx>1 && fH->GetDimension() == 1) {
3764 Double_t binval=fH->GetBinContent(binx);
3765 Int_t binnear=binx;
3766 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3767 Double_t binvaltmp = fH->GetBinContent(ibin);
3768 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3769 binval=binvaltmp;
3770 binnear=ibin;
3771 }
3772 }
3773 binx = binnear;
3774 }
3775 } else {
3776 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3777 binx = fXaxis->FindFixBin(y);
3778 if (drawOption.Index("same") >= 0) {
3779 TH1 *h1;
3780 TIter next(gPad->GetListOfPrimitives());
3781 while ((h1 = (TH1 *)next())) {
3782 if (!h1->InheritsFrom(TH1::Class())) continue;
3783 binmin = h1->GetXaxis()->GetFirst();
3784 break;
3785 }
3786 } else {
3787 binmin = fXaxis->GetFirst();
3788 }
3789 binx1 = fXaxis->FindFixBin(x1);
3790 // special case if more than 1 bin in x per pixel
3791 if (binx1-binx>1 && fH->GetDimension() == 1) {
3792 Double_t binval=fH->GetBinContent(binx);
3793 Int_t binnear=binx;
3794 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3795 Double_t binvaltmp = fH->GetBinContent(ibin);
3796 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3797 binval=binvaltmp;
3798 binnear=ibin;
3799 }
3800 }
3801 binx = binnear;
3802 }
3803 }
3804 if (fH->GetDimension() == 1) {
3806 TProfile *tp = (TProfile*)fH;
3807 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3808 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3809 (Int_t) tp->GetBinEntries(binx));
3810 }
3811 else {
3812 Double_t integ = 0;
3813 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3814 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3815 x,y,binx,fH->GetBinContent(binx),integ);
3816 }
3817 } else if (fH->GetDimension() == 2) {
3818 if (fH->InheritsFrom(TH2Poly::Class())) {
3819 TH2Poly *th2 = (TH2Poly*)fH;
3820 biny = th2->FindBin(x,y);
3821 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3822 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3823 }
3824 else if (fH->InheritsFrom(TProfile2D::Class())) {
3825 TProfile2D *tp = (TProfile2D*)fH;
3826 biny = fYaxis->FindFixBin(y);
3827 Int_t bin = fH->GetBin(binx,biny);
3828 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3829 x, y, binx, biny, fH->GetBinContent(bin),
3830 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3831 } else {
3832 biny = fYaxis->FindFixBin(y);
3833 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3834 x,y,binx,biny,fH->GetBinContent(binx,biny),
3835 fH->GetBinError(binx,biny));
3836 }
3837 } else {
3838 // 3d case: retrieving the x,y,z bin is not yet implemented
3839 // print just the x,y info
3840 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3841 }
3842
3843 return (char *)fObjectInfo.Data();
3844}
3845
3846////////////////////////////////////////////////////////////////////////////////
3847/// Set highlight (enable/disable) mode for fH
3848
3850{
3851 if (fH->IsHighlight()) return;
3852
3853 fXHighlightBin = -1;
3854 fYHighlightBin = -1;
3855 // delete previous highlight box
3856 if (gXHighlightBox) gXHighlightBox.reset();
3857 if (gYHighlightBox) gYHighlightBox.reset();
3858 // emit Highlighted() signal (user can check on disabled)
3859 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3860}
3861
3862////////////////////////////////////////////////////////////////////////////////
3863/// Check on highlight bin
3864
3866{
3867 // call from DistancetoPrimitive (only if highlight is enable)
3868
3869 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3870 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3871 Int_t binx = fXaxis->FindFixBin(x);
3872 Int_t biny = fYaxis->FindFixBin(y);
3873 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3874
3875 Bool_t changedBin = kFALSE;
3876 if (binx != fXHighlightBin) {
3877 fXHighlightBin = binx;
3878 changedBin = kTRUE;
3879 } else if (fH->GetDimension() == 1) return;
3880 if (biny != fYHighlightBin) {
3881 fYHighlightBin = biny;
3882 changedBin = kTRUE;
3883 }
3884 if (!changedBin) return;
3885
3886 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3887 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3888
3889 // paint highlight bin as box (recursive calls PaintHighlightBin)
3890 gPad->Modified(kTRUE);
3891 gPad->Update();
3892
3893 // emit Highlighted() signal
3894 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3895}
3896
3897////////////////////////////////////////////////////////////////////////////////
3898/// Paint highlight bin as TBox object
3899
3901{
3902 // call from PaintTitle
3903
3904 if (!fH->IsHighlight()) return;
3905
3906 Double_t uxmin = gPad->GetUxmin();
3907 Double_t uxmax = gPad->GetUxmax();
3908 Double_t uymin = gPad->GetUymin();
3909 Double_t uymax = gPad->GetUymax();
3910 if (gPad->GetLogx()) {
3911 uxmin = TMath::Power(10.0, uxmin);
3912 uxmax = TMath::Power(10.0, uxmax);
3913 }
3914 if (gPad->GetLogy()) {
3915 uymin = TMath::Power(10.0, uymin);
3916 uymax = TMath::Power(10.0, uymax);
3917 }
3918
3919 // testing specific possibility (after zoom, draw with "same", log, etc.)
3920 Double_t hcenter;
3921 if (gPad->IsVertical()) {
3923 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3924 } else {
3926 if ((hcenter < uymin) || (hcenter > uymax)) return;
3927 }
3928 if (fH->GetDimension() == 2) {
3930 if ((hcenter < uymin) || (hcenter > uymax)) return;
3931 }
3932
3933 // paint X highlight bin (for 1D or 2D)
3934 Double_t hbx1, hbx2, hby1, hby2;
3935 if (gPad->IsVertical()) {
3938 hby1 = uymin;
3939 hby2 = uymax;
3940 } else {
3941 hbx1 = uxmin;
3942 hbx2 = uxmax;
3945 }
3946
3947 if (!gXHighlightBox) {
3948 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3949 gXHighlightBox->SetBit(kCannotPick);
3950 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3951 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3952 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3953 }
3954 gXHighlightBox->SetX1(hbx1);
3955 gXHighlightBox->SetX2(hbx2);
3956 gXHighlightBox->SetY1(hby1);
3957 gXHighlightBox->SetY2(hby2);
3958 gXHighlightBox->Paint();
3959
3960 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3961 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3962
3963 // paint Y highlight bin (only for 2D)
3964 if (fH->GetDimension() != 2) return;
3965 hbx1 = uxmin;
3966 hbx2 = uxmax;
3969
3970 if (!gYHighlightBox) {
3971 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3972 gYHighlightBox->SetBit(kCannotPick);
3973 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3974 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3975 }
3976 gYHighlightBox->SetX1(hbx1);
3977 gYHighlightBox->SetX2(hbx2);
3978 gYHighlightBox->SetY1(hby1);
3979 gYHighlightBox->SetY2(hby2);
3980 gYHighlightBox->Paint();
3981}
3982
3983////////////////////////////////////////////////////////////////////////////////
3984/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3985
3987{
3988
3989 for (Int_t i=0;i<fNcuts;i++) {
3992 if (fCutsOpt[i] > 0) {
3993 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3994 } else {
3995 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3996 }
3997 }
3998 return kTRUE;
3999}
4000
4001////////////////////////////////////////////////////////////////////////////////
4002/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4003
4005{
4006
4007 for (Int_t i=0;i<fNcuts;i++) {
4008 if (fCutsOpt[i] > 0) {
4009 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4010 } else {
4011 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4012 }
4013 }
4014 return kTRUE;
4015}
4016
4017////////////////////////////////////////////////////////////////////////////////
4018/// Decode string `choptin` and fill Hoption structure.
4019
4021{
4022
4023 char *l;
4024 char chopt[128];
4025 Int_t nch = strlen(choptin);
4026 strlcpy(chopt,choptin,128);
4027 Int_t hdim = fH->GetDimension();
4028 Bool_t explicitColor = kFALSE;
4029
4037 Hoption.Candle = 0;
4038 Hoption.Polar = 0;
4039
4040 // special 2D options
4041 Hoption.List = 0;
4042 Hoption.Zscale = 0;
4043 Hoption.FrontBox = 1;
4044 Hoption.BackBox = 1;
4046
4047 Hoption.Zero = 0;
4048
4050
4051 //check for graphical cuts
4052 MakeCuts(chopt);
4053
4054 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4055 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4056 if (!nch) Hoption.Hist = 1;
4057 if (fFunctions->First()) Hoption.Func = 1;
4058 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4059
4060 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4061 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4062 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4063 if (l1 || l2 || l3) {
4064 Int_t i = gPad->NextPaletteColor();
4065 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4066 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4067 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4068 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4069 }
4070
4071 l = strstr(chopt,"MIN0");
4072 if (l) {
4073 Hoption.MinimumZero = 1;
4074 memcpy(l," ",4);
4075 }
4076
4077 l = strstr(chopt,"SPEC");
4078 if (l) {
4079 Hoption.Color = 0;
4080 memcpy(l," ",4);
4081 Int_t bs=0;
4082 l = strstr(chopt,"BF(");
4083 if (l) {
4084 if (sscanf(&l[3],"%d",&bs) > 0) {
4085 Int_t i=0;
4086 while (l[i]!=')') {
4087 l[i] = ' ';
4088 i++;
4089 }
4090 l[i] = ' ';
4091 }
4092 }
4093 Hoption.Spec = TMath::Max(1600,bs);
4094 return 1;
4095 }
4096
4097 l = strstr(chopt,"GL");
4098 if (l) {
4099 memcpy(l," ",2);
4100 }
4101 l = strstr(chopt,"X+");
4102 if (l) {
4103 Hoption.AxisPos = 10;
4104 memcpy(l," ",2);
4105 }
4106 l = strstr(chopt,"Y+");
4107 if (l) {
4108 Hoption.AxisPos += 1;
4109 memcpy(l," ",2);
4110 }
4111 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4112 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4113
4114 l = strstr(chopt,"SAMES");
4115 if (l) {
4116 if (nch == 5) Hoption.Hist = 1;
4117 Hoption.Same = 2;
4118 memcpy(l," ",5);
4119 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4120 }
4121 l = strstr(chopt,"SAME");
4122 if (l) {
4123 if (nch == 4) Hoption.Hist = 1;
4124 Hoption.Same = 1;
4125 memcpy(l," ",4);
4126 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4127 }
4128
4129 l = strstr(chopt,"SCAT");
4130 if (l) {
4131 Warning("MakeChopt","option SCAT is deprecated.");
4132 Hoption.Scat = 1;
4133 memcpy(l," ",4);
4134 Hoption.Color = 0;
4135 }
4136
4137 l = strstr(chopt,"PIE");
4138 if (l) {
4139 Hoption.Pie = 1;
4140 memcpy(l," ",3);
4141 }
4142
4143
4144 l = strstr(chopt,"CANDLE");
4145 if (l) {
4146 TCandle candle;
4147 Hoption.Candle = candle.ParseOption(l);
4148 Hoption.Color = 0;
4149 }
4150
4151 l = strstr(chopt,"VIOLIN");
4152 if (l) {
4153 TCandle candle;
4154 Hoption.Candle = candle.ParseOption(l);
4155 Hoption.Color = 0;
4156 }
4157
4158 l = strstr(chopt,"LEGO");
4159 if (l) {
4160 Hoption.Color = 0;
4161 Hoption.Lego = 1; memcpy(l," ",4);
4162 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4163 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4164 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4165 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4166 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4167 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4168 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4169 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4170 }
4171
4172 l = strstr(chopt,"SURF");
4173 if (l) {
4174 Hoption.Color = 0;
4175 Hoption.Surf = 1; memcpy(l," ",4);
4176 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4177 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4178 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4179 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4180 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4181 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4182 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4183 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4184 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4185 }
4186
4187 l = strstr(chopt,"TF3");
4188 if (l) {
4189 memcpy(l," ",3);
4190 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4191 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4192 }
4193
4194 l = strstr(chopt,"ISO");
4195 if (l) {
4196 memcpy(l," ",3);
4197 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4198 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4199 Hoption.Color = 0;
4200 }
4201
4202 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4203
4204 l = strstr(chopt,"CONT");
4205 if (l) {
4206 memcpy(l," ",4);
4207 if (hdim>1) {
4208 Hoption.Color = 0;
4209 Hoption.Contour = 1;
4210 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4211 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4212 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4213 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4214 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4215 } else {
4216 Hoption.Hist = 1;
4217 }
4218 }
4219 l = strstr(chopt,"HBAR");
4220 if (l) {
4221 Hoption.Hist = 0;
4222 Hoption.Bar = 20; memcpy(l," ",4);
4223 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4224 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4225 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4226 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4227 }
4228 l = strstr(chopt,"BAR");
4229 if (l) {
4230 Hoption.Hist = 0;
4231 Hoption.Bar = 10; memcpy(l," ",3);
4232 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4233 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4234 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4235 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4236 }
4237
4238 l = strstr(chopt,"ARR" );
4239 if (l) {
4240 memcpy(l," ", 3);
4241 if (hdim>1) {
4242 Hoption.Arrow = 1;
4243 Hoption.Color = 0;
4244 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4245 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4246 } else {
4247 Hoption.Hist = 1;
4248 }
4249 }
4250 l = strstr(chopt,"BOX" );
4251 if (l) {
4252 memcpy(l," ", 3);
4253 if (hdim>1) {
4254 Hoption.Color = 0;
4255 Hoption.Box = 1;
4256 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4257 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4258 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4259 } else {
4260 Hoption.Hist = 1;
4261 }
4262 }
4263 l = strstr(chopt,"TEXT");
4264 if (l) {
4265 Int_t angle;
4266 if (sscanf(&l[4],"%d",&angle) > 0) {
4267 if (angle < 0) angle=0;
4268 if (angle > 90) angle=90;
4269 Hoption.Text = 1000+angle;
4270 } else {
4271 Hoption.Text = 1;
4272 }
4273 memcpy(l," ", 4);
4274 l = strstr(chopt,"N");
4275 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4276 Hoption.Color = 0;
4277 }
4278 l = strstr(chopt,"COLZ");
4279 if (l) {
4280 memcpy(l," ",4);
4281 if (hdim > 1) {
4282 explicitColor = kTRUE;
4283 Hoption.Color = 1;
4284 Hoption.Zscale = 1;
4285 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4286 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4287 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4288 } else {
4289 Hoption.Hist = 1;
4290 }
4291 }
4292 l = strstr(chopt,"COL" );
4293 if (l) {
4294 memcpy(l," ", 3);
4295 if (hdim > 1) {
4296 explicitColor = kTRUE;
4297 Hoption.Color = 1;
4298 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4299 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4300 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4301 } else {
4302 Hoption.Hist = 1;
4303 }
4304 }
4305 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4306 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4307 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4308 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4309 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4310 l = strstr(chopt,"POLN"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 3; memcpy(l," ",4); }
4311 l = strstr(chopt,"POLF"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 2; memcpy(l," ",4); }
4312 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 1; memcpy(l," ",3); }
4313 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4314 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4315 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4316
4317 l = strstr(chopt,"TRI");
4318 if (l) {
4319 if (!explicitColor) Hoption.Color = 0;
4320 Hoption.Tri = 1; memcpy(l," ",3);
4321 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4322 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4323 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4324 }
4325
4326 l = strstr(chopt,"AITOFF");
4327 if (l) {
4328 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4329 }
4330 l = strstr(chopt,"MERCATOR");
4331 if (l) {
4332 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4333 }
4334 l = strstr(chopt,"SINUSOIDAL");
4335 if (l) {
4336 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4337 }
4338 l = strstr(chopt,"PARABOLIC");
4339 if (l) {
4340 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4341 }
4342 l = strstr(chopt,"MOLLWEIDE");
4343 if (l) {
4344 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4345 }
4346 if (Hoption.Proj > 0) {
4347 if (!explicitColor) Hoption.Color = 0;
4348 Hoption.Contour = 14;
4349 }
4350
4351 if (strstr(chopt,"A")) Hoption.Axis = -1;
4352 if (strstr(chopt,"B")) Hoption.Bar = 1;
4353 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4354 if (strstr(chopt,"F")) Hoption.Fill =1;
4355 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4356 if (strstr(chopt,"F2")) Hoption.Fill =2;
4357 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4358 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4359 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4360 if (strstr(chopt,"*")) Hoption.Star =1;
4361 if (strstr(chopt,"H")) Hoption.Hist =2;
4362 if (strstr(chopt,"P0")) Hoption.Mark =10;
4363
4364 if (fH->InheritsFrom(TH2Poly::Class())) {
4365 if ((Hoption.Fill+Hoption.Line+Hoption.Mark != 0) && !explicitColor) Hoption.Color = 0;
4366 }
4367
4368 if (strstr(chopt,"E")) {
4369 if (hdim == 1) {
4370 Hoption.Error = 1;
4371 if (strstr(chopt,"E1")) Hoption.Error = 11;
4372 if (strstr(chopt,"E2")) Hoption.Error = 12;
4373 if (strstr(chopt,"E3")) Hoption.Error = 13;
4374 if (strstr(chopt,"E4")) Hoption.Error = 14;
4375 if (strstr(chopt,"E5")) Hoption.Error = 15;
4376 if (strstr(chopt,"E6")) Hoption.Error = 16;
4377 if (strstr(chopt,"E0")) Hoption.Error += 40;
4378 if (strstr(chopt,"X0")) {
4379 if (Hoption.Error == 1) Hoption.Error += 20;
4380 Hoption.Error += 10;
4381 }
4383 Hoption.Text += 2000;
4384 Hoption.Error = 0;
4385 }
4386 } else {
4387 if (Hoption.Error == 0) {
4388 Hoption.Error = 100;
4389 if (!explicitColor) Hoption.Color = 0;
4390 }
4391 if (Hoption.Text) {
4392 Hoption.Text += 2000;
4393 Hoption.Error = 0;
4394 }
4395 }
4396 }
4397
4398 if (Hoption.Surf == 15) {
4400 Hoption.Surf = 13;
4401 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4402 }
4403 }
4404
4405 // Copy options from current style
4406 Hoption.Logx = gPad->GetLogx();
4407 Hoption.Logy = gPad->GetLogy();
4408 Hoption.Logz = gPad->GetLogz();
4409
4410 // Check options incompatibilities
4411 if (Hoption.Bar == 1) Hoption.Hist = -1;
4412 return 1;
4413}
4414
4415////////////////////////////////////////////////////////////////////////////////
4416/// Decode string `choptin` and fill Graphical cuts structure.
4417
4419{
4420
4421 fNcuts = 0;
4422 char *left = (char*)strchr(choptin,'[');
4423 if (!left) return 0;
4424 char *right = (char*)strchr(choptin,']');
4425 if (!right) return 0;
4426 Int_t nch = right-left;
4427 if (nch < 2) return 0;
4428 char *cuts = left+1;
4429 *right = 0;
4430 char *comma, *minus;
4431 Int_t i;
4432 while (true) {
4433 comma = strchr(cuts,',');
4434 if (comma) *comma = 0;
4435 minus = strchr(cuts,'-');
4436 if (minus) cuts = minus+1;
4437 while (*cuts == ' ') cuts++;
4438 Int_t nc = strlen(cuts);
4439 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4440 TIter next(gROOT->GetListOfSpecials());
4441 TCutG *cut=nullptr;
4442 TObject *obj;
4443 while ((obj = next())) {
4444 if (!obj->InheritsFrom(TCutG::Class())) continue;
4445 if (strcmp(obj->GetName(),cuts)) continue;
4446 cut = (TCutG*)obj;
4447 break;
4448 }
4449 if (cut) {
4450 fCuts[fNcuts] = cut;
4451 fCutsOpt[fNcuts] = 1;
4452 if (minus) fCutsOpt[fNcuts] = -1;
4453 fNcuts++;
4454 }
4455 if (!comma) break;
4456 cuts = comma+1;
4457 }
4458 for (i=0;i<=nch;i++) left[i] = ' ';
4459 return fNcuts;
4460}
4461
4462////////////////////////////////////////////////////////////////////////////////
4463/// [Control routine to paint any kind of histograms](\ref HP00)
4464
4466{
4467
4468 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4469
4470 //For iOS: put the histogram on the top of stack of pickable objects.
4471 const TPickerStackGuard topPush(fH);
4472
4473 gPad->SetVertical(kTRUE);
4474
4475 TH1 *oldhist = gCurrentHist;
4476 gCurrentHist = fH;
4477 TH1 *hsave = fH;
4478 Double_t minsav = fH->GetMinimumStored();
4479
4480 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4481
4482 // Paint using TSpectrum2Painter
4483 if (Hoption.Spec) {
4484 if (!TableInit()) return;
4485 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4486 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4487 (size_t)fH, option, Hoption.Spec).Data());
4488 return;
4489 }
4490
4491 // Deflate the labels in case of alphanumeric labels
4495
4496 if (Hoption.Pie) {
4497 if (fH->GetDimension() == 1) {
4498 if (!fPie)
4499 fPie = std::make_unique<TPie>(fH);
4500 fPie->Paint(option);
4501 } else {
4502 Error("Paint", "Option PIE is for 1D histograms only");
4503 }
4504 return;
4505 } else {
4506 fPie.reset();
4507 }
4508
4509 fXbuf.resize(kNMAX);
4510 fYbuf.resize(kNMAX);
4511 if (fH->GetDimension() > 2) {
4512 PaintH3(option);
4513 fH->SetMinimum(minsav);
4514 if (Hoption.Func) {
4515 Hoption_t hoptsave = Hoption;
4516 Hparam_t hparsave = Hparam;
4518 SetHistogram(hsave);
4519 Hoption = hoptsave;
4520 Hparam = hparsave;
4521 }
4522 gCurrentHist = oldhist;
4523 fXbuf.clear();
4524 fYbuf.clear();
4525 return;
4526 }
4527 TView *view = gPad->GetView();
4528 if (view) {
4529 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4530 delete view;
4531 gPad->SetView(nullptr);
4532 }
4533 }
4534 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4535 // In case of 1D histogram, Z axis becomes Y axis.
4536 Int_t logysav=0, logzsav=0;
4537 if (fH->GetDimension() == 1) {
4538 logysav = Hoption.Logy;
4539 logzsav = Hoption.Logz;
4540 Hoption.Logz = 0;
4541 if (Hoption.Logy) {
4542 Hoption.Logz = 1;
4543 Hoption.Logy = 0;
4544 }
4545 }
4547 if (Hoption.Func) {
4548 Hoption_t hoptsave = Hoption;
4549 Hparam_t hparsave = Hparam;
4551 SetHistogram(hsave);
4552 Hoption = hoptsave;
4553 Hparam = hparsave;
4554 }
4555 fH->SetMinimum(minsav);
4556 gCurrentHist = oldhist;
4557 fXbuf.clear();
4558 fYbuf.clear();
4559 if (fH->GetDimension() == 1) {
4560 Hoption.Logy = logysav;
4561 Hoption.Logz = logzsav;
4562 }
4563 return;
4564 }
4565
4566 if (Hoption.Bar >= 20) {
4568 fXbuf.clear();
4569 fYbuf.clear();
4570 return;
4571 }
4572
4573 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4574 // fill Hparam structure with histo parameters
4575 if (!PaintInit()) {
4576 fXbuf.clear();
4577 fYbuf.clear();
4578 return;
4579 }
4580
4581 // Picture surround (if new page) and page number (if requested).
4582 // Histogram surround (if not option "Same").
4583 PaintFrame();
4584
4585 // Paint histogram axis only
4586 Bool_t gridx = gPad->GetGridx();
4587 Bool_t gridy = gPad->GetGridy();
4588 if (Hoption.Axis > 0) {
4589 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4590 else {
4591 if (gridx) gPad->SetGridx(0);
4592 if (gridy) gPad->SetGridy(0);
4594 if (gridx) gPad->SetGridx(1);
4595 if (gridy) gPad->SetGridy(1);
4596 }
4597 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4598 goto paintstat;
4599 }
4600 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4601
4602 // test for options BAR or HBAR
4603 if (Hoption.Bar >= 10) {
4605 }
4606
4607 // do not draw histogram if error bars required
4608 if (!Hoption.Error) {
4609 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4610 }
4611
4612 // test for error bars or option E
4613 if (Hoption.Error) {
4615 if (Hoption.Hist == 2) PaintHist(option);
4616 }
4617
4619
4620 // test for associated function
4621 if (Hoption.Func) {
4622 Hoption_t hoptsave = Hoption;
4623 Hparam_t hparsave = Hparam;
4625 SetHistogram(hsave);
4626 Hoption = hoptsave;
4627 Hparam = hparsave;
4628 }
4629
4630 if (gridx) gPad->SetGridx(0);
4631 if (gridy) gPad->SetGridy(0);
4633 if (gridx) gPad->SetGridx(1);
4634 if (gridy) gPad->SetGridy(1);
4635
4636 PaintTitle(); // Draw histogram title
4637
4638 // Draw box with histogram statistics and/or fit parameters
4639paintstat:
4640 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4641 TIter next(fFunctions);
4642 TObject *obj = nullptr;
4643 while ((obj = next())) {
4644 if (obj->InheritsFrom(TF1::Class())) break;
4645 obj = nullptr;
4646 }
4647
4648 //Stat is painted twice (first, it will be in canvas' list of primitives),
4649 //second, it will be here, this is not required on iOS.
4650 //Condition is ALWAYS true on a platform different from iOS.
4651 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4652 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4653 }
4654 fH->SetMinimum(minsav);
4655 gCurrentHist = oldhist;
4656 fXbuf.clear();
4657 fYbuf.clear();
4658}
4659
4660////////////////////////////////////////////////////////////////////////////////
4661/// [Control function to draw a table as an arrow plot](\ref HP12)
4662
4664{
4665 Double_t xk, xstep, yk, ystep;
4666 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4669 Double_t xrg = gPad->GetUxmin();
4670 Double_t yrg = gPad->GetUymin();
4671 Double_t xln = gPad->GetUxmax() - xrg;
4672 Double_t yln = gPad->GetUymax() - yrg;
4673 Double_t cx = (xln/Double_t(ncx))/2.;
4674 Double_t cy = (yln/Double_t(ncy))/2.;
4675 Double_t dn = 1.E-30;
4676
4677 auto arrow = new TArrow();
4678 arrow->SetAngle(30);
4679 arrow->SetFillStyle(1001);
4680 arrow->SetFillColor(fH->GetLineColor());
4681 arrow->SetLineColor(fH->GetLineColor());
4682 arrow->SetLineWidth(fH->GetLineWidth());
4683
4684 // Initialize the levels on the Z axis
4685 Int_t ncolors=0, ndivz=0;
4686 Double_t scale=0.;
4687 if (Hoption.Arrow>1) {
4688 ncolors = gStyle->GetNumberOfColors();
4689 Int_t ndiv = fH->GetContour();
4690 if (ndiv == 0 ) {
4691 ndiv = gStyle->GetNumberContours();
4692 fH->SetContour(ndiv);
4693 }
4694 ndivz = TMath::Abs(ndiv);
4695 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4696 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4697 }
4698
4699 for (Int_t id=1;id<=2;id++) {
4700 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4701 yk = fYaxis->GetBinLowEdge(j);
4702 ystep = fYaxis->GetBinWidth(j);
4703 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4704 xk = fXaxis->GetBinLowEdge(i);
4705 xstep = fXaxis->GetBinWidth(i);
4706 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4707 if (i == Hparam.xfirst) {
4708 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4709 } else if (i == Hparam.xlast) {
4710 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4711 } else {
4712 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4713 }
4714 if (j == Hparam.yfirst) {
4715 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4716 } else if (j == Hparam.ylast) {
4717 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4718 } else {
4719 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4720 }
4721 if (id == 1) {
4722 dn = TMath::Max(dn, TMath::Abs(dx));
4723 dn = TMath::Max(dn, TMath::Abs(dy));
4724 } else if (id == 2) {
4725 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4726 dxn = cx*dx/dn;
4727 x1 = xc - dxn;
4728 x2 = xc + dxn;
4729 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4730 dyn = cy*dy/dn;
4731 y1 = yc - dyn;
4732 y2 = yc + dyn;
4733 if (Hoption.Arrow>1) {
4734 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4735 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4736 if (theColor > ncolors-1) theColor = ncolors-1;
4737 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4738 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4739 }
4740 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4741 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4742 } else {
4743 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4744 }
4745 }
4746 }
4747 }
4748 }
4749
4751}
4752
4753////////////////////////////////////////////////////////////////////////////////
4754/// Draw axis (2D case) of an histogram.
4755///
4756/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4757/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4758/// feature is used to make sure that the grid is drawn in the background and
4759/// the axis tick marks in the foreground of the pad.
4760
4762{
4763
4764 //On iOS, grid should not be pickable and can not be highlighted.
4765 //Condition is never true on a platform different from iOS.
4766 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4767 return;
4768
4769 if (Hoption.Axis == -1) return;
4770 if (Hoption.Same && Hoption.Axis <= 0) return;
4771
4772 // Repainting alphanumeric labels axis on a plot done with
4773 // the option HBAR (horizontal) needs some adjustments.
4774 TAxis *xaxis = nullptr;
4775 TAxis *yaxis = nullptr;
4776 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4777 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4778 TIter next(gPad->GetListOfPrimitives());
4779 TObject *obj;
4780 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4781 while ((obj = next())) {
4782 if (!obj->InheritsFrom(TH1::Class()) &&
4783 !obj->InheritsFrom(THStack::Class())) continue;
4784 TString opt = obj->GetDrawOption();
4785 opt.ToLower();
4786 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4787 if (strstr(opt,"hbar")) {
4788 gPad->SetVertical(kFALSE);
4789 xaxis = fXaxis;
4790 yaxis = fYaxis;
4791 if (!strcmp(xaxis->GetName(),"xaxis")) {
4792 fXaxis = yaxis;
4793 fYaxis = xaxis;
4794 }
4795 }
4796 break;
4797 }
4798 }
4799 }
4800
4801 static char chopt[10] = "";
4802 Double_t gridl = 0;
4803 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4804 Int_t useHparam = 0;
4805 Double_t umin, umax, uminsave, umaxsave;
4806 Short_t xAxisPos = Hoption.AxisPos/10;
4807 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4808
4809 Double_t axmin = gPad->GetUxmin();
4810 Double_t axmax = gPad->GetUxmax();
4811 Double_t aymin = gPad->GetUymin();
4812 Double_t aymax = gPad->GetUymax();
4813 char *cw = nullptr;
4814 TGaxis axis;
4815
4816 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4817 // Hparam must be use for the axis limits.
4818 if (Hoption.Contour == 14) useHparam = 1;
4819 if (Hoption.Same) {
4820 TObject *obj;
4821 TIter next(gPad->GetListOfPrimitives());
4822 while ((obj=next())) {
4823 if (strstr(obj->GetDrawOption(),"cont4")) {
4824 useHparam = 1;
4825 break;
4826 }
4827 }
4828 }
4829
4830 // Paint X axis
4831
4832 //To make X-axis selectable on iOS device.
4833 if (gPad->PadInSelectionMode())
4834 gPad->PushSelectableObject(fXaxis);
4835
4836 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4837 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4838 ndivx = fXaxis->GetNdivisions();
4839 if (ndivx > 1000) {
4840 nx2 = ndivx/100;
4841 nx1 = TMath::Max(1, ndivx%100);
4842 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4843 }
4844 axis.SetTextAngle(0);
4846
4847 chopt[0] = 0;
4848 strlcat(chopt, "SDH",10);
4849 if (ndivx < 0) strlcat(chopt, "N",10);
4850 if (gPad->GetGridx()) {
4851 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4852 strlcat(chopt, "W",10);
4853 }
4854
4855 // Define X-Axis limits
4856 if (Hoption.Logx) {
4857 strlcat(chopt, "G",10);
4858 ndiv = TMath::Abs(ndivx);
4859 if (useHparam) {
4860 umin = TMath::Power(10,Hparam.xmin);
4861 umax = TMath::Power(10,Hparam.xmax);
4862 } else {
4863 umin = TMath::Power(10,axmin);
4864 umax = TMath::Power(10,axmax);
4865 }
4866 } else {
4867 ndiv = TMath::Abs(ndivx);
4868 if (useHparam) {
4869 umin = Hparam.xmin;
4870 umax = Hparam.xmax;
4871 } else {
4872 umin = axmin;
4873 umax = axmax;
4874 }
4875 }
4876
4877 // Display axis as time
4878 if (fXaxis->GetTimeDisplay()) {
4879 strlcat(chopt,"t",10);
4880 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4882 }
4883 }
4884
4885 // The main X axis can be on the bottom or on the top of the pad
4886 Double_t xAxisYPos1, xAxisYPos2;
4887 if (xAxisPos == 1) {
4888 // Main X axis top
4889 xAxisYPos1 = aymax;
4890 xAxisYPos2 = aymin;
4891 } else {
4892 // Main X axis bottom
4893 xAxisYPos1 = aymin;
4894 xAxisYPos2 = aymax;
4895 }
4896
4897 // Paint the main X axis (always)
4898 uminsave = umin;
4899 umaxsave = umax;
4900 ndivsave = ndiv;
4901 axis.SetOption(chopt);
4902 if (xAxisPos) {
4903 strlcat(chopt, "-",10);
4904 gridl = -gridl;
4905 }
4906 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4907 axis.SetLabelSize(0.);
4908 axis.SetTitle("");
4909 }
4910 axis.PaintAxis(axmin, xAxisYPos1,
4911 axmax, xAxisYPos1,
4912 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4913
4914 // Paint additional X axis (if needed)
4915 // On iOS, this additional X axis is neither pickable, nor highlighted.
4916 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4917 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4918 if (xAxisPos) {
4919 cw=strstr(chopt,"-");
4920 *cw='z';
4921 } else {
4922 strlcat(chopt, "-",10);
4923 }
4924 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4925 if ((cw=strstr(chopt,"W"))) *cw='z';
4926 axis.SetTitle("");
4927 axis.PaintAxis(axmin, xAxisYPos2,
4928 axmax, xAxisYPos2,
4929 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4930 }
4931 }//End of "if pad in selection mode etc".
4932
4933 // Paint Y axis
4934 //On iOS, Y axis must pushed into the stack of selectable objects.
4935 if (gPad->PadInSelectionMode())
4936 gPad->PushSelectableObject(fYaxis);
4937
4938 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4939 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4940 ndivy = fYaxis->GetNdivisions();
4942
4943 chopt[0] = 0;
4944 strlcat(chopt, "SDH",10);
4945 if (ndivy < 0) strlcat(chopt, "N",10);
4946 if (gPad->GetGridy()) {
4947 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4948 strlcat(chopt, "W",10);
4949 }
4950
4951 // Define Y-Axis limits
4952 if (Hoption.Logy) {
4953 strlcat(chopt, "G",10);
4954 ndiv = TMath::Abs(ndivy);
4955 if (useHparam) {
4956 umin = TMath::Power(10,Hparam.ymin);
4957 umax = TMath::Power(10,Hparam.ymax);
4958 } else {
4959 umin = TMath::Power(10,aymin);
4960 umax = TMath::Power(10,aymax);
4961 }
4962 } else {
4963 ndiv = TMath::Abs(ndivy);
4964 if (useHparam) {
4965 umin = Hparam.ymin;
4966 umax = Hparam.ymax;
4967 } else {
4968 umin = aymin;
4969 umax = aymax;
4970 }
4971 }
4972
4973 // Display axis as time
4974 if (fYaxis->GetTimeDisplay()) {
4975 strlcat(chopt,"t",10);
4976 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4978 }
4979 }
4980
4981 // The main Y axis can be on the left or on the right of the pad
4982 Double_t yAxisXPos1, yAxisXPos2;
4983 if (yAxisPos == 1) {
4984 // Main Y axis left
4985 yAxisXPos1 = axmax;
4986 yAxisXPos2 = axmin;
4987 } else {
4988 // Main Y axis right
4989 yAxisXPos1 = axmin;
4990 yAxisXPos2 = axmax;
4991 }
4992
4993 // Paint the main Y axis (always)
4994 uminsave = umin;
4995 umaxsave = umax;
4996 ndivsave = ndiv;
4997 axis.SetOption(chopt);
4998 if (yAxisPos) {
4999 strlcat(chopt, "+L",10);
5000 gridl = -gridl;
5001 }
5002 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5003 axis.SetLabelSize(0.);
5004 axis.SetTitle("");
5005 }
5006 axis.PaintAxis(yAxisXPos1, aymin,
5007 yAxisXPos1, aymax,
5008 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5009
5010 // Paint the additional Y axis (if needed)
5011 // Additional checks for pad mode are required on iOS: this "second" axis is
5012 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5013 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5014 if (gPad->GetTicky() < 2) {
5015 strlcat(chopt, "U",10);
5017 } else {
5018 strlcat(chopt, "+L",10);
5019 }
5020 if ((cw=strstr(chopt,"W"))) *cw='z';
5021 axis.SetTitle("");
5022 axis.PaintAxis(yAxisXPos2, aymin,
5023 yAxisXPos2, aymax,
5024 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
5025 }
5026 }//End of "if pad is in selection mode etc."
5027
5028 // Reset the axis if they have been inverted in case of option HBAR
5029 if (xaxis) {
5030 fXaxis = xaxis;
5031 fYaxis = yaxis;
5032 }
5033}
5034
5035////////////////////////////////////////////////////////////////////////////////
5036/// [Draw a bar-chart in a normal pad.](\ref HP10)
5037
5039{
5040
5041 Int_t bar = Hoption.Bar - 10;
5042 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
5045 TBox box;
5046 Int_t hcolor = fH->GetFillColor();
5047 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5048 Int_t hstyle = fH->GetFillStyle();
5049 box.SetFillColor(hcolor);
5050 box.SetFillStyle(hstyle);
5051 box.SetLineStyle(fH->GetLineStyle());
5052 box.SetLineColor(fH->GetLineColor());
5053 box.SetLineWidth(fH->GetLineWidth());
5054 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5055 y = fH->GetBinContent(bin);
5056 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5057 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5058 ymin = gPad->GetUymin();
5059 ymax = gPad->YtoPad(y);
5060 if (ymax < gPad->GetUymin()) continue;
5061 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5062 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5063 if (Hoption.MinimumZero && ymin < 0)
5064 ymin=TMath::Min(0.,gPad->GetUymax());
5065 w = (xmax-xmin)*width;
5066 xmin += offset*(xmax-xmin);
5067 xmax = xmin + w;
5068 if (bar < 1) {
5069 box.PaintBox(xmin,ymin,xmax,ymax);
5070 } else {
5071 umin = xmin + bar*(xmax-xmin)/10.;
5072 umax = xmax - bar*(xmax-xmin)/10.;
5073 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5074 box.PaintBox(xmin,ymin,umin,ymax);
5075 box.SetFillColor(hcolor);
5076 box.PaintBox(umin,ymin,umax,ymax);
5077 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5078 box.PaintBox(umax,ymin,xmax,ymax);
5079 }
5080 }
5081}
5082
5083////////////////////////////////////////////////////////////////////////////////
5084/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5085
5087{
5088
5089 gPad->SetVertical(kFALSE);
5090
5091 PaintInitH();
5092
5093 TAxis *xaxis = fXaxis;
5094 TAxis *yaxis = fYaxis;
5095 if (!strcmp(xaxis->GetName(),"xaxis")) {
5096 fXaxis = yaxis;
5097 fYaxis = xaxis;
5098 }
5099
5100 PaintFrame();
5102
5103 Int_t bar = Hoption.Bar - 20;
5104 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5107 TBox box;
5108 Int_t hcolor = fH->GetFillColor();
5109 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5110 Int_t hstyle = fH->GetFillStyle();
5111 box.SetFillColor(hcolor);
5112 box.SetFillStyle(hstyle);
5113 box.SetLineStyle(fH->GetLineStyle());
5114 box.SetLineColor(fH->GetLineColor());
5115 box.SetLineWidth(fH->GetLineWidth());
5116 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5117 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5118 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5119 xmin = gPad->GetUxmin();
5120 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5121 if (xmax < gPad->GetUxmin()) continue;
5122 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5123 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5124 if (Hoption.MinimumZero && xmin < 0)
5125 xmin=TMath::Min(0.,gPad->GetUxmax());
5126 w = (ymax-ymin)*width;
5127 ymin += offset*(ymax-ymin);
5128 ymax = ymin + w;
5129 if (bar < 1) {
5130 box.PaintBox(xmin,ymin,xmax,ymax);
5131 } else {
5132 umin = ymin + bar*(ymax-ymin)/10.;
5133 umax = ymax - bar*(ymax-ymin)/10.;
5134 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5135 box.PaintBox(xmin,ymin,xmax,umin);
5136 box.SetFillColor(hcolor);
5137 box.PaintBox(xmin,umin,xmax,umax);
5138 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5139 box.PaintBox(xmin,umax,xmax,ymax);
5140 }
5141 }
5142
5143 PaintTitle();
5144
5145 // Draw box with histogram statistics and/or fit parameters
5146 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5147 TIter next(fFunctions);
5148 TObject *obj = nullptr;
5149 while ((obj = next())) {
5150 if (obj->InheritsFrom(TF1::Class())) break;
5151 obj = nullptr;
5152 }
5153 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5154 }
5155
5156 fXaxis = xaxis;
5157 fYaxis = yaxis;
5158}
5159
5160////////////////////////////////////////////////////////////////////////////////
5161/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5162
5164{
5165
5166 Style_t fillsav = fH->GetFillStyle();
5167 Style_t colsav = fH->GetFillColor();
5168 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5169 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5170 fH->TAttLine::Modify();
5171 fH->TAttFill::Modify();
5172
5173 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5174 Double_t ux1 = gPad->PixeltoX(1);
5175 Double_t ux0 = gPad->PixeltoX(0);
5176 Double_t uy1 = gPad->PixeltoY(1);
5177 Double_t uy0 = gPad->PixeltoY(0);
5178 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5179 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5180
5181 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5184 Double_t zminlin = zmin, zmaxlin = zmax;
5185
5186 // In case of option SAME, zmin and zmax values are taken from the
5187 // first plotted 2D histogram.
5188 if (Hoption.Same > 0 && Hoption.Same < 10) {
5189 TH2 *h2;
5190 TIter next(gPad->GetListOfPrimitives());
5191 while ((h2 = (TH2 *)next())) {
5192 if (!h2->InheritsFrom(TH2::Class())) continue;
5193 zmin = TMath::Max(h2->GetMinimum(), 0.);
5194 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5195 TMath::Abs(h2->GetMinimum()));
5196 zminlin = zmin;
5197 zmaxlin = zmax;
5198 if (Hoption.Logz) {
5199 if (zmin <= 0) {
5200 zmin = TMath::Log10(zmax*0.001);
5201 } else {
5202 zmin = TMath::Log10(zmin);
5203 }
5204 zmax = TMath::Log10(zmax);
5205 }
5206 break;
5207 }
5208 } else {
5209 if (Hoption.Logz) {
5210 if (zmin > 0) {
5211 zmin = TMath::Log10(zmin);
5212 zmax = TMath::Log10(zmax);
5213 } else {
5214 return;
5215 }
5216 }
5217 }
5218
5219 Double_t zratio, dz = zmax - zmin;
5220 Bool_t kZminNeg = kFALSE;
5221 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5222 Bool_t kZNeg = kFALSE;
5223
5224 // Define the dark and light colors the "button style" boxes.
5225 Color_t color = fH->GetFillColor();
5226 Color_t light=0, dark=0;
5227 if (Hoption.Box == 11) {
5228 light = TColor::GetColorBright(color);
5229 dark = TColor::GetColorDark(color);
5230 }
5231
5232 // Loop over all the bins and draw the boxes
5233 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5234 yk = fYaxis->GetBinLowEdge(j);
5235 ystep = fYaxis->GetBinWidth(j);
5236 ycent = 0.5*ystep;
5237 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5238 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5239 xk = fXaxis->GetBinLowEdge(i);
5240 xstep = fXaxis->GetBinWidth(i);
5241 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5242 xcent = 0.5*xstep;
5243 z = Hparam.factor*fH->GetBinContent(bin);
5244 kZNeg = kFALSE;
5245
5246 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5247 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5248 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5249
5250 if (z < 0) {
5251 if (Hoption.Logz) continue;
5252 z = -z;
5253 kZNeg = kTRUE;
5254 }
5255 if (Hoption.Logz) {
5256 if (z != 0) z = TMath::Log10(z);
5257 else z = zmin;
5258 }
5259
5260 if (dz == 0) continue;
5261 zratio = TMath::Sqrt((z-zmin)/dz);
5262 if (zratio == 0) continue;
5263
5264 xup = xcent*zratio + xk + xcent;
5265 xlow = 2*(xk + xcent) - xup;
5266 if (xup-xlow < dxmin) xup = xlow+dxmin;
5267 if (Hoption.Logx) {
5268 if (xup > 0) xup = TMath::Log10(xup);
5269 else continue;
5270 if (xlow > 0) xlow = TMath::Log10(xlow);
5271 else continue;
5272 }
5273
5274 yup = ycent*zratio + yk + ycent;
5275 ylow = 2*(yk + ycent) - yup;
5276 if (yup-ylow < dymin) yup = ylow+dymin;
5277 if (Hoption.Logy) {
5278 if (yup > 0) yup = TMath::Log10(yup);
5279 else continue;
5280 if (ylow > 0) ylow = TMath::Log10(ylow);
5281 else continue;
5282 }
5283
5284 xlow = TMath::Max(xlow, gPad->GetUxmin());
5285 ylow = TMath::Max(ylow, gPad->GetUymin());
5286 xup = TMath::Min(xup , gPad->GetUxmax());
5287 yup = TMath::Min(yup , gPad->GetUymax());
5288
5289 if (xlow >= xup) continue;
5290 if (ylow >= yup) continue;
5291
5292 if (Hoption.Box == 1) {
5293 fH->SetFillColor(color);
5294 fH->TAttFill::Modify();
5295 gPad->PaintBox(xlow, ylow, xup, yup);
5296 if (kZNeg) {
5297 gPad->PaintLine(xlow, ylow, xup, yup);
5298 gPad->PaintLine(xlow, yup, xup, ylow);
5299 }
5300 } else if (Hoption.Box == 11) {
5301 // Draw the center of the box
5302 fH->SetFillColor(color);
5303 fH->TAttFill::Modify();
5304 gPad->PaintBox(xlow, ylow, xup, yup);
5305
5306 // Draw top&left part of the box
5307 Double_t x[7], y[7];
5308 Double_t bwidth = 0.1;
5309 x[0] = xlow; y[0] = ylow;
5310 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5311 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5312 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5313 x[4] = xup; y[4] = yup;
5314 x[5] = xlow; y[5] = yup;
5315 x[6] = xlow; y[6] = ylow;
5316 if (kZNeg) fH->SetFillColor(dark);
5317 else fH->SetFillColor(light);
5318 fH->TAttFill::Modify();
5319 gPad->PaintFillArea(7, x, y);
5320
5321 // Draw bottom&right part of the box
5322 x[0] = xlow; y[0] = ylow;
5323 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5324 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5325 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5326 x[4] = xup; y[4] = yup;
5327 x[5] = xup; y[5] = ylow;
5328 x[6] = xlow; y[6] = ylow;
5329 if (kZNeg) fH->SetFillColor(light);
5330 else fH->SetFillColor(dark);
5331 fH->TAttFill::Modify();
5332 gPad->PaintFillArea(7, x, y);
5333 }
5334 }
5335 }
5336
5338 fH->SetFillStyle(fillsav);
5339 fH->SetFillColor(colsav);
5340 fH->TAttFill::Modify();
5341}
5342
5343
5344
5345////////////////////////////////////////////////////////////////////////////////
5346/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5347
5349{
5350 TH1D *hproj = nullptr;
5351 TH2D *h2 = (TH2D*)fH;
5352
5353 TCandle myCandle;
5355 myCandle.SetMarkerColor(fH->GetLineColor());
5356 myCandle.SetLineColor(fH->GetLineColor());
5357 myCandle.SetLineWidth(fH->GetLineWidth());
5358 myCandle.SetFillColor(fH->GetFillColor());
5359 myCandle.SetFillStyle(fH->GetFillStyle());
5360 myCandle.SetMarkerSize(fH->GetMarkerSize());
5361 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5363
5364 Bool_t swapXY = myCandle.IsHorizontal();
5365 const Double_t standardCandleWidth = 0.66;
5366 const Double_t standardHistoWidth = 0.8;
5367
5368 double allMaxContent = 0, allMaxIntegral = 0;
5369 if (myCandle.IsViolinScaled())
5370 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5371
5372 if (!swapXY) { // Vertical candle
5373 //Determining the slice with the maximum integral - if necessary
5374 if (myCandle.IsCandleScaled())
5375 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5376 hproj = h2->ProjectionY("_px", i, i);
5377 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5378 }
5379 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5380 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5381 Double_t binWidth = fXaxis->GetBinWidth(i);
5382 hproj = h2->ProjectionY("_px", i, i);
5383 if (hproj->GetEntries() != 0) {
5384 Double_t candleWidth = fH->GetBarWidth();
5385 Double_t offset = fH->GetBarOffset()*binWidth;
5386 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5387 double myIntegral = hproj->Integral();
5388 Double_t histoWidth = candleWidth;
5389 if (candleWidth > 0.999 && candleWidth < 1.001) {
5390 candleWidth = standardCandleWidth;
5391 histoWidth = standardHistoWidth;
5392 }
5393 if (Hoption.Logz && myMaxContent > 0) {
5394 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5395 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5396 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5397 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5398 histoWidth *= myMaxContent/allMaxContent;
5399 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5400 candleWidth *= myIntegral/allMaxIntegral;
5401
5402 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5403 myCandle.SetCandleWidth(candleWidth*binWidth);
5404 myCandle.SetHistoWidth(histoWidth*binWidth);
5405 myCandle.SetHistogram(hproj);
5406 myCandle.Paint();
5407 }
5408 }
5409 } else { // Horizontal candle
5410 //Determining the slice with the maximum integral - if necessary
5411 if (myCandle.IsCandleScaled())
5412 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5413 hproj = h2->ProjectionX("_py", i, i);
5414 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5415 }
5416 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5417 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5418 Double_t binWidth = fYaxis->GetBinWidth(i);
5419 hproj = h2->ProjectionX("_py", i, i);
5420 if (hproj->GetEntries() != 0) {
5421 Double_t candleWidth = fH->GetBarWidth();
5422 Double_t offset = fH->GetBarOffset()*binWidth;
5423 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5424 double myIntegral = hproj->Integral();
5425 Double_t histoWidth = candleWidth;
5426 if (candleWidth > 0.999 && candleWidth < 1.001) {
5427 candleWidth = standardCandleWidth;
5428 histoWidth = standardHistoWidth;
5429 }
5430 if (Hoption.Logz && myMaxContent > 0) {
5431 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5432 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5433 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5434 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5435 histoWidth *= myMaxContent/allMaxContent;
5436 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5437 candleWidth *= myIntegral/allMaxIntegral;
5438
5439 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5440 myCandle.SetCandleWidth(candleWidth*binWidth);
5441 myCandle.SetHistoWidth(histoWidth*binWidth);
5442 myCandle.SetHistogram(hproj);
5443 myCandle.Paint();
5444 }
5445 }
5446 }
5447 delete hproj;
5448}
5449
5450
5451
5452////////////////////////////////////////////////////////////////////////////////
5453/// Returns the rendering regions for an axis to use in the COL2 option
5454///
5455/// The algorithm analyses the size of the axis compared to the size of
5456/// the rendering region. It figures out the boundaries to use for each color
5457/// of the rendering region. Only one axis is computed here.
5458///
5459/// This allows for a single computation of the boundaries before iterating
5460/// through all of the bins.
5461///
5462/// \param pAxis the axis to consider
5463/// \param nPixels the number of pixels to render axis into
5464/// \param isLog whether the axis is log scale
5465
5466std::vector<THistRenderingRegion>
5468{
5469 std::vector<THistRenderingRegion> regions;
5470
5471 enum STRATEGY { Bins, Pixels } strategy;
5472
5473 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5474
5475 if (nBins >= nPixels) {
5476 // more bins than pixels... we should loop over pixels and sample
5477 strategy = Pixels;
5478 } else {
5479 // fewer bins than pixels... we should loop over bins
5480 strategy = Bins;
5481 }
5482
5483 if (isLog) {
5484
5485 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5486 Int_t binOffset=0;
5487 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5488 binOffset++;
5489 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5490 }
5491 if (xMin <= 0) {
5492 // this should cause an error if we have
5493 return regions;
5494 }
5495 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5496
5497 if (strategy == Bins) {
5498 // logarithmic plot. we find the pixel for the bin
5499 // pixel = eta * log10(V) - alpha
5500 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5501 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5502 // and V is axis value
5503 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5504 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5505
5506 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5507
5508 // linear plot. we simply need to find the appropriate bin
5509 // for the
5510 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5511 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5512 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5513 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5514 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5515 std::make_pair(bin, bin+1)};
5516 regions.push_back(region);
5517 }
5518
5519 } else {
5520
5521 // loop over pixels
5522
5523 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5524
5525 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5526 // linear plot
5527 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5528 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5529 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5530 std::make_pair(binLow, binHigh)};
5531 regions.push_back(region);
5532 }
5533 }
5534 } else {
5535 // standard linear plot
5536
5537 if (strategy == Bins) {
5538 // loop over bins
5539 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5540
5541 // linear plot. we simply need to find the appropriate bin
5542 // for the
5543 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5544 Int_t xPx1 = xPx0 + nPixels/nBins;
5545
5546 // make sure we don't compute beyond our bounds
5547 if (xPx1>= nPixels) xPx1 = nPixels-1;
5548
5549 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5550 std::make_pair(bin, bin+1)};
5551 regions.push_back(region);
5552 }
5553 } else {
5554 // loop over pixels
5555 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5556 // linear plot
5557 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5558 Int_t binHigh = binLow + nBins/nPixels;
5559 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5560 std::make_pair(binLow, binHigh)};
5561 regions.push_back(region);
5562 }
5563 }
5564 }
5565
5566 return regions;
5567}
5568
5569////////////////////////////////////////////////////////////////////////////////
5570/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5571
5573{
5574
5575 if (Hoption.System != kCARTESIAN) {
5576 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5577 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5578 PaintColorLevels(nullptr);
5579 return;
5580 }
5581
5582 Double_t z;
5583
5584 // Use existing max or min values. If either is already set
5585 // the appropriate value to use.
5586 Double_t zmin = fH->GetMinimumStored();
5587 Double_t zmax = fH->GetMaximumStored();
5588 Double_t originalZMin = zmin;
5589 Double_t originalZMax = zmax;
5590 if ((zmin == -1111) && (zmax == -1111)) {
5591 fH->GetMinimumAndMaximum(zmin, zmax);
5592 fH->SetMinimum(zmin);
5593 fH->SetMaximum(zmax);
5594 } else if (zmin == -1111) {
5595 zmin = fH->GetMinimum();
5596 fH->SetMinimum(zmin);
5597 } else if (zmax == -1111) {
5598 zmax = fH->GetMaximum();
5599 fH->SetMaximum(zmax);
5600 }
5601
5602 Double_t dz = zmax - zmin;
5603 if (dz <= 0) { // Histogram filled with a constant value
5604 zmax += 0.1*TMath::Abs(zmax);
5605 zmin -= 0.1*TMath::Abs(zmin);
5606 dz = zmax - zmin;
5607 }
5608
5609 if (Hoption.Logz) {
5610 if (zmin > 0) {
5611 zmin = TMath::Log10(zmin);
5612 zmax = TMath::Log10(zmax);
5613 dz = zmax - zmin;
5614 } else {
5615 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5616 "Cannot plot logz because bin content is less than 0.");
5617 return;
5618 }
5619 }
5620
5621 // Initialize the levels on the Z axis
5622 Int_t ndiv = fH->GetContour();
5623 if (ndiv == 0 ) {
5624 ndiv = gStyle->GetNumberContours();
5625 fH->SetContour(ndiv);
5626 }
5627 std::vector<Double_t> colorBounds(ndiv);
5628 std::vector<Double_t> contours(ndiv, 0);
5629 if (!fH->TestBit(TH1::kUserContour)) {
5630 fH->SetContour(ndiv);
5631 } else {
5632 fH->GetContour(contours.data());
5633 }
5634
5635 Double_t step = 1.0/ndiv;
5636 for (Int_t i=0; i<ndiv; ++i) {
5637 colorBounds[i] = step*i;
5638 }
5639
5640 auto pFrame = gPad->GetFrame();
5641 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5642 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5643 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5644 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5645 Int_t nXPixels = px1-px0;
5646 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5647
5648 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5649
5650 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5651 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5652 if (xRegions.empty() || yRegions.empty()) {
5653 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5654 "Encountered error while computing rendering regions.");
5655 return;
5656 }
5657
5658 Bool_t minExists = kFALSE;
5659 Bool_t maxExists = kFALSE;
5660 Double_t minValue = 1.;
5661 Double_t maxValue = 0.;
5662 for (auto& yRegion : yRegions) {
5663 for (auto& xRegion : xRegions ) {
5664
5665 const auto& xBinRange = xRegion.fBinRange;
5666 const auto& yBinRange = yRegion.fBinRange;
5667
5668 // sample the range
5669 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5670
5671 if (Hoption.Logz) {
5672 if (z > 0) z = TMath::Log10(z);
5673 else z = zmin;
5674 }
5675
5676 // obey the user's max and min values if they were set
5677 if (z > zmax) z = zmax;
5678 if (z < zmin) z = zmin;
5679
5681 // contours are absolute values
5682 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5683 z = colorBounds[index];
5684 } else {
5685 Int_t index = 0;
5686 if (dz != 0) {
5687 index = 0.001 + ((z - zmin)/dz)*ndiv;
5688 }
5689
5690 if (index == static_cast<Int_t>(colorBounds.size())) {
5691 index--;
5692 }
5693
5694 // Do a little bookkeeping to use later for getting libAfterImage to produce
5695 // the correct colors
5696 if (index == 0) {
5697 minExists = kTRUE;
5698 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5699 maxExists = kTRUE;
5700 }
5701
5702 z = colorBounds[index];
5703
5704 if (z < minValue) {
5705 minValue = z;
5706 }
5707 if (z > maxValue) {
5708 maxValue = z;
5709 }
5710 }
5711
5712 // fill in the actual pixels
5713 const auto& xPixelRange = xRegion.fPixelRange;
5714 const auto& yPixelRange = yRegion.fPixelRange;
5715 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5716 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5717 Int_t pixel = yPx*nXPixels + xPx;
5718 buffer[pixel] = z;
5719 }
5720 }
5721 } // end px loop
5722 } // end py loop
5723
5724 // This is a bit of a hack to ensure that we span the entire color range and
5725 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5726 // single pixel on the edge of the image to a different color. This is even more
5727 // true because the chosen pixels will be covered by the axis.
5728 if (minValue != maxValue) {
5729 if ( !minExists) {
5730 buffer.front() = 0;
5731 }
5732
5733 if ( !maxExists) {
5734 buffer[buffer.size()-nXPixels] = 0.95;
5735 }
5736 }
5737
5738 // Generate the TImage
5740 TImage* pImage = TImage::Create();
5742 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5743 delete pPalette;
5744
5745 auto pp = gPad->GetPainter();
5746 if (pp)
5747 pp->DrawImage(pImage, px0, py1);
5748
5749 delete pImage;
5750
5751 if (Hoption.Zscale)
5752 PaintPalette();
5753
5754 // Reset the maximum and minimum values to their original values
5755 // when this function was called. If we don't do this, an initial
5756 // value of -1111 will be replaced with the true max or min values.
5757 fH->SetMinimum(originalZMin);
5758 fH->SetMaximum(originalZMax);
5759}
5760
5761////////////////////////////////////////////////////////////////////////////////
5762/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5763
5765{
5766 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5767
5768 Double_t zmin = fH->GetMinimum();
5769 Double_t zmax = fH->GetMaximum();
5770
5771 Double_t dz = zmax - zmin;
5772 if (dz <= 0) { // Histogram filled with a constant value
5773 zmax += 0.1*TMath::Abs(zmax);
5774 zmin -= 0.1*TMath::Abs(zmin);
5775 dz = zmax - zmin;
5776 }
5777
5778 // In case of option SAME, zmin and zmax values are taken from the
5779 // first plotted 2D histogram.
5780 if (Hoption.Same > 0 && Hoption.Same < 10) {
5781 TH2 *h2;
5782 TIter next(gPad->GetListOfPrimitives());
5783 while ((h2 = (TH2 *)next())) {
5784 if (!h2->InheritsFrom(TH2::Class())) continue;
5785 zmin = h2->GetMinimum();
5786 zmax = h2->GetMaximum();
5787 fH->SetMinimum(zmin);
5788 fH->SetMaximum(zmax);
5789 if (Hoption.Logz) {
5790 if (zmin <= 0) {
5791 zmin = TMath::Log10(zmax*0.001);
5792 } else {
5793 zmin = TMath::Log10(zmin);
5794 }
5795 zmax = TMath::Log10(zmax);
5796 }
5797 dz = zmax - zmin;
5798 break;
5799 }
5800 } else {
5801 if (Hoption.Logz) {
5802 if (zmin > 0) {
5803 zmin = TMath::Log10(zmin);
5804 zmax = TMath::Log10(zmax);
5805 dz = zmax - zmin;
5806 } else {
5807 return;
5808 }
5809 }
5810 }
5811
5812 Style_t fillsav = fH->GetFillStyle();
5813 Style_t colsav = fH->GetFillColor();
5814 fH->SetFillStyle(1001);
5815 fH->TAttFill::Modify();
5816
5817 // Initialize the levels on the Z axis
5818 Int_t ncolors = gStyle->GetNumberOfColors();
5819 Int_t ndiv = fH->GetContour();
5820 if (ndiv == 0) {
5821 ndiv = gStyle->GetNumberContours();
5822 fH->SetContour(ndiv);
5823 }
5824 Int_t ndivz = TMath::Abs(ndiv);
5825 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5826 Double_t scale = (dz ? ndivz / dz : 1.0);
5827
5828 Double_t xmin = gPad->GetUxmin();
5829 Double_t xmax = gPad->GetUxmax();
5830 Double_t ymin = gPad->GetUymin();
5831 Double_t ymax = gPad->GetUymax();
5832
5833 // range used for polar coordinates
5834 Double_t pxmin = xmin, pxmax = xmax, pymin = ymin, pymax = ymax, pkr = 0.5;
5835 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 2)) {
5836 pxmin = fXaxis->GetXmin();
5837 pxmax = fXaxis->GetXmax();
5838 if (Hoption.Logx) {
5839 if (pxmax <= 0)
5840 return;
5841 pxmax = TMath::Log10(pxmax);
5842 if (pxmin <= 0)
5843 pxmin = pxmax - 5;
5844 else
5845 pxmin = TMath::Log10(pxmin);
5846 }
5847 pkr = 0.45; // makes fixed range more pretty
5848 pymin = fYaxis->GetXmin();
5849 pymax = fYaxis->GetXmax();
5850 if (Hoption.Logy) {
5851 if (pymax <= 0)
5852 return;
5853 pymax = TMath::Log10(pymax);
5854 if (pymin <= 0)
5855 pymin = pymax - 5;
5856 else
5857 pymin = TMath::Log10(pymin);
5858 } else if ((pymax > 0) && (pymin > 0)) {
5859 // force minimal radius to 0 to display natural polar graphics
5860 pymin = 0;
5861 }
5862 }
5863
5864 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 3)) {
5865 // do not touch boundaries when draw without axis histogram
5866 if (!Hoption.Same)
5867 pkr = 0.45;
5868 // for natural coordinates force minimal radius to 0
5869 if (!Hoption.Logy && (pymax > 0))
5870 pymin = 0;
5871 }
5872
5873 Int_t color;
5874 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5875 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5876 yk = fYaxis->GetBinLowEdge(j);
5877 ystep = fYaxis->GetBinWidth(j);
5878 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5879 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5880 xk = fXaxis->GetBinLowEdge(i);
5881 xstep = fXaxis->GetBinWidth(i);
5882 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5883 z = fH->GetBinContent(bin);
5884 e = fH->GetBinError(bin);
5885 // if fH is a profile histogram do not draw empty bins
5886 if (prof2d) {
5887 const Double_t binEntries = prof2d->GetBinEntries(bin);
5888 if (binEntries == 0)
5889 continue;
5890 } else {
5891 // don't draw the empty bins for non-profile histograms
5892 // with positive content
5893 if (z == 0 && e == 0) {
5894 if (zmin >= 0 || Hoption.Logz) continue;
5895 if (Hoption.Color == 2) continue;
5896 }
5897 }
5898
5899 if (Hoption.Logz)
5900 z = z > 0 ? TMath::Log10(z) : zmin;
5901 if (z < zmin && !Hoption.Zero)
5902 continue;
5903 xup = xk + xstep;
5904 xlow = xk;
5905 if (Hoption.Logx) {
5906 if ((xup <= 0) || (xlow <= 0))
5907 continue;
5908 xup = TMath::Log10(xup);
5909 xlow = TMath::Log10(xlow);
5910 }
5911 yup = yk + ystep;
5912 ylow = yk;
5913 if (Hoption.Logy) {
5914 if ((yup <= 0) || (ylow <= 0))
5915 continue;
5916 yup = TMath::Log10(yup);
5917 ylow = TMath::Log10(ylow);
5918 }
5919 if ((xup < xmin) || (yup < ymin) || (xlow > xmax) || (ylow > ymax))
5920 continue;
5921 if (xlow < xmin)
5922 xlow = xmin;
5923 if (ylow < ymin)
5924 ylow = ymin;
5925 if (xup > xmax)
5926 xup = xmax;
5927 if (yup > ymax)
5928 yup = ymax;
5929
5931 zc = fH->GetContourLevelPad(0);
5932 if (z < zc) continue;
5933 color = -1;
5934 for (Int_t k=0; k<ndiv; k++) {
5935 zc = fH->GetContourLevelPad(k);
5936 if (z < zc) {
5937 continue;
5938 } else {
5939 color++;
5940 }
5941 }
5942 } else {
5943 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5944 }
5945
5946 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5947 if (theColor > ncolors-1)
5948 theColor = ncolors-1;
5949 auto fillColor = gStyle->GetColorPalette(theColor);
5950 if (Hoption.System != kPOLAR) {
5951 fH->SetFillColor(fillColor);
5952 fH->TAttFill::Modify();
5953 gPad->PaintBox(xlow, ylow, xup, yup);
5954 } else {
5955 Double_t midx = (xmin + xmax) / 2;
5956 Double_t midy = (ymin + ymax) / 2;
5957 Double_t rx = xmax - xmin;
5958 Double_t ry = ymax - ymin;
5959 Double_t a1, a2;
5960
5961 if (Hoption.Polar == 3) {
5962 a1 = xlow / TMath::Pi() * 180;
5963 a2 = xup / TMath::Pi() * 180;
5964 } else {
5965 a1 = ((xlow - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5966 a2 = ((xup - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5967 }
5968 Double_t r1 = (ylow - pymin) / (pymax - pymin) * rx * pkr;
5969 Double_t r2 = (yup - pymin) / (pymax - pymin) * rx * pkr;
5970
5971 TCrown crown(midx, midy, r1, r2, a1, a2);
5972 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5973 crown.SetFillColor(fillColor);
5974 crown.SetLineColor(fH->GetLineColor());
5975 crown.SetLineWidth(fH->GetLineWidth());
5976 crown.SetLineStyle(fH->GetLineStyle());
5977 crown.Paint();
5978 }
5979 }
5980 }
5981
5983
5984 fH->SetFillStyle(fillsav);
5985 fH->SetFillColor(colsav);
5986 fH->TAttFill::Modify();
5987
5988}
5989
5990////////////////////////////////////////////////////////////////////////////////
5991/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5992
5994{
5995
5996 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5997 Int_t itars, mode, ir[4];
5998 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5999
6000 if (Hoption.Contour == 14) {
6001 Hoption.Surf = 12;
6002 Hoption.Axis = 1;
6003 thesave = gPad->GetTheta();
6004 phisave = gPad->GetPhi();
6005 gPad->SetPhi(0.);
6006 gPad->SetTheta(90.);
6008 gPad->SetPhi(phisave);
6009 gPad->SetTheta(thesave);
6010 TView *view = gPad->GetView();
6011 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
6012 PaintAxis();
6013 return;
6014 }
6015
6016 if (Hoption.Same) {
6017 // If the contour is painted on a 3d plot, the contour lines are
6018 // paint in 3d too.
6019 TObject *obj;
6020 TIter next(gPad->GetListOfPrimitives());
6021 while ((obj=next())) {
6022 if (strstr(obj->GetDrawOption(),"surf") ||
6023 strstr(obj->GetDrawOption(),"lego") ||
6024 strstr(obj->GetDrawOption(),"tri")) {
6025 Hoption.Surf = 16;
6027 return;
6028 }
6029 }
6030 }
6031
6032 if (Hoption.Contour == 15) {
6033 TGraphDelaunay2D *dt = nullptr;
6034 TGraphDelaunay *dtOld = nullptr;
6035 TList *hl = fH->GetListOfFunctions();
6036 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6037 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6038 if (!dt && !dtOld) return;
6039 if (!fGraph2DPainter)
6040 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6041 fGraph2DPainter->Paint(option);
6042 return;
6043 }
6044
6045 gPad->SetBit(TGraph::kClipFrame);
6046
6047 std::vector<Double_t> levels(2*kMAXCONTOUR);
6048 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6049 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6050 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6051
6052 Int_t npmax = 0;
6053 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6054
6055 ncontour = fH->GetContour();
6056 if (ncontour == 0) {
6057 ncontour = gStyle->GetNumberContours();
6058 fH->SetContour(ncontour);
6059 }
6060 if (ncontour > kMAXCONTOUR) {
6061 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6062 kMAXCONTOUR, ncontour);
6063 ncontour = kMAXCONTOUR-1;
6064 }
6065 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ncontour);
6066
6067 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6068 Int_t linesav = fH->GetLineStyle();
6069 Int_t colorsav = fH->GetLineColor();
6070 Int_t fillsav = fH->GetFillColor();
6071 if (Hoption.Contour == 13) {
6072 fH->TAttLine::Modify();
6073 }
6074
6075 std::vector<std::unique_ptr<TPolyLine>> polys;
6076 TObjArray *contours = nullptr;
6077 TList *list = nullptr;
6078 TGraph *graph = nullptr;
6079 std::vector<Int_t> np;
6080 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6081 np.resize(ncontour);
6082 for (i=0;i<ncontour;i++)
6083 np[i] = 0;
6084 for (i=0;i<ncontour;i++)
6085 polys.emplace_back(std::make_unique<TPolyLine>(100));
6086 if (Hoption.List == 1) {
6087 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6088 if (contours) {
6089 gROOT->GetListOfSpecials()->Remove(contours);
6090 count = contours->GetSize();
6091 for (i=0;i<count;i++) {
6092 list = (TList*)contours->At(i);
6093 if (list) list->Delete();
6094 }
6095 contours->Delete();
6096 delete contours;
6097 }
6098 contours = new TObjArray(ncontour);
6099 contours->SetName("contours");
6100 gROOT->GetListOfSpecials()->Add(contours);
6101 for (i=0;i<ncontour;i++) {
6102 list = new TList();
6103 contours->Add(list);
6104 }
6105 }
6106 }
6107 Int_t theColor;
6108 Int_t ncolors = gStyle->GetNumberOfColors();
6109 Int_t ndivz = TMath::Abs(ncontour);
6110
6111 Int_t k,ipoly;
6112 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6113 y[0] = fYaxis->GetBinCenter(j);
6114 y[1] = y[0];
6115 y[2] = fYaxis->GetBinCenter(j+1);
6116 y[3] = y[2];
6117 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6118 zc[0] = fH->GetBinContent(i, j);
6119 zc[1] = fH->GetBinContent(i+1, j);
6120 zc[2] = fH->GetBinContent(i+1, j+1);
6121 zc[3] = fH->GetBinContent(i, j+1);
6122 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6123 if (Hoption.Logz) {
6124 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6125 else zc[0] = Hparam.zmin;
6126 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6127 else zc[1] = Hparam.zmin;
6128 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6129 else zc[2] = Hparam.zmin;
6130 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6131 else zc[3] = Hparam.zmin;
6132 }
6133 for (k=0;k<4;k++) {
6134 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6135 }
6136 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6137 x[0] = fXaxis->GetBinCenter(i);
6138 x[3] = x[0];
6139 x[1] = fXaxis->GetBinCenter(i+1);
6140 x[2] = x[1];
6141 if (zc[0] <= zc[1]) n = 0; else n = 1;
6142 if (zc[2] <= zc[3]) m = 2; else m = 3;
6143 if (zc[n] > zc[m]) n = m;
6144 n++;
6145 lj=1;
6146 for (ix=1;ix<=4;ix++) {
6147 m = n%4 + 1;
6148 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6149 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6150 lj += 2*ljfill;
6151 n = m;
6152 }
6153
6154 if (zc[0] <= zc[1]) n = 0; else n = 1;
6155 if (zc[2] <= zc[3]) m = 2; else m = 3;
6156 if (zc[n] > zc[m]) n = m;
6157 n++;
6158 lj=2;
6159 for (ix=1;ix<=4;ix++) {
6160 if (n == 1) m = 4;
6161 else m = n-1;
6162 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6163 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6164 lj += 2*ljfill;
6165 n = m;
6166 }
6167
6168 // Re-order endpoints
6169
6170 count = 0;
6171 for (ix=1; ix<=lj-5; ix +=2) {
6172 //count = 0;
6173 while (itarr[ix-1] != itarr[ix]) {
6174 xsave = xarr[ix];
6175 ysave = yarr[ix];
6176 itars = itarr[ix];
6177 for (jx=ix; jx<=lj-5; jx +=2) {
6178 xarr[jx] = xarr[jx+2];
6179 yarr[jx] = yarr[jx+2];
6180 itarr[jx] = itarr[jx+2];
6181 }
6182 xarr[lj-3] = xsave;
6183 yarr[lj-3] = ysave;
6184 itarr[lj-3] = itars;
6185 if (count > 100) break;
6186 count++;
6187 }
6188 }
6189
6190 if (count > 100) continue;
6191 for (ix=1; ix<=lj-2; ix +=2) {
6192 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6193 icol = gStyle->GetColorPalette(theColor);
6194 if (Hoption.Contour == 11) {
6195 fH->SetLineColor(icol);
6196 }
6197 if (Hoption.Contour == 12) {
6198 mode = icol%5;
6199 if (mode == 0) mode = 5;
6201 }
6202 if (Hoption.Contour != 1) {
6203 fH->TAttLine::Modify();
6204 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6205 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6206 continue;
6207 }
6208
6209 ipoly = itarr[ix-1];
6210 if (ipoly >=0 && ipoly <ncontour) {
6211 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6212 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6213 np[ipoly] += 2;
6214 if (npmax < np[ipoly]) npmax = np[ipoly];
6215 }
6216 }
6217 } // end of if (ir[0]
6218 } //end of for (i
6219 } //end of for (j
6220
6222 std::vector<Double_t> xp, yp;
6223 Int_t nadd,iminus,iplus;
6224 Int_t istart;
6225 Int_t first = ncontour;
6226 std::vector<Int_t> polysort;
6227 Int_t contListNb;
6228 if (Hoption.Contour != 1) {
6229 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6230 goto theEND;
6231 }
6232
6233 //The 2 points line generated above are now sorted/merged to generate
6234 //a list of consecutive points.
6235 // If the option "List" has been specified, the list of points is saved
6236 // in the form of TGraph objects in the ROOT list of special objects.
6237 xmin = gPad->GetUxmin();
6238 ymin = gPad->GetUymin();
6239 xp.resize(2*npmax);
6240 yp.resize(2*npmax);
6241 polysort.resize(ncontour);
6242 //find first positive contour
6243 for (ipoly=0;ipoly<ncontour;ipoly++) {
6244 if (levels[ipoly] >= 0) {first = ipoly; break;}
6245 }
6246 //store negative contours from 0 to minimum, then all positive contours
6247 k = 0;
6248 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6249 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6250 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6251 contListNb = 0;
6252 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6253 for (k=0;k<ncontour;k++) {
6254 ipoly = polysort[k];
6255 if (Hoption.List) list = (TList*)contours->At(contListNb);
6256 contListNb++;
6257 if (np[ipoly] == 0)
6258 continue;
6259 Double_t *xx = polys[ipoly]->GetX();
6260 Double_t *yy = polys[ipoly]->GetY();
6261 istart = 0;
6262 while (true) {
6263 iminus = npmax;
6264 iplus = iminus+1;
6265 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6266 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6267 xx[istart] = xmin; yy[istart] = ymin;
6268 xx[istart+1] = xmin; yy[istart+1] = ymin;
6269 while (true) {
6270 nadd = 0;
6271 for (i=2;i<np[ipoly];i+=2) {
6272 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6273 iplus++;
6274 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6275 xx[i] = xmin; yy[i] = ymin;
6276 xx[i+1] = xmin; yy[i+1] = ymin;
6277 nadd++;
6278 }
6279 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6280 iminus--;
6281 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6282 xx[i] = xmin; yy[i] = ymin;
6283 xx[i+1] = xmin; yy[i+1] = ymin;
6284 nadd++;
6285 }
6286 }
6287 if (nadd == 0) break;
6288 }
6289 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6290 icol = gStyle->GetColorPalette(theColor);
6291 if (Hoption.Contour == 1) {
6292 if (ndivz > 1) fH->SetFillColor(icol);
6293 fH->TAttFill::Modify();
6294 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6295 }
6296 if (Hoption.List) {
6297 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6298 if (Hoption.Contour == 1)
6299 graph->SetFillColor(icol);
6300 else if (Hoption.Contour == 11)
6301 graph->SetLineColor(icol);
6302 else if (Hoption.Contour == 12) {
6303 mode = icol%5;
6304 if (mode == 0) mode = 5;
6305 graph->SetLineStyle(mode);
6306 }
6307 graph->SetLineWidth(fH->GetLineWidth());
6308 list->Add(graph);
6309 }
6310 //check if more points are left
6311 istart = 0;
6312 for (i=2;i<np[ipoly];i+=2) {
6313 if (xx[i] != xmin && yy[i] != ymin) {
6314 istart = i;
6315 break;
6316 }
6317 }
6318 if (istart == 0) break;
6319 }
6320 }
6321
6322theEND:
6323 gPad->ResetBit(TGraph::kClipFrame);
6325 fH->SetLineStyle(linesav);
6326 fH->SetLineColor(colorsav);
6327 fH->SetFillColor(fillsav);
6328}
6329
6330////////////////////////////////////////////////////////////////////////////////
6331/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6332
6334 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6335 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6336{
6337
6338 Bool_t vert;
6339 Double_t tlen, tdif, elev, diff, pdif, xlen;
6340 Int_t n, i, icount;
6341
6342 if (x1 == x2) {
6343 vert = kTRUE;
6344 tlen = y2 - y1;
6345 } else {
6346 vert = kFALSE;
6347 tlen = x2 - x1;
6348 }
6349
6350 n = icont1 +1;
6351 tdif = elev2 - elev1;
6352 i = 0;
6353 icount = 0;
6354 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6355 //elev = fH->GetContourLevel(n);
6356 elev = levels[n];
6357 diff = elev - elev1;
6358 pdif = diff/tdif;
6359 xlen = tlen*pdif;
6360 if (vert) {
6361 if (Hoption.Logx)
6362 xarr[i] = TMath::Log10(x1);
6363 else
6364 xarr[i] = x1;
6365 if (Hoption.Logy)
6366 yarr[i] = TMath::Log10(y1 + xlen);
6367 else
6368 yarr[i] = y1 + xlen;
6369 } else {
6370 if (Hoption.Logx)
6371 xarr[i] = TMath::Log10(x1 + xlen);
6372 else
6373 xarr[i] = x1 + xlen;
6374 if (Hoption.Logy)
6375 yarr[i] = TMath::Log10(y1);
6376 else
6377 yarr[i] = y1;
6378 }
6379 itarr[i] = n;
6380 icount++;
6381 i +=2;
6382 n++;
6383 }
6384 return icount;
6385}
6386
6387////////////////////////////////////////////////////////////////////////////////
6388/// [Draw 1D histograms error bars.](\ref HP09)
6389
6391{
6392
6393 // On iOS, we do not highlight histogram, if it's not picked at the moment
6394 // (but part of histogram (axis or pavestat) was picked, that's why this code
6395 // is called at all. This conditional statement never executes on non-iOS platform.
6396 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6397
6398 const Int_t kBASEMARKER=8;
6399 Double_t xp, yp, ex1, ex2, ey1, ey2;
6400 Double_t delta;
6401 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbasex, sbasey;
6402 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6404 Double_t logxmin = 0;
6405 Double_t logymin = 0;
6406 Double_t offset = 0.;
6407 Double_t width = 0.;
6408 Int_t i, k, npoints, first, last, fixbin;
6409 Int_t if1 = 0;
6410 Int_t if2 = 0;
6411 Bool_t drawmarker;
6412 Int_t errormarker;
6413 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6414 static Float_t cxx[30] = {1.0,1.0,0.5,0.5,1.0,1.0,0.5,0.6,1.0,0.5,0.5,1.0,0.5,0.6,1.0,1.0,1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0};
6415 static Float_t cyy[30] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.5,0.5,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0};
6416
6417 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6418 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6419 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6420 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6421 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6422 if (Hoption.Error == 11) option1 = 1;
6423 if (Hoption.Error == 12) option2 = 1;
6424 if (Hoption.Error == 13) option3 = 1;
6425 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6426 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6427 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6428 if (option2+option3 == 0) optionE = 1;
6429 if (Hoption.Error == 0) optionE = 0;
6430 if (fXaxis->GetXbins()->fN) fixbin = 0;
6431 else fixbin = 1;
6432
6433 offset = fH->GetBarOffset();
6434 width = fH->GetBarWidth();
6435
6437 if (optionEX0) {
6438 xerror = 0;
6439 } else {
6440 xerror = gStyle->GetErrorX();
6441 }
6442 symbolsize = fH->GetMarkerSize();
6443 if (errormarker == 1) symbolsize = 0.01;
6444 sbasex = sbasey = symbolsize*kBASEMARKER;
6445 if (errormarker >= 20 && errormarker <= 49) {
6446 sbasex *= cxx[errormarker-20];
6447 sbasey *= cyy[errormarker-20];
6448 }
6449 // set the graphics attributes
6450
6451 fH->TAttLine::Modify();
6452 fH->TAttFill::Modify();
6453 fH->TAttMarker::Modify();
6454
6455 // set the first and last bin
6456
6457 Double_t factor = Hparam.factor;
6458 first = Hparam.xfirst;
6459 last = Hparam.xlast;
6460 npoints = last - first +1;
6461 xmin = gPad->GetUxmin();
6462 xmax = gPad->GetUxmax();
6463 ymin = gPad->GetUymin();
6464 ymax = gPad->GetUymax();
6465
6466 xsegm.reserve(1024);
6467 ysegm.reserve(1024);
6468 if (!xsegm.capacity() || !ysegm.capacity()) {
6469 Error("PaintErrors", "out of memory for lines painting");
6470 return;
6471 }
6472
6473 auto flush_segmentes = [&]() {
6474 if (xsegm.size() > 0) {
6475 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6476 xsegm.clear();
6477 ysegm.clear();
6478 }
6479 };
6480
6481 auto add_segment = [&](Double_t x1, Double_t y1, Double_t x2, Double_t y2) {
6482 xsegm.emplace_back(x1);
6483 xsegm.emplace_back(x2);
6484 ysegm.emplace_back(y1);
6485 ysegm.emplace_back(y2);
6486 if (xsegm.size() == xsegm.capacity())
6487 flush_segmentes();
6488 };
6489
6490 auto flush_markers = [&]() {
6491 if (xmarker.size() > 0) {
6492 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6493 xmarker.clear();
6494 ymarker.clear();
6495 }
6496 };
6497
6498 auto add_marker = [&](Double_t x, Double_t y) {
6499 if (xmarker.capacity() == 0) {
6500 xmarker.reserve(256);
6501 ymarker.reserve(256);
6502 }
6503
6504 xmarker.emplace_back(x);
6505 ymarker.emplace_back(y);
6506 if (xmarker.size() == xmarker.capacity()) {
6507 flush_segmentes();
6508 flush_markers();
6509 }
6510 };
6511
6512
6513 if (option3) {
6514 xline.resize(2*npoints);
6515 yline.resize(2*npoints);
6516 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6517 Error("PaintErrors", "too many points, out of memory");
6518 return;
6519 }
6520 if1 = 1;
6521 if2 = 2*npoints;
6522 }
6523
6524 // compute the offset of the error bars due to the symbol size
6525 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6526 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6527
6528 // compute size of the lines at the end of the error bars
6529 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6530 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6531 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6532
6533
6534 if (fixbin) {
6535 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6536 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6537 } else {
6538 delta = fH->GetBinWidth(first);
6539 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6540 }
6541
6542 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6543 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6544 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6545
6546 // ---------------------- Loop over the points---------------------
6547 for (k=first; k<=last; k++) {
6548
6549 // get the data
6550 // xp = X position of the current point
6551 // yp = Y position of the current point
6552 // ex1 = Low X error
6553 // ex2 = Up X error
6554 // ey1 = Low Y error
6555 // ey2 = Up Y error
6556 // (xi,yi) = Error bars coordinates
6557
6558 // apply offset on errors for bar histograms
6559 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6560 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6561 if (Hoption.Logx) {
6562 xminTmp = TMath::Power(10, xminTmp);
6563 xmaxTmp = TMath::Power(10, xmaxTmp);
6564 }
6565 Double_t w = (xmaxTmp-xminTmp)*width;
6566 xminTmp += offset*(xmaxTmp-xminTmp);
6567 xmaxTmp = xminTmp + w;
6568 xp = (xminTmp+xmaxTmp)/2.;
6569
6570 if (Hoption.Logx) {
6571 if (xp <= 0) goto L30;
6572 if (xp < logxmin) goto L30;
6573 if (xp > TMath::Power(10,xmax)) break;
6574 } else {
6575 if (xp < xmin) goto L30;
6576 if (xp > xmax) break;
6577 }
6578 yp = factor*fH->GetBinContent(k);
6579 if (optionI0 && yp==0) goto L30;
6580 if (fixbin) {
6581 ex1 = xerror*Hparam.xbinsize;
6582 } else {
6583 delta = fH->GetBinWidth(k);
6584 ex1 = xerror*delta;
6585 }
6586 if (fH->GetBinErrorOption() == TH1::kNormal) {
6587 ey1 = factor*fH->GetBinError(k);
6588 ey2 = ey1;
6589 } else {
6590 ey1 = factor*fH->GetBinErrorLow(k);
6591 ey2 = factor*fH->GetBinErrorUp(k);
6592 }
6593 ex2 = ex1;
6594
6595 xi4 = xp;
6596 xi3 = xp;
6597 xi2 = xp + ex2;
6598 xi1 = xp - ex1;
6599
6600 yi1 = yp;
6601 yi2 = yp;
6602 yi3 = yp - ey1;
6603 yi4 = yp + ey2;
6604
6605 // take the LOG if necessary
6606 if (Hoption.Logx) {
6607 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6608 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6609 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6610 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6611 }
6612 if (Hoption.Logy) {
6613 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6614 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6615 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6616 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6617 }
6618
6619 // test if error bars are not outside the limits
6620 // otherwise they are truncated
6621
6622 xi1 = TMath::Max(xi1,xmin);
6623 xi2 = TMath::Min(xi2,xmax);
6624 yi3 = TMath::Max(yi3,ymin);
6625 yi4 = TMath::Min(yi4,ymax);
6626
6627 // test if the marker is on the frame limits. If "Yes", the
6628 // marker will not be drawn and the error bars will be readjusted.
6629
6630 drawmarker = kTRUE;
6631 if (!option0 && !option3) {
6632 if (Hoption.Logy && yp < logymin) goto L30;
6633 if (yi1 < ymin || yi1 > ymax) goto L30;
6634 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6635 }
6636 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6637
6638 // draw the error rectangles
6639 if (option2) {
6640 if ((yi3 >= ymax) || (yi4 <= ymin))
6641 goto L30;
6642 gPad->PaintBox(xi1,yi3,xi2,yi4);
6643 }
6644
6645 // keep points for fill area drawing
6646 if (option3) {
6647 xline[if1-1] = xi3;
6648 xline[if2-1] = xi3;
6649 yline[if1-1] = yi4;
6650 yline[if2-1] = yi3;
6651 if1++;
6652 if2--;
6653 }
6654
6655 // draw the error bars
6656 if (Hoption.Logy && yp < logymin)
6657 drawmarker = kFALSE;
6658 if (optionE && drawmarker) {
6659 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6660 add_segment(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6661 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6662 add_segment(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6663 // don't duplicate the horizontal line
6664 if (Hoption.Hist != 2) {
6665 if (yi1<ymax && yi1>ymin) {
6666 if (xi1 < xi3 - s2x)
6667 add_segment(xi1,yi1,xi3 - s2x,yi2);
6668 if (xi3 + s2x < xi2)
6669 add_segment(xi3 + s2x,yi1,xi2,yi2);
6670 }
6671 }
6672 }
6673 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6674 if ((yi3 < yi1) && (yi3 < ymax))
6675 add_segment(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6676 if ((yi1 < yi4) && (yi4 > ymin))
6677 add_segment(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6678 // don't duplicate the horizontal line
6679 if (Hoption.Hist != 2) {
6680 if (yi1<ymax && yi1>ymin) {
6681 if (xi1 < xi3)
6682 add_segment(xi1,yi1,xi3,yi2);
6683 if (xi3 < xi2)
6684 add_segment(xi3,yi1,xi2,yi2);
6685 }
6686 }
6687 }
6688
6689 // draw line at the end of the error bars
6690
6691 if (option1 && drawmarker) {
6692
6693 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin)
6694 add_segment(xi3 - bxsize, yi3, xi3 + bxsize, yi3);
6695 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin)
6696 add_segment(xi3 - bxsize, yi4, xi3 + bxsize, yi4);
6697 if (yi1 <= ymax && yi1 >= ymin) {
6698 if (xi1 < xi3-s2x)
6699 add_segment(xi1, yi1 - bysize, xi1, yi1 + bysize);
6700 if (xi2 > xi3+s2x)
6701 add_segment(xi2, yi1 - bysize, xi2, yi1 + bysize);
6702 }
6703 }
6704
6705 // draw the marker
6706
6707 if (drawmarker)
6708 add_marker(xi3, yi1);
6709
6710L30:
6711 if (fixbin) xp += Hparam.xbinsize;
6712 else {
6713 if (k < last) {
6714 delta = fH->GetBinWidth(k+1);
6715 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6716 }
6717 }
6718 } //end of for loop
6719
6720 flush_segmentes();
6721
6722 flush_markers();
6723
6724
6725 // draw the filled area
6726
6727 if (option3) {
6728 TGraph graph;
6729 graph.SetLineStyle(fH->GetLineStyle());
6730 graph.SetLineColor(fH->GetLineColor());
6731 graph.SetLineWidth(fH->GetLineWidth());
6732 graph.SetFillStyle(fH->GetFillStyle());
6733 graph.SetFillColor(fH->GetFillColor());
6734 Int_t logx = gPad->GetLogx();
6735 Int_t logy = gPad->GetLogy();
6736 gPad->SetLogx(0);
6737 gPad->SetLogy(0);
6738
6739 // In some cases the number of points in the fill area is smaller than
6740 // 2*npoints. In such cases the array xline and yline must be arranged
6741 // before being plotted. The next loop does that.
6742 if (if2 > npoints) {
6743 for (i=1; i<if1; i++) {
6744 xline[if1-2+i] = xline[if2-1+i];
6745 yline[if1-2+i] = yline[if2-1+i];
6746 }
6747 npoints = if1-1;
6748 }
6749 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6750 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6751 gPad->SetLogx(logx);
6752 gPad->SetLogy(logy);
6753 }
6754}
6755
6756////////////////////////////////////////////////////////////////////////////////
6757/// Draw 2D histograms errors.
6758
6760{
6761
6762 fH->TAttMarker::Modify();
6763 fH->TAttLine::Modify();
6764
6765 // Define the 3D view
6766 fXbuf[0] = Hparam.xmin;
6767 fYbuf[0] = Hparam.xmax;
6768 fXbuf[1] = Hparam.ymin;
6769 fYbuf[1] = Hparam.ymax;
6770 fXbuf[2] = Hparam.zmin;
6771 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6772 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6773 TView *view = gPad ? gPad->GetView() : nullptr;
6774 if (!view) {
6775 Error("Paint2DErrors", "no TView in current pad");
6776 return;
6777 }
6778 Double_t thedeg = 90 - gPad->GetTheta();
6779 Double_t phideg = -90 - gPad->GetPhi();
6780 Double_t psideg = view->GetPsi();
6781 Int_t irep;
6782 view->SetView(phideg, thedeg, psideg, irep);
6783
6784 // Set color/style for back box
6785 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6786 fLego->SetFillColor(gPad->GetFrameFillColor());
6787 fLego->TAttFill::Modify();
6788 Int_t backcolor = gPad->GetFrameFillColor();
6789 if (Hoption.System != kCARTESIAN) backcolor = 0;
6790 view->PadRange(backcolor);
6791 fLego->SetFillStyle(fH->GetFillStyle());
6792 fLego->SetFillColor(fH->GetFillColor());
6793 fLego->TAttFill::Modify();
6794
6795 // Paint the Back Box if needed
6796 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6797 fLego->InitMoveScreen(-1.1,1.1);
6798 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6800 fLego->BackBox(90);
6801 }
6802
6803 // Paint the Errors
6804 Double_t x, ex, x1, x2;
6805 Double_t y, ey, y1, y2;
6806 Double_t z, ez1, ez2, z1, z2;
6807 Double_t temp1[3],temp2[3];
6808 Double_t xyerror;
6809 if (Hoption.Error == 110) {
6810 xyerror = 0;
6811 } else {
6812 xyerror = gStyle->GetErrorX();
6813 }
6814
6815 Double_t xk, xstep, yk, ystep;
6816 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6817 y = fYaxis->GetBinCenter(j);
6818 ey = fYaxis->GetBinWidth(j)*xyerror;
6819 y1 = y-ey;
6820 y2 = y+ey;
6821 if (Hoption.Logy) {
6822 if (y > 0) y = TMath::Log10(y);
6823 else continue;
6824 if (y1 > 0) y1 = TMath::Log10(y1);
6825 else y1 = Hparam.ymin;
6826 if (y2 > 0) y2 = TMath::Log10(y2);
6827 else y2 = Hparam.ymin;
6828 }
6829 yk = fYaxis->GetBinLowEdge(j);
6830 ystep = fYaxis->GetBinWidth(j);
6831 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6832 xk = fXaxis->GetBinLowEdge(i);
6833 xstep = fXaxis->GetBinWidth(i);
6834 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6835 Int_t bin = fH->GetBin(i,j);
6836 x = fXaxis->GetBinCenter(i);
6837 ex = fXaxis->GetBinWidth(i)*xyerror;
6838 x1 = x-ex;
6839 x2 = x+ex;
6840 if (Hoption.Logx) {
6841 if (x > 0) x = TMath::Log10(x);
6842 else continue;
6843 if (x1 > 0) x1 = TMath::Log10(x1);
6844 else x1 = Hparam.xmin;
6845 if (x2 > 0) x2 = TMath::Log10(x2);
6846 else x2 = Hparam.xmin;
6847 }
6848 z = fH->GetBinContent(bin);
6849 if (fH->GetBinErrorOption() == TH1::kNormal) {
6850 ez1 = fH->GetBinError(bin);
6851 ez2 = ez1;
6852 }
6853 else {
6854 ez1 = fH->GetBinErrorLow(bin);
6855 ez2 = fH->GetBinErrorUp(bin);
6856 }
6857 z1 = z - ez1;
6858 z2 = z + ez2;
6859 if (Hoption.Logz) {
6860 if (z > 0) z = TMath::Log10(z);
6861 else z = Hparam.zmin;
6862 if (z1 > 0) z1 = TMath::Log10(z1);
6863 else z1 = Hparam.zmin;
6864 if (z2 > 0) z2 = TMath::Log10(z2);
6865 else z2 = Hparam.zmin;
6866
6867 }
6868 if (z <= Hparam.zmin) continue;
6869 if (z > Hparam.zmax) z = Hparam.zmax;
6870
6871 temp1[0] = x1;
6872 temp1[1] = y;
6873 temp1[2] = z;
6874 temp2[0] = x2;
6875 temp2[1] = y;
6876 temp2[2] = z;
6877 gPad->PaintLine3D(temp1, temp2);
6878 temp1[0] = x;
6879 temp1[1] = y1;
6880 temp1[2] = z;
6881 temp2[0] = x;
6882 temp2[1] = y2;
6883 temp2[2] = z;
6884 gPad->PaintLine3D(temp1, temp2);
6885 temp1[0] = x;
6886 temp1[1] = y;
6887 temp1[2] = z1;
6888 temp2[0] = x;
6889 temp2[1] = y;
6890 temp2[2] = z2;
6891 gPad->PaintLine3D(temp1, temp2);
6892 temp1[0] = x;
6893 temp1[1] = y;
6894 temp1[2] = z;
6895 view->WCtoNDC(temp1, &temp2[0]);
6896 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6897 }
6898 }
6899
6900 // Paint the Front Box if needed
6901 if (Hoption.FrontBox) {
6902 fLego->InitMoveScreen(-1.1,1.1);
6904 fLego->FrontBox(90);
6905 }
6906
6907 // Paint the Axis if needed
6908 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6909 TGaxis axis;
6910 PaintLegoAxis(&axis, 90);
6911 }
6912
6913 fLego.reset();
6914}
6915
6916////////////////////////////////////////////////////////////////////////////////
6917/// Calculate range and clear pad (canvas).
6918
6920{
6921
6922 if (Hoption.Same) return;
6923
6925
6926 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6927 Hoption.Contour == 14 || Hoption.Error >= 100) {
6928 TObject *frame = gPad->FindObject("TFrame");
6929 if (frame) gPad->Remove(frame);
6930 return;
6931 }
6932
6933 //The next statement is always executed on non-iOS platform,
6934 //on iOS depends on pad mode.
6935 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6936 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6937}
6938
6939////////////////////////////////////////////////////////////////////////////////
6940/// [Paint functions associated to an histogram.](\ref HP28")
6941
6943{
6944 auto lnk = fFunctions->FirstLink();
6945
6946 while (lnk) {
6947 auto obj = lnk->GetObject();
6948 TVirtualPad::TContext ctxt(true);
6949 if (obj->InheritsFrom(TF2::Class())) {
6950 if (!obj->TestBit(TF2::kNotDraw)) {
6951 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6952 TF2 *f2 = (TF2*)obj;
6953 f2->SetMinimum(fH->GetMinimum());
6954 f2->SetMaximum(fH->GetMaximum());
6955 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6956 f2->Paint("surf same");
6957 } else {
6958 obj->Paint("cont3 same");
6959 }
6960 }
6961 } else if (obj->InheritsFrom(TF1::Class())) {
6962 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6963 } else {
6964 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6965 gPad->PushSelectableObject(obj);
6966
6967 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6968 //and picked object.
6969 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6970 obj->Paint(lnk->GetOption());
6971 }
6972 lnk = lnk->Next();
6973 }
6974}
6975
6976////////////////////////////////////////////////////////////////////////////////
6977/// [Control routine to draw 1D histograms](\ref HP01b)
6978
6980{
6981
6982 //On iOS: do not highlight hist, if part of it was selected.
6983 //Never executes on non-iOS platform.
6984 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6985 return;
6986
6987 static char chopth[17];
6988
6989 Int_t htype, oldhtype;
6990 Int_t i, j, first, last, nbins, fixbin;
6991 Double_t c1, yb;
6992 yb = 0;
6993
6994 strlcpy(chopth, " ",17);
6995
6998 Double_t baroffset = fH->GetBarOffset();
6999 Double_t barwidth = fH->GetBarWidth();
7000 Double_t baroffsetsave = gStyle->GetBarOffset();
7001 Double_t barwidthsave = gStyle->GetBarWidth();
7002 gStyle->SetBarOffset(baroffset);
7003 gStyle->SetBarWidth(barwidth);
7004
7005 // Create "LIFE" structure to keep current histogram status
7006
7007 first = Hparam.xfirst;
7008 last = Hparam.xlast;
7009 nbins = last - first + 1;
7010
7011 std::vector<Double_t> keepx, keepy;
7012 if (fXaxis->GetXbins()->fN) fixbin = 0;
7013 else fixbin = 1;
7014 if (fixbin) keepx.resize(2);
7015 else keepx.resize(nbins+1);
7016 keepy.resize(nbins);
7017 Double_t logymin = 0;
7018 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
7019
7020 // Loop on histogram bins
7021
7022 for (j=first; j<=last;j++) {
7024 if (TMath::Abs(ymax-ymin) > 0) {
7025 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
7026 else yb = c1;
7027 }
7028 if (!Hoption.Line) {
7029 yb = TMath::Max(yb, ymin);
7030 yb = TMath::Min(yb, ymax);
7031 }
7032 keepy[j-first] = yb;
7033 }
7034
7035 // Draw histogram according to value of FillStyle and FillColor
7036
7037 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7038 else {
7039 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7040 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7041 }
7042
7043 // Prepare Fill area (systematic with option "Bar").
7044
7045 oldhtype = fH->GetFillStyle();
7046 htype = oldhtype;
7047 if (Hoption.Bar) {
7048 if (htype == 0 || htype == 1000) htype = 1001;
7049 }
7050
7051 Width_t lw = (Width_t)fH->GetLineWidth();
7052
7053 // Code option for GrapHist
7054
7055 if (Hoption.Line) chopth[0] = 'L';
7056 if (Hoption.Star) chopth[1] = '*';
7057 if (Hoption.Mark) chopth[2] = 'P';
7058 if (Hoption.Mark == 10) chopth[3] = '0';
7060 if (Hoption.Curve) chopth[3] = 'C';
7061 if (Hoption.Hist > 0) chopth[4] = 'H';
7062 else if (Hoption.Bar) chopth[5] = 'B';
7063 if (Hoption.Logy) chopth[6] = '1';
7064 if (fH->GetFillColor() && htype) {
7065 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7066 chopth[7] = 'F';
7067 }
7068 }
7069 }
7070 if (!fixbin && strlen(chopth)) {
7071 chopth[8] = 'N';
7072 }
7073
7074 if (Hoption.Fill == 2) chopth[13] = '2';
7075
7076 // Option LOGX
7077
7078 if (Hoption.Logx) {
7079 chopth[9] = 'G';
7080 chopth[10] = 'X';
7081 if (fixbin) {
7082 keepx[0] = TMath::Power(10,keepx[0]);
7083 keepx[1] = TMath::Power(10,keepx[1]);
7084 }
7085 }
7086
7087 if (Hoption.Off) {
7088 chopth[11] = ']';
7089 chopth[12] = '[';
7090 }
7091
7092 // Draw the histogram
7093
7094 TGraph graph;
7095 graph.SetLineWidth(lw);
7096 graph.SetLineStyle(fH->GetLineStyle());
7097 graph.SetLineColor(fH->GetLineColor());
7098 graph.SetFillStyle(htype);
7099 graph.SetFillColor(fH->GetFillColor());
7101 graph.SetMarkerSize(fH->GetMarkerSize());
7104
7105 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7106
7107 gStyle->SetBarOffset(baroffsetsave);
7108 gStyle->SetBarWidth(barwidthsave);
7109
7110 htype=oldhtype;
7111}
7112
7113////////////////////////////////////////////////////////////////////////////////
7114/// [Control function to draw a 3D histograms.](\ref HP01d)
7115
7117{
7118
7119 TString cmd;
7120 TString opt = option;
7121 opt.ToLower();
7122 Int_t irep;
7123 Float_t NEntries = fH->GetEntries();
7124
7125 if (fCurrentF3 || strstr(opt,"tf3")) {
7126 PaintTF3();
7127 return;
7128 }
7129
7130 if (NEntries > 0) {
7131 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7132 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7133 PaintH3Box(1);
7134 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7135 PaintH3Box(2);
7136 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7137 PaintH3Box(3);
7138 } else {
7140 }
7141 return;
7142 }
7143
7144 if (strstr(opt,"iso")) {
7145 PaintH3Iso();
7146 return;
7147 }
7148 }
7149
7150 TView *view = gPad ? gPad->GetView() : nullptr;
7151 if (!view) return;
7152
7153 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7154 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7155
7156 Double_t thedeg = 90 - gPad->GetTheta();
7157 Double_t phideg = -90 - gPad->GetPhi();
7158 Double_t psideg = view->GetPsi();
7159 view->SetView(phideg, thedeg, psideg, irep);
7160
7161 if(NEntries > 0) { // Paint as 3D scatter plot
7162 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7163 gROOT->ProcessLine(cmd.Data());
7164 } else {
7165 TAxis* xAxis = fH->GetXaxis();
7166 TAxis* yAxis = fH->GetYaxis();
7167 TAxis* zAxis = fH->GetZaxis();
7168 Double_t xmin = xAxis->GetXmin();
7169 Double_t xmax = xAxis->GetXmax();
7170 Double_t ymin = yAxis->GetXmin();
7171 Double_t ymax = yAxis->GetXmax();
7172 Double_t zmin = zAxis->GetXmin();
7173 Double_t zmax = zAxis->GetXmax();
7174 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7175 }
7176
7177 if (Hoption.Same) return;
7178
7179 // Draw axis
7180 view->SetOutlineToCube();
7181 TSeqCollection *ol = view->GetOutline();
7182 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7184
7185 if (!Hoption.Axis && !Hoption.Same) {
7186 TGaxis axis;
7187 PaintLegoAxis(&axis, 90);
7188 }
7189
7190 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7191 // be painted with the option colz.
7192 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7193 Int_t ndiv = fH->GetContour();
7194 if (ndiv == 0 ) {
7195 ndiv = gStyle->GetNumberContours();
7196 fH->SetContour(ndiv);
7197 }
7198 PaintPalette();
7199 }
7200
7201 // Draw title
7202 PaintTitle();
7203
7204 //Draw stats and fit results
7205 TF1 *fit = nullptr;
7206 TIter next(fFunctions);
7207 while (auto obj = next()) {
7208 if (obj->InheritsFrom(TF1::Class())) {
7209 fit = (TF1*)obj;
7210 break;
7211 }
7212 }
7213 if ((Hoption.Same%10) != 1) {
7214 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7216 }
7217 }
7218
7219}
7220
7221////////////////////////////////////////////////////////////////////////////////
7222/// Compute histogram parameters used by the drawing routines.
7223
7225{
7226
7227 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7228
7229 Int_t i;
7230 static const char *where = "PaintInit";
7231 Double_t yMARGIN = gStyle->GetHistTopMargin();
7232 Int_t maximum = 0;
7233 Int_t minimum = 0;
7234 if (fH->GetMaximumStored() != -1111) maximum = 1;
7235 if (fH->GetMinimumStored() != -1111) minimum = 1;
7236
7237 // Compute X axis parameters
7238
7239 Int_t last = fXaxis->GetLast();
7240 Int_t first = fXaxis->GetFirst();
7243 Hparam.xlast = last;
7244 Hparam.xfirst = first;
7247
7248 // if log scale in X, replace xmin,max by the log
7249 if (Hoption.Logx) {
7250 if (Hparam.xmax<=0) {
7251 Error(where, "cannot set X axis to log scale");
7252 return 0;
7253 }
7254 if (Hparam.xlowedge <=0 ) {
7255 if (Hoption.Same) {
7256 TH1* h1 = nullptr;
7257 TObject *obj;
7258 TIter next(gPad->GetListOfPrimitives());
7259 while ((obj = (TObject *)next())) {
7260 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7261 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7262 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7263 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7264 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7265 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7266 }
7267 if (h1) {
7269 } else {
7270 Error(where, "undefined user's coordinates. Cannot use option SAME");
7271 return 0;
7272 }
7273 } else {
7274 for (i=first; i<=last; i++) {
7275 Double_t binLow = fXaxis->GetBinLowEdge(i);
7276 if (binLow>0) {
7277 Hparam.xlowedge = binLow;
7278 break;
7279 }
7280 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7281 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7282 break;
7283 }
7284 }
7285 if (Hparam.xlowedge<=0) {
7286 Error(where, "cannot set X axis to log scale");
7287 return 0;
7288 }
7289 }
7291 }
7296 if (Hparam.xlast > last) Hparam.xlast = last;
7297 if (Hparam.xfirst < first) Hparam.xfirst = first;
7298 }
7299
7300 // Compute Y axis parameters
7301 Double_t bigp = TMath::Power(10,32);
7302 Double_t ymax = -bigp;
7303 Double_t ymin = bigp;
7304 Double_t c1, e1;
7305 Double_t xv[1];
7306 Double_t fval;
7307 TObject *f;
7308 TF1 *f1;
7309 Double_t allchan = 0;
7310 Int_t nonNullErrors = 0;
7311 TIter next(fFunctions);
7312 for (i=first; i<=last;i++) {
7313 c1 = fH->GetBinContent(i);
7314 if (std::isnan(c1) || std::isinf(c1))
7315 continue;
7317 if (Hoption.Logy) {
7318 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7319 } else {
7321 }
7322 if (Hoption.Error) {
7324 e1 = fH->GetBinError(i);
7325 else
7326 e1 = fH->GetBinErrorUp(i);
7327 if (e1 > 0) nonNullErrors++;
7328 ymax = TMath::Max(ymax,c1+e1);
7330 e1 = fH->GetBinErrorLow(i);
7331
7332 if (Hoption.Logy) {
7333 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7334 } else {
7335 ymin = TMath::Min(ymin,c1-e1);
7336 }
7337 }
7338 if (Hoption.Func) {
7339 xv[0] = fXaxis->GetBinCenter(i);
7340 while ((f = (TObject*) next())) {
7341 if (f->IsA() == TF1::Class()) {
7342 f1 = (TF1*)f;
7343 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7344 fval = f1->Eval(xv[0],0,0);
7345 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7346 ymax = TMath::Max(ymax,fval);
7347 if (Hoption.Logy) {
7348 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7349 }
7350 }
7351 }
7352 next.Reset();
7353 }
7354 allchan += c1;
7355 }
7356 if (!nonNullErrors) {
7357 if (Hoption.Error) {
7358 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7359 Hoption.Error=0;
7360 }
7361 }
7362
7363
7364 // Take into account maximum , minimum
7365
7366 if (Hoption.Logy && ymin <= 0) {
7367 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7368 else ymin = 0.001*ymax;
7369 }
7370
7371 Double_t xm = ymin;
7372 if (maximum) ymax = fH->GetMaximumStored();
7373 if (minimum) xm = fH->GetMinimumStored();
7374 if (Hoption.Logy && xm < 0) {
7375 Error(where, "log scale requested with a negative argument (%f)", xm);
7376 return 0;
7377 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7378 ymin = 0.01;
7379 ymax = 10.;
7380 } else {
7381 ymin = xm;
7382 }
7383
7384 if (ymin >= ymax) {
7385 if (Hoption.Logy) {
7386 if (ymax > 0) ymin = 0.001*ymax;
7387 else {
7388 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7389 return 0;
7390 }
7391 }
7392 else {
7393 if (ymin > 0) {
7394 ymin = 0;
7395 ymax *= 2;
7396 } else if (ymin < 0) {
7397 ymax = 0;
7398 ymin *= 2;
7399 } else {
7400 ymin = 0;
7401 ymax = 1;
7402 }
7403 }
7404 }
7405
7406 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7407 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7408 ymin = ymin*(1-1E-14);
7409 ymax = ymax*(1+1E-14);
7410 }
7411
7412 // take into account normalization factor
7413 Hparam.allchan = allchan;
7414 Double_t factor = allchan;
7415 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7416 if (allchan) factor /= allchan;
7417 if (factor == 0) factor = 1;
7418 Hparam.factor = factor;
7419 ymax = factor*ymax;
7420 ymin = factor*ymin;
7421 //just in case the norm factor is negative
7422 // this may happen with a positive norm factor and a negative integral !
7423 if (ymax < ymin) {
7424 Double_t temp = ymax;
7425 ymax = ymin;
7426 ymin = temp;
7427 }
7428
7429 // For log scales, histogram coordinates are LOG10(ymin) and
7430 // LOG10(ymax). Final adjustment (if not option "Same"
7431 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7432 // Maximum and Minimum are not defined.
7433 if (Hoption.Logy) {
7434 if (ymin <=0 || ymax <=0) {
7435 Error(where, "Cannot set Y axis to log scale");
7436 return 0;
7437 }
7439 if (!minimum) ymin += TMath::Log10(0.5);
7441 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7442 if (!Hoption.Same) {
7443 Hparam.ymin = ymin;
7444 Hparam.ymax = ymax;
7445 }
7446 return 1;
7447 }
7448
7449 // final adjustment of ymin for linear scale.
7450 // if minimum is not set , then ymin is set to zero if >0
7451 // or to ymin - margin if <0.
7452 if (!minimum) {
7453 if (Hoption.MinimumZero) {
7454 if (ymin >= 0) ymin = 0;
7455 else ymin -= yMARGIN*(ymax-ymin);
7456 } else {
7457 Double_t dymin = yMARGIN*(ymax-ymin);
7458 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7459 else ymin -= dymin;
7460 }
7461 }
7462
7463 // final adjustment of YMAXI for linear scale (if not option "Same"):
7464 // decrease histogram height to MAX% of allowed height if HMAXIM
7465 // has not been called.
7466 if (!maximum) {
7467 ymax += yMARGIN*(ymax-ymin);
7468 }
7469
7470 Hparam.ymin = ymin;
7471 Hparam.ymax = ymax;
7472 return 1;
7473}
7474
7475////////////////////////////////////////////////////////////////////////////////
7476/// Compute histogram parameters used by the drawing routines for a rotated pad.
7477
7479{
7480
7481 static const char *where = "PaintInitH";
7482 Double_t yMARGIN = gStyle->GetHistTopMargin();
7483 Int_t maximum = 0;
7484 Int_t minimum = 0;
7485 if (fH->GetMaximumStored() != -1111) maximum = 1;
7486 if (fH->GetMinimumStored() != -1111) minimum = 1;
7487
7488 // Compute X axis parameters
7489
7490 Int_t last = fXaxis->GetLast();
7491 Int_t first = fXaxis->GetFirst();
7494 Hparam.xlast = last;
7495 Hparam.xfirst = first;
7498
7499 // if log scale in Y, replace ymin,max by the log
7500 if (Hoption.Logy) {
7501 if (Hparam.xlowedge <=0 ) {
7504 }
7505 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7506 Error(where, "cannot set Y axis to log scale");
7507 return 0;
7508 }
7513 if (Hparam.xlast > last) Hparam.xlast = last;
7514 }
7515
7516 // Compute Y axis parameters
7517 Double_t bigp = TMath::Power(10,32);
7518 Double_t xmax = -bigp;
7519 Double_t xmin = bigp;
7520 Double_t c1, e1;
7521 Double_t xv[1];
7522 Double_t fval;
7523 Int_t i;
7524 TObject *f;
7525 TF1 *f1;
7526 Double_t allchan = 0;
7527 TIter next(fFunctions);
7528 for (i=first; i<=last;i++) {
7529 c1 = fH->GetBinContent(i);
7532 if (Hoption.Error) {
7533 e1 = fH->GetBinError(i);
7534 xmax = TMath::Max(xmax,c1+e1);
7535 xmin = TMath::Min(xmin,c1-e1);
7536 }
7537 if (Hoption.Func) {
7538 xv[0] = fXaxis->GetBinCenter(i);
7539 while ((f = (TObject*) next())) {
7540 if (f->IsA() == TF1::Class()) {
7541 f1 = (TF1*)f;
7542 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7543 fval = f1->Eval(xv[0],0,0);
7544 xmax = TMath::Max(xmax,fval);
7545 if (Hoption.Logy) {
7546 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7547 }
7548 }
7549 }
7550 next.Reset();
7551 }
7552 allchan += c1;
7553 }
7554
7555 // Take into account maximum , minimum
7556
7557 if (Hoption.Logx && xmin <= 0) {
7558 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7559 else xmin = 0.001*xmax;
7560 }
7561 Double_t xm = xmin;
7562 if (maximum) xmax = fH->GetMaximumStored();
7563 if (minimum) xm = fH->GetMinimumStored();
7564 if (Hoption.Logx && xm <= 0) {
7565 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7566 return 0;
7567 }
7568 else xmin = xm;
7569 if (xmin >= xmax) {
7570 if (Hoption.Logx) {
7571 if (xmax > 0) xmin = 0.001*xmax;
7572 else {
7573 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7574 return 0;
7575 }
7576 }
7577 else {
7578 if (xmin > 0) {
7579 xmin = 0;
7580 xmax *= 2;
7581 } else if (xmin < 0) {
7582 xmax = 0;
7583 xmin *= 2;
7584 } else {
7585 xmin = 0;
7586 xmax = 1;
7587 }
7588 }
7589 }
7590
7591 // take into account normalization factor
7592 Hparam.allchan = allchan;
7593 Double_t factor = allchan;
7594 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7595 if (allchan) factor /= allchan;
7596 if (factor == 0) factor = 1;
7597 Hparam.factor = factor;
7598 xmax = factor*xmax;
7599 xmin = factor*xmin;
7600
7601 // For log scales, histogram coordinates are LOG10(ymin) and
7602 // LOG10(ymax). Final adjustment (if not option "Same"
7603 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7604 // Maximum and Minimum are not defined.
7605 if (Hoption.Logx) {
7606 if (xmin <=0 || xmax <=0) {
7607 Error(where, "Cannot set Y axis to log scale");
7608 return 0;
7609 }
7611 if (!minimum) xmin += TMath::Log10(0.5);
7613 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7614 if (!Hoption.Same) {
7615 Hparam.xmin = xmin;
7616 Hparam.xmax = xmax;
7617 }
7618 return 1;
7619 }
7620
7621 // final adjustment of ymin for linear scale.
7622 // if minimum is not set , then ymin is set to zero if >0
7623 // or to ymin - margin if <0.
7624 if (!minimum) {
7625 if (xmin >= 0) xmin = 0;
7626 else xmin -= yMARGIN*(xmax-xmin);
7627 }
7628
7629 // final adjustment of YMAXI for linear scale (if not option "Same"):
7630 // decrease histogram height to MAX% of allowed height if HMAXIM
7631 // has not been called.
7632 if (!maximum) {
7633 xmax += yMARGIN*(xmax-xmin);
7634 }
7635 Hparam.xmin = xmin;
7636 Hparam.xmax = xmax;
7637 return 1;
7638}
7639
7640////////////////////////////////////////////////////////////////////////////////
7641/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7642
7644{
7645 // Predefined box structure
7646 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7647 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7648 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7649 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7650
7651 // Define dimensions of world space
7652 TAxis *xaxis = fH->GetXaxis();
7653 TAxis *yaxis = fH->GetYaxis();
7654 TAxis *zaxis = fH->GetZaxis();
7655
7656 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7657 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7658 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7659 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7660 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7661 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7662
7663 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7664
7665 // Set view
7666 TView *view = gPad ? gPad->GetView() : nullptr;
7667 if (!view) {
7668 Error("PaintH3", "no TView in current pad");
7669 return;
7670 }
7671 Double_t thedeg = 90 - gPad->GetTheta();
7672 Double_t phideg = -90 - gPad->GetPhi();
7673 Double_t psideg = view->GetPsi();
7674 Int_t irep;
7675 view->SetView(phideg, thedeg, psideg, irep);
7676
7677 Int_t backcolor = gPad->GetFrameFillColor();
7678 view->PadRange(backcolor);
7679
7680 // Draw back surfaces of frame box
7681 fLego->InitMoveScreen(-1.1,1.1);
7682 if (Hoption.BackBox) {
7683 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7685 fLego->BackBox(90);
7686 }
7687
7689
7690 // Define order of drawing
7691 Double_t *tnorm = view->GetTnorm();
7692 if (!tnorm) return;
7693 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7694 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7695 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7696 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7697 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7698 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7699 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7700 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7701 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7702
7703 // Set graphic attributes (colour, style, etc.)
7704 Style_t fillsav = fH->GetFillStyle();
7705 Style_t colsav = fH->GetFillColor();
7706 Style_t coldark = TColor::GetColorDark(colsav);
7707 Style_t colbright = TColor::GetColorBright(colsav);
7708
7709 fH->SetFillStyle(1001);
7710 fH->TAttFill::Modify();
7711 fH->TAttLine::Modify();
7712 Int_t ncolors = gStyle->GetNumberOfColors();
7713 Int_t theColor;
7714
7715 // Create bin boxes and draw
7719
7720 Double_t pmin[3], pmax[3], sxyz[8][3];
7721 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7722 pmin[0] = xaxis->GetBinLowEdge(ix);
7723 pmax[0] = xaxis->GetBinUpEdge(ix);
7724 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7725 pmin[1] = yaxis->GetBinLowEdge(iy);
7726 pmax[1] = yaxis->GetBinUpEdge(iy);
7727 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7728 pmin[2] = zaxis->GetBinLowEdge(iz);
7729 pmax[2] = zaxis->GetBinUpEdge(iz);
7730 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7731 Bool_t neg = kFALSE;
7732 Int_t n = 5;
7733 if (w<0) {
7734 w = -w;
7735 neg = kTRUE;
7736 }
7737 if (w < wmin) continue;
7738 if (w > wmax) w = wmax;
7739 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7740 if (scale == 0) continue;
7741 for (Int_t i=0; i<3; ++i) {
7742 Double_t c = (pmax[i] + pmin[i])*0.5;
7743 Double_t d = (pmax[i] - pmin[i])*scale;
7744 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7745 sxyz[k][i] = wxyz[k][i]*d + c;
7746 }
7747 }
7748 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7749 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7750 }
7751 Double_t x[8], y[8]; // draw bin box faces
7752 for (Int_t k=0; k<6; ++k) {
7753 for (Int_t i=0; i<4; ++i) {
7754 Int_t iv = iface[k][i];
7755 x[i] = sxyz[iv][0];
7756 y[i] = sxyz[iv][1];
7757 }
7758 x[4] = x[0] ; y[4] = y[0];
7759 if (neg) {
7760 x[5] = x[2] ; y[5] = y[2];
7761 x[6] = x[3] ; y[6] = y[3];
7762 x[7] = x[1] ; y[7] = y[1];
7763 n = 8;
7764 } else {
7765 n = 5;
7766 }
7767 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7768 if (z <= 0.) continue;
7769 if (iopt == 2) {
7770 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7772 } else {
7773 if (k == 3 || k == 5) {
7774 fH->SetFillColor(coldark);
7775 } else if (k == 0 || k == 1) {
7776 fH->SetFillColor(colbright);
7777 } else {
7778 fH->SetFillColor(colsav);
7779 }
7780 }
7781 fH->TAttFill::Modify();
7782 gPad->PaintFillArea(4, x, y);
7783 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7784 }
7785 }
7786 }
7787 }
7788
7789 // Draw front surfaces of frame box
7790 if (Hoption.FrontBox) fLego->FrontBox(90);
7791
7792 // Draw axis and title
7793 if (!Hoption.Axis && !Hoption.Same) {
7794 TGaxis axis;
7795 PaintLegoAxis(&axis, 90);
7796 }
7797 PaintTitle();
7798
7799 // Draw palette. if needed.
7800 if (Hoption.Zscale) {
7801 Int_t ndiv = fH->GetContour();
7802 if (ndiv == 0 ) {
7803 ndiv = gStyle->GetNumberContours();
7804 fH->SetContour(ndiv);
7805 }
7806 PaintPalette();
7807 }
7808
7809 //Draw stats and fit results
7810 TF1 *fit = nullptr;
7811 TIter next(fFunctions);
7812 while (auto obj = next()) {
7813 if (obj->InheritsFrom(TF1::Class())) {
7814 fit = (TF1*)obj;
7815 break;
7816 }
7817 }
7818 if ((Hoption.Same%10) != 1) {
7819 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7821 }
7822 }
7823
7824 fLego.reset();
7825
7826 fH->SetFillStyle(fillsav);
7827 fH->SetFillColor(colsav);
7828 fH->TAttFill::Modify();
7829}
7830
7831////////////////////////////////////////////////////////////////////////////////
7832/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7833
7835{
7836 // Predefined box structure
7837 Double_t wxyz[8][3] = {
7838 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7839 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7840 };
7841 Int_t iface[6][4] = {
7842 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7843 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7844 };
7845 Double_t normal[6][3] = {
7846 {0,0,-1}, {0,0,1}, // Z-, Z+
7847 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7848 };
7849
7850 // Define dimensions of world space
7851 TAxis *xaxis = fH->GetXaxis();
7852 TAxis *yaxis = fH->GetYaxis();
7853 TAxis *zaxis = fH->GetZaxis();
7854
7855 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7856 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7857 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7858 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7859 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7860 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7861
7862 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7863
7864 // Set view
7865 TView *view = gPad ? gPad->GetView() : nullptr;
7866 if (!view) {
7867 Error("PaintH3", "no TView in current pad");
7868 return;
7869 }
7870 Double_t thedeg = 90 - gPad->GetTheta();
7871 Double_t phideg = -90 - gPad->GetPhi();
7872 Double_t psideg = view->GetPsi();
7873 Int_t irep;
7874 view->SetView(phideg, thedeg, psideg, irep);
7875
7876 Int_t backcolor = gPad->GetFrameFillColor();
7877 view->PadRange(backcolor);
7878
7879 // Draw front surfaces of frame box
7880 if (Hoption.FrontBox) {
7881 fLego->InitMoveScreen(-1.1,1.1);
7883 }
7884
7885 // Initialize hidden line removal algorithm "raster screen"
7886 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7887
7888 // Define order of drawing
7889 Double_t *tnorm = view->GetTnorm();
7890 if (!tnorm) return;
7891 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7892 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7893 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7894 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7895 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7896 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7897 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7898 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7899 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7900
7901 // Set line attributes (colour, style, etc.)
7902 fH->TAttLine::Modify();
7903
7904 // Create bin boxes and draw
7905 const Int_t NTMAX = 100;
7906 Double_t tt[NTMAX][2];
7910 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7911 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7912 pmin[0] = xaxis->GetBinLowEdge(ix);
7913 pmax[0] = xaxis->GetBinUpEdge(ix);
7914 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7915 pmin[1] = yaxis->GetBinLowEdge(iy);
7916 pmax[1] = yaxis->GetBinUpEdge(iy);
7917 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7918 pmin[2] = zaxis->GetBinLowEdge(iz);
7919 pmax[2] = zaxis->GetBinUpEdge(iz);
7920 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7921 Bool_t neg = kFALSE;
7922 if (w<0) {
7923 w = -w;
7924 neg = kTRUE;
7925 }
7926 if (w < wmin) continue;
7927 if (w > wmax) w = wmax;
7928 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7929 if (scale == 0) continue;
7930 for (Int_t i=0; i<3; ++i) {
7931 Double_t c = (pmax[i] + pmin[i])*0.5;
7932 Double_t d = (pmax[i] - pmin[i])*scale;
7933 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7934 sxyz[k][i] = wxyz[k][i]*d + c;
7935 }
7936 }
7937 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7938 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7939 }
7940 for (Int_t k=0; k<6; ++k) { // draw box faces
7941 Double_t zn;
7942 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7943 if (zn <= 0) continue;
7944 for (Int_t i=0; i<4; ++i) {
7945 Int_t ip = iface[k][i];
7946 pp[i][0] = sxyz[ip][0];
7947 pp[i][1] = sxyz[ip][1];
7948 }
7949 for (Int_t i=0; i<4; ++i) {
7950 Int_t i1 = i;
7951 Int_t i2 = (i == 3) ? 0 : i + 1;
7952 Int_t nt;
7953 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7954 Double_t xdel = pp[i2][0] - pp[i1][0];
7955 Double_t ydel = pp[i2][1] - pp[i1][1];
7956 Double_t x[2], y[2];
7957 for (Int_t it = 0; it < nt; ++it) {
7958 x[0] = pp[i1][0] + xdel*tt[it][0];
7959 y[0] = pp[i1][1] + ydel*tt[it][0];
7960 x[1] = pp[i1][0] + xdel*tt[it][1];
7961 y[1] = pp[i1][1] + ydel*tt[it][1];
7962 gPad->PaintPolyLine(2, x, y);
7963 }
7964 }
7965 if (neg) {
7966 Int_t i1 = 0;
7967 Int_t i2 = 2;
7968 Int_t nt;
7969 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7970 Double_t xdel = pp[i2][0] - pp[i1][0];
7971 Double_t ydel = pp[i2][1] - pp[i1][1];
7972 Double_t x[2], y[2];
7973 for (Int_t it = 0; it < nt; ++it) {
7974 x[0] = pp[i1][0] + xdel*tt[it][0];
7975 y[0] = pp[i1][1] + ydel*tt[it][0];
7976 x[1] = pp[i1][0] + xdel*tt[it][1];
7977 y[1] = pp[i1][1] + ydel*tt[it][1];
7978 gPad->PaintPolyLine(2, x, y);
7979 }
7980 i1 = 1;
7981 i2 = 3;
7982 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7983 xdel = pp[i2][0] - pp[i1][0];
7984 ydel = pp[i2][1] - pp[i1][1];
7985 for (Int_t it = 0; it < nt; ++it) {
7986 x[0] = pp[i1][0] + xdel*tt[it][0];
7987 y[0] = pp[i1][1] + ydel*tt[it][0];
7988 x[1] = pp[i1][0] + xdel*tt[it][1];
7989 y[1] = pp[i1][1] + ydel*tt[it][1];
7990 gPad->PaintPolyLine(2, x, y);
7991 }
7992 }
7993 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7994 }
7995 }
7996 }
7997 }
7998
7999 // Draw frame box
8000 if (Hoption.BackBox) {
8001 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8003 fLego->BackBox(90);
8004 }
8005
8006 if (Hoption.FrontBox) fLego->FrontBox(90);
8007
8008 // Draw axis and title
8009 if (!Hoption.Axis && !Hoption.Same) {
8010 TGaxis axis;
8011 PaintLegoAxis(&axis, 90);
8012 }
8013 PaintTitle();
8014
8015 //Draw stats and fit results
8016 TF1 *fit = nullptr;
8017 TIter next(fFunctions);
8018 while (auto obj = next()) {
8019 if (obj->InheritsFrom(TF1::Class())) {
8020 fit = (TF1*)obj;
8021 break;
8022 }
8023 }
8024 if ((Hoption.Same%10) != 1) {
8025 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8027 }
8028 }
8029
8030 fLego.reset();
8031}
8032
8033////////////////////////////////////////////////////////////////////////////////
8034/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8035
8037{
8038
8039 const Double_t ydiff = 1;
8040 const Double_t yligh1 = 10;
8041 const Double_t qa = 0.15;
8042 const Double_t qd = 0.15;
8043 const Double_t qs = 0.8;
8044 Double_t fmin, fmax;
8045 Int_t i, irep;
8046 Int_t nbcol = 28;
8047 Int_t icol1 = 201;
8048 Int_t ic1 = icol1;
8049 Int_t ic2 = ic1+nbcol;
8050 Int_t ic3 = ic2+nbcol;
8051
8052 TAxis *xaxis = fH->GetXaxis();
8053 TAxis *yaxis = fH->GetYaxis();
8054 TAxis *zaxis = fH->GetZaxis();
8055
8056 Int_t nx = fH->GetNbinsX();
8057 Int_t ny = fH->GetNbinsY();
8058 Int_t nz = fH->GetNbinsZ();
8059
8060 std::vector<Double_t> x(nx);
8061 std::vector<Double_t> y(ny);
8062 std::vector<Double_t> z(nz);
8063
8064 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8065 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8066 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8067
8068 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8069 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8070 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8071 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8072 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8073 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8074
8075 Double_t s[3];
8076 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8077 s[1] = 0.5*s[0];
8078 s[2] = 1.5*s[0];
8079
8080 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8081
8082 TView *view = gPad ? gPad->GetView() : nullptr;
8083 if (!view) {
8084 Error("PaintH3Iso", "no TView in current pad");
8085 return;
8086 }
8087 Double_t thedeg = 90 - gPad->GetTheta();
8088 Double_t phideg = -90 - gPad->GetPhi();
8089 Double_t psideg = view->GetPsi();
8090 view->SetView(phideg, thedeg, psideg, irep);
8091
8092 Int_t backcolor = gPad->GetFrameFillColor();
8093 if (Hoption.System != kCARTESIAN) backcolor = 0;
8094 view->PadRange(backcolor);
8095
8096 Double_t dcol = 0.5/Double_t(nbcol);
8097 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8098 if (!colref) {
8099 return;
8100 }
8101 Float_t r, g, b, hue, light, satur;
8102 colref->GetRGB(r,g,b);
8103 TColor::RGBtoHLS(r,g,b,hue,light,satur);
8104 TColor *acol;
8105 for (Int_t col=0;col<nbcol;col++) {
8106 acol = gROOT->GetColor(col+icol1);
8107 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8108 if (acol) acol->SetRGB(r, g, b);
8109 }
8110
8111 fLego->InitMoveScreen(-1.1,1.1);
8112
8113 if (Hoption.BackBox) {
8114 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8116 fLego->BackBox(90);
8117 }
8118
8119 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8120 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8121 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8122 fmin = ydiff*qa;
8123 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8124 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8125
8126 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8127
8128 if (Hoption.FrontBox) {
8129 fLego->InitMoveScreen(-1.1,1.1);
8131 fLego->FrontBox(90);
8132 }
8133 if (!Hoption.Axis && !Hoption.Same) {
8134 TGaxis axis;
8135 PaintLegoAxis(&axis, 90);
8136 }
8137
8138 PaintTitle();
8139
8140 //Draw stats and fit results
8141 TF1 *fit = nullptr;
8142 TIter next(fFunctions);
8143 while (auto obj = next()) {
8144 if (obj->InheritsFrom(TF1::Class())) {
8145 fit = (TF1*)obj;
8146 break;
8147 }
8148 }
8149 if ((Hoption.Same%10) != 1) {
8150 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8152 }
8153 }
8154
8155 fLego.reset();
8156}
8157
8158////////////////////////////////////////////////////////////////////////////////
8159/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8160
8162{
8163
8164 Int_t raster = 1;
8165 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8166 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8167 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8168 Double_t zmin = Hparam.zmin;
8169 Double_t zmax = Hparam.zmax;
8170 Double_t xlab1 = Hparam.xmin;
8171 Double_t xlab2 = Hparam.xmax;
8172 Double_t ylab1 = Hparam.ymin;
8173 Double_t ylab2 = Hparam.ymax;
8174 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8175 Double_t deltaz = TMath::Abs(zmin);
8176 if (deltaz == 0) deltaz = 1;
8177 if (zmin >= zmax) {
8178 zmin -= 0.5*deltaz;
8179 zmax += 0.5*deltaz;
8180 }
8181 Double_t z1c = zmin;
8182 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8183
8184 // Compute the lego limits and instantiate a lego object
8185 fXbuf[0] = -1;
8186 fYbuf[0] = 1;
8187 fXbuf[1] = -1;
8188 fYbuf[1] = 1;
8189 if (Hoption.System == kPOLAR) {
8190 fXbuf[2] = z1c;
8191 fYbuf[2] = z2c;
8192 } else if (Hoption.System == kCYLINDRICAL) {
8193 if (Hoption.Logy) {
8194 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8195 else fXbuf[2] = 0;
8196 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8197 else fYbuf[2] = 0;
8198 } else {
8199 fXbuf[2] = ylab1;
8200 fYbuf[2] = ylab2;
8201 }
8202 z1c = 0; z2c = 1;
8203 } else if (Hoption.System == kSPHERICAL) {
8204 fXbuf[2] = -1;
8205 fYbuf[2] = 1;
8206 z1c = 0; z2c = 1;
8207 } else if (Hoption.System == kRAPIDITY) {
8208 fXbuf[2] = -1/TMath::Tan(dangle);
8209 fYbuf[2] = 1/TMath::Tan(dangle);
8210 } else {
8211 fXbuf[0] = xlab1;
8212 fYbuf[0] = xlab2;
8213 fXbuf[1] = ylab1;
8214 fYbuf[1] = ylab2;
8215 fXbuf[2] = z1c;
8216 fYbuf[2] = z2c;
8217 raster = 0;
8218 }
8219
8220 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8221
8222 Int_t nids = -1;
8223 TH1 * hid = nullptr;
8224 Color_t colormain = -1, colordark = -1;
8225 Bool_t drawShadowsInLego1 = kTRUE;
8226
8227 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8228 if (Hoption.Lego == 13) {
8229 Hoption.Lego = 11;
8230 fLego->SetMesh(0);
8231 }
8232 // LEGO4 is like LEGO1 except no shadows are drawn.
8233 if (Hoption.Lego == 14) {
8234 Hoption.Lego = 11;
8235 drawShadowsInLego1 = kFALSE;
8236 }
8237
8238 // Initialize the levels on the Z axis
8239 Int_t ndiv = fH->GetContour();
8240 if (ndiv == 0 ) {
8241 ndiv = gStyle->GetNumberContours();
8242 fH->SetContour(ndiv);
8243 }
8244 Int_t ndivz = TMath::Abs(ndiv);
8245 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8246
8247 // Initialize colors
8248 if (!fStack) {
8249 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8250 } else {
8251 for (Int_t id=0;id<=fStack->GetSize();id++) {
8252 hid = (TH1*)fStack->At((id==0)?id:id-1);
8253 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8254 }
8255 }
8256
8257 if (Hoption.Lego == 11) {
8258 nids = 1;
8259 if (fStack) nids = fStack->GetSize();
8260 hid = fH;
8261 for (Int_t id=0;id<=nids;id++) {
8262 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8263 colormain = hid->GetFillColor();
8264 if (colormain == 1) colormain = 17; //avoid drawing with black
8265 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
8266 else colordark = colormain;
8267 fLego->SetColorMain(colormain,id);
8268 fLego->SetColorDark(colordark,id);
8269 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8270 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8271 }
8272 }
8273
8274 // Now ready to draw the lego plot
8275 Int_t irep = 0;
8276
8277 TView *view = gPad ? gPad->GetView() : nullptr;
8278 if (!view) {
8279 Error("PaintLego", "no TView in current pad");
8280 return;
8281 }
8282
8283 Double_t thedeg = 90 - gPad->GetTheta();
8284 Double_t phideg = -90 - gPad->GetPhi();
8285 Double_t psideg = view->GetPsi();
8286 view->SetView(phideg, thedeg, psideg, irep);
8287
8288 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8289 fLego->SetFillStyle(fH->GetFillStyle());
8290
8291 // Set color/style for back box
8292 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8293 fLego->SetFillColor(gPad->GetFrameFillColor());
8294 fLego->TAttFill::Modify();
8295
8296 Int_t backcolor = gPad->GetFrameFillColor();
8297 if (Hoption.System != kCARTESIAN) backcolor = 0;
8298 view->PadRange(backcolor);
8299
8300 fLego->SetFillStyle(fH->GetFillStyle());
8301 fLego->SetFillColor(fH->GetFillColor());
8302 fLego->TAttFill::Modify();
8303
8304 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8305
8306 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8307 else fLego->InitMoveScreen(-1.1,1.1);
8308
8309 if (Hoption.Lego == 19) {
8311 if (Hoption.BackBox) fLego->BackBox(90);
8312 if (Hoption.FrontBox) fLego->FrontBox(90);
8313 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8314 return;
8315 }
8316
8317 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8320 fLego->BackBox(90);
8321 }
8322 }
8323
8324 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8325
8326 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8328 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8329 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8330 if (Hoption.System == kPOLAR) {
8331 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8332 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8333 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8334 } else if (Hoption.System == kCYLINDRICAL) {
8335 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8336 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8337 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8338 } else if (Hoption.System == kSPHERICAL) {
8339 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8340 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8341 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8342 } else if (Hoption.System == kRAPIDITY) {
8343 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8344 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8345 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8346 } else {
8347 if (Hoption.Lego == 1) {
8349 fLego->LegoCartesian(90,nx,ny,"FB");}
8350 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8351 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8352 }
8353
8354 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8357 fLego->BackBox(90);
8358 }
8359 }
8360 if (Hoption.System == kCARTESIAN) {
8361 fLego->InitMoveScreen(-1.1,1.1);
8363 if (Hoption.FrontBox) fLego->FrontBox(90);
8364 }
8365 if (!Hoption.Axis && !Hoption.Same) {
8366 TGaxis axis;
8367 PaintLegoAxis(&axis, 90);
8368 }
8370 fLego.reset();
8371}
8372
8373////////////////////////////////////////////////////////////////////////////////
8374/// Draw the axis for legos and surface plots.
8375
8377{
8378
8379 static Double_t epsil = 0.001;
8380
8381 Double_t cosa, sina;
8382 Double_t bmin, bmax;
8383 Double_t r[24] /* was [3][8] */;
8384 Int_t ndivx, ndivy, ndivz, i;
8385 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8386 static char chopax[8], chopay[8], chopaz[8];
8387 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8388 Double_t rad;
8389
8390 TView *view = gPad ? gPad->GetView() : nullptr;
8391 if (!view) {
8392 Error("PaintLegoAxis", "no TView in current pad");
8393 return;
8394 }
8395
8396 // In polar coordinates, draw a short line going from the external circle
8397 // corresponding to r = 1 up to r = 1.1
8398 if (Hoption.System == kPOLAR) {
8399 r[0] = 1;
8400 r[1] = 0;
8401 r[2] = 0;
8402 view->WCtoNDC(r, x1);
8403 r[0] = 1.1;
8404 r[1] = 0;
8405 r[2] = 0;
8406 view->WCtoNDC(r, x2);
8407 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8408 return;
8409 }
8410
8411 if (Hoption.System != kCARTESIAN) return;
8412
8413 rad = TMath::ATan(1.) * 4. /180.;
8414 cosa = TMath::Cos(ang*rad);
8415 sina = TMath::Sin(ang*rad);
8416
8417 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8418 for (i = 1; i <= 8; ++i) {
8419 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8420 r[i*3 - 2] = av[i*3 - 2]*sina;
8421 r[i*3 - 1] = av[i*3 - 1];
8422 }
8423
8424 view->WCtoNDC(&r[ix1*3 - 3], x1);
8425 view->WCtoNDC(&r[ix2*3 - 3], x2);
8426 view->WCtoNDC(&r[iy1*3 - 3], y1);
8427 view->WCtoNDC(&r[iy2*3 - 3], y2);
8428 view->WCtoNDC(&r[iz1*3 - 3], z1);
8429 view->WCtoNDC(&r[iz2*3 - 3], z2);
8430
8431 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8432
8433 Double_t *rmin = view->GetRmin();
8434 Double_t *rmax = view->GetRmax();
8435 if (!rmin || !rmax) return;
8436
8437 // Initialize the axis options
8438 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8439 else strlcpy(chopax, "SDH=-",8);
8440 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8441 else strlcpy(chopay, "SDH=-",8);
8442 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8443 else strlcpy(chopaz, "SDH=-",8);
8444
8445 // Option LOG is required ?
8446 if (Hoption.Logx) strlcat(chopax,"G",8);
8447 if (Hoption.Logy) strlcat(chopay,"G",8);
8448 if (Hoption.Logz) strlcat(chopaz,"G",8);
8449
8450 // Initialize the number of divisions. If the
8451 // number of divisions is negative, option 'N' is required.
8452 ndivx = fXaxis->GetNdivisions();
8453 ndivy = fYaxis->GetNdivisions();
8454 ndivz = fZaxis->GetNdivisions();
8455 if (ndivx < 0) {
8456 ndivx = TMath::Abs(ndivx);
8457 strlcat(chopax, "N",8);
8458 }
8459 if (ndivy < 0) {
8460 ndivy = TMath::Abs(ndivy);
8461 strlcat(chopay, "N",8);
8462 }
8463 if (ndivz < 0) {
8464 ndivz = TMath::Abs(ndivz);
8465 strlcat(chopaz, "N",8);
8466 }
8467
8468 // Set Axis attributes.
8469 // The variable SCALE rescales the VSIZ
8470 // in order to have the same label size for all angles.
8471
8472 axis->SetLineWidth(1);
8473
8474 // X axis drawing
8475 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8478 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8479 bmin = TMath::Power(10, rmin[0]);
8480 bmax = TMath::Power(10, rmax[0]);
8481 } else {
8482 bmin = rmin[0];
8483 bmax = rmax[0];
8484 }
8485 // Option time display is required ?
8486 if (fXaxis->GetTimeDisplay()) {
8487 strlcat(chopax,"t",8);
8488 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8489 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8490 } else {
8492 }
8493 }
8494 axis->SetOption(chopax);
8495 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8496 }
8497
8498 // Y axis drawing
8499 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8502 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8503
8504 if (fH->GetDimension() < 2) {
8505 strlcpy(chopay, "V=+UN",8);
8506 ndivy = 0;
8507 }
8508 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8509 y2[0] = y1[0];
8510 }
8511 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8512 bmin = TMath::Power(10, rmin[1]);
8513 bmax = TMath::Power(10, rmax[1]);
8514 } else {
8515 bmin = rmin[1];
8516 bmax = rmax[1];
8517 }
8518 // Option time display is required ?
8519 if (fYaxis->GetTimeDisplay()) {
8520 strlcat(chopay,"t",8);
8521 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8522 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8523 } else {
8525 }
8526 }
8527 axis->SetOption(chopay);
8528 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8529 }
8530
8531 // Z axis drawing
8532 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8534 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8535 bmin = TMath::Power(10, rmin[2]);
8536 bmax = TMath::Power(10, rmax[2]);
8537 } else {
8538 bmin = rmin[2];
8539 bmax = rmax[2];
8540 }
8541 // Option time display is required ?
8542 if (fZaxis->GetTimeDisplay()) {
8543 strlcat(chopaz,"t",8);
8544 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8545 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8546 } else {
8548 }
8549 }
8550 axis->SetOption(chopaz);
8551 TString ztit = fZaxis->GetTitle();
8552 if (ztit.Index(";")>0) {
8553 ztit.Remove(ztit.Index(";"),ztit.Length());
8554 axis->SetTitle(ztit.Data());
8555 }
8556 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8557 }
8558
8559 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8560}
8561
8562////////////////////////////////////////////////////////////////////////////////
8563/// [Paint the color palette on the right side of the pad.](\ref HP22)
8564
8566{
8567 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8568 TView *view = gPad ? gPad->GetView() : nullptr;
8569 if (palette) {
8570 if (view) {
8571 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8572 fFunctions->Remove(palette);
8573 delete palette; palette = nullptr;
8574 }
8575 } else {
8576 if (palette->TestBit(TPaletteAxis::kHasView)) {
8577 fFunctions->Remove(palette);
8578 delete palette; palette = nullptr;
8579 }
8580 }
8581 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8582 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8583 }
8584
8585 if (!palette) {
8586 Double_t xup = gPad->GetUxmax();
8587 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8588 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8589 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8590 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8591 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8592 Double_t xmax = gPad->PadtoX(xup + xr);
8593 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8594 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8595 fFunctions->AddFirst(palette);
8596 palette->Paint();
8597 }
8598}
8599
8600////////////////////////////////////////////////////////////////////////////////
8601/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8602
8604{
8605
8606 fH->TAttMarker::Modify();
8607
8608 Int_t k, marker;
8609 Double_t dz, z, xk,xstep, yk, ystep;
8610 Double_t scale = 1;
8611 Bool_t ltest = kFALSE;
8612 Double_t zmax = fH->GetMaximum();
8613 Double_t zmin = fH->GetMinimum();
8614 if (zmin == 0 && zmax == 0) return;
8615 if (zmin == zmax) {
8616 zmax += 0.1*TMath::Abs(zmax);
8617 zmin -= 0.1*TMath::Abs(zmin);
8618 }
8620 if (Hoption.Logz) {
8621 if (zmin > 0) zmin = TMath::Log10(zmin);
8622 else zmin = 0;
8623 if (zmax > 0) zmax = TMath::Log10(zmax);
8624 else zmax = 0;
8625 if (zmin == 0 && zmax == 0) return;
8626 dz = zmax - zmin;
8627 scale = 100/dz;
8628 if (ncells > 10000) scale /= 5;
8629 ltest = kTRUE;
8630 } else {
8631 dz = zmax - zmin;
8632 if (dz >= kNMAX || zmax < 1) {
8633 scale = (kNMAX-1)/dz;
8634 if (ncells > 10000) scale /= 5;
8635 ltest = kTRUE;
8636 }
8637 }
8638 if (fH->GetMinimumStored() == -1111) {
8639 Double_t yMARGIN = gStyle->GetHistTopMargin();
8640 if (Hoption.MinimumZero) {
8641 if (zmin >= 0) zmin = 0;
8642 else zmin -= yMARGIN*(zmax-zmin);
8643 } else {
8644 Double_t dzmin = yMARGIN*(zmax-zmin);
8645 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8646 else zmin -= dzmin;
8647 }
8648 }
8649
8650 TString opt = option;
8651 opt.ToLower();
8652 if (opt.Contains("scat=")) {
8653 char optscat[100];
8654 strlcpy(optscat,opt.Data(),100);
8655 char *oscat = strstr(optscat,"scat=");
8656 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8657 sscanf(oscat+5,"%lg",&scale);
8658 }
8659 // use an independent instance of a random generator
8660 // instead of gRandom to avoid conflicts and
8661 // to get same random numbers when drawing the same histogram
8662 TRandom2 random;
8663 marker=0;
8664 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8665 yk = fYaxis->GetBinLowEdge(j);
8666 ystep = fYaxis->GetBinWidth(j);
8667 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8668 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8669 xk = fXaxis->GetBinLowEdge(i);
8670 xstep = fXaxis->GetBinWidth(i);
8671 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8672 z = fH->GetBinContent(bin);
8673 if (z < zmin) z = zmin;
8674 if (z > zmax) z = zmax;
8675 if (Hoption.Logz) {
8676 if (z > 0) z = TMath::Log10(z) - zmin;
8677 } else {
8678 z -= zmin;
8679 }
8680 if (z <= 0) continue;
8681 k = Int_t(z*scale);
8682 if (ltest) k++;
8683 if (k > 0) {
8684 for (Int_t loop=0; loop<k; loop++) {
8685 if (k+marker >= kNMAX) {
8686 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8687 marker=0;
8688 }
8689 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8690 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8691 if (Hoption.Logx) {
8692 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8693 else break;
8694 }
8695 if (Hoption.Logy) {
8696 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8697 else break;
8698 }
8699 if (fXbuf[marker] < gPad->GetUxmin()) break;
8700 if (fYbuf[marker] < gPad->GetUymin()) break;
8701 if (fXbuf[marker] > gPad->GetUxmax()) break;
8702 if (fYbuf[marker] > gPad->GetUymax()) break;
8703 marker++;
8704 }
8705 }
8706 }
8707 }
8708 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8709
8711}
8712
8713////////////////////////////////////////////////////////////////////////////////
8714/// Static function to paint special objects like vectors and matrices.
8715/// This function is called via `gROOT->ProcessLine` to paint these objects
8716/// without having a direct dependency of the graphics or histogramming
8717/// system.
8718
8720{
8721
8722 if (!obj) return;
8723 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8724
8725 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8726 // case TMatrixF
8727 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8728 R__TMatrixFBase->SetBit(kCanDelete);
8729 R__TMatrixFBase->Draw(option);
8730
8731 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8732 // case TMatrixD
8733 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8734 R__TMatrixDBase->SetBit(kCanDelete);
8735 R__TMatrixDBase->Draw(option);
8736
8737 } else if (obj->InheritsFrom(TVectorF::Class())) {
8738 //case TVectorF
8739 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8740 R__TVectorF->SetBit(kCanDelete);
8741 R__TVectorF->Draw(option);
8742
8743 } else if (obj->InheritsFrom(TVectorD::Class())) {
8744 //case TVectorD
8745 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8746 R__TVectorD->SetBit(kCanDelete);
8747 R__TVectorD->Draw(option);
8748 }
8749}
8750
8751////////////////////////////////////////////////////////////////////////////////
8752/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8753
8755{
8756 TString tt, tf;
8757 Int_t dofit;
8758 TPaveStats *stats = nullptr;
8759 TIter next(fFunctions);
8760 while (auto obj = next()) {
8761 if (obj->InheritsFrom(TPaveStats::Class())) {
8762 stats = (TPaveStats*)obj;
8763 break;
8764 }
8765 }
8766
8767 if (stats && dostat) {
8768 dofit = stats->GetOptFit();
8769 dostat = stats->GetOptStat();
8770 } else {
8771 dofit = gStyle->GetOptFit();
8772 }
8773 if (!dofit) fit = nullptr;
8774 if (dofit == 1) dofit = 111;
8775 if (dostat == 1) dostat = 1111;
8776 Int_t print_name = dostat%10;
8777 Int_t print_entries = (dostat/10)%10;
8778 Int_t print_mean = (dostat/100)%10;
8779 Int_t print_stddev = (dostat/1000)%10;
8780 Int_t print_under = (dostat/10000)%10;
8781 Int_t print_over = (dostat/100000)%10;
8782 Int_t print_integral= (dostat/1000000)%10;
8783 Int_t print_skew = (dostat/10000000)%10;
8784 Int_t print_kurt = (dostat/100000000)%10;
8785 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8786 print_under + print_over + print_integral +
8787 print_skew + print_kurt;
8788 Int_t print_fval = dofit%10;
8789 Int_t print_ferrors = (dofit/10)%10;
8790 Int_t print_fchi2 = (dofit/100)%10;
8791 Int_t print_fprob = (dofit/1000)%10;
8792 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8793 if (fit) {
8794 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8795 else nlinesf += fit->GetNpar();
8796 }
8797 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8798
8799 // Pavetext with statistics
8800 Bool_t done = kFALSE;
8801 if (!dostat && !fit) {
8802 if (stats) { fFunctions->Remove(stats); delete stats;}
8803 return;
8804 }
8805 Double_t statw = gStyle->GetStatW();
8806 if (fit) statw = 1.8*gStyle->GetStatW();
8807 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8808 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8809 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8810 }
8811 if (stats) {
8812 stats->Clear();
8813 done = kTRUE;
8814 } else {
8815 stats = new TPaveStats(
8816 gStyle->GetStatX()-statw,
8817 gStyle->GetStatY()-stath,
8818 gStyle->GetStatX(),
8819 gStyle->GetStatY(),"brNDC");
8820
8821 stats->SetParent(fH);
8822 stats->SetOptFit(dofit);
8823 stats->SetOptStat(dostat);
8824 stats->SetFillColor(gStyle->GetStatColor());
8825 stats->SetFillStyle(gStyle->GetStatStyle());
8827 stats->SetTextFont(gStyle->GetStatFont());
8828 if (gStyle->GetStatFont()%10 > 2)
8830 stats->SetFitFormat(gStyle->GetFitFormat());
8832 stats->SetName("stats");
8833
8835 stats->SetTextAlign(12);
8836 stats->SetBit(kCanDelete);
8837 stats->SetBit(kMustCleanup);
8838 }
8839 if (print_name) stats->AddText(fH->GetName());
8840 if (print_entries) {
8841 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8842 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8843 stats->AddText(tt.Data());
8844 }
8845 if (print_mean) {
8846 if (print_mean == 1) {
8847 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8848 tt.Form(tf.Data(),fH->GetMean(1));
8849 } else {
8850 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8851 ,"%",stats->GetStatFormat());
8852 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8853 }
8854 stats->AddText(tt.Data());
8856 if (print_mean == 1) {
8857 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8858 tt.Form(tf.Data(),fH->GetMean(2));
8859 } else {
8860 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8861 ,"%",stats->GetStatFormat());
8862 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8863 }
8864 stats->AddText(tt.Data());
8865 }
8866 }
8867 if (print_stddev) {
8868 if (print_stddev == 1) {
8869 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8870 tt.Form(tf.Data(),fH->GetStdDev(1));
8871 } else {
8872 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8873 ,"%",stats->GetStatFormat());
8874 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8875 }
8876 stats->AddText(tt.Data());
8878 if (print_stddev == 1) {
8879 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8880 tt.Form(tf.Data(),fH->GetStdDev(2));
8881 } else {
8882 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8883 ,"%",stats->GetStatFormat());
8884 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8885 }
8886 stats->AddText(tt.Data());
8887 }
8888 }
8889 if (print_under) {
8890 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8891 tt.Form(tf.Data(),fH->GetBinContent(0));
8892 stats->AddText(tt.Data());
8893 }
8894 if (print_over) {
8895 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8896 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8897 stats->AddText(tt.Data());
8898 }
8899 if (print_integral) {
8900 if (print_integral == 1) {
8901 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8902 tt.Form(tf.Data(),fH->Integral());
8903 } else {
8904 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8905 tt.Form(tf.Data(),fH->Integral("width"));
8906 }
8907 stats->AddText(tt.Data());
8908 }
8909 if (print_skew) {
8910 if (print_skew == 1) {
8911 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8912 tt.Form(tf.Data(),fH->GetSkewness(1));
8913 } else {
8914 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8915 ,"%",stats->GetStatFormat());
8916 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8917 }
8918 stats->AddText(tt.Data());
8919 }
8920 if (print_kurt) {
8921 if (print_kurt == 1) {
8922 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8923 tt.Form(tf.Data(),fH->GetKurtosis(1));
8924 } else {
8925 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8926 ,"%",stats->GetStatFormat());
8927 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8928 }
8929 stats->AddText(tt.Data());
8930 }
8931
8932 // Draw Fit parameters
8933 if (fit) {
8934 Int_t ndf = fit->GetNDF();
8935 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8936 tt.Form(tf.Data(),fit->GetChisquare());
8937 if (print_fchi2) stats->AddText(tt.Data());
8938 if (print_fprob) {
8939 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8940 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8941 stats->AddText(tt.Data());
8942 }
8943 if (print_fval || print_ferrors) {
8944 Double_t parmin,parmax;
8945 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8946 fit->GetParLimits(ipar,parmin,parmax);
8947 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8948 if (print_ferrors) {
8949 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8950 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8951 tt.Form(tf.Data(),fit->GetParameter(ipar)
8952 ,fit->GetParError(ipar));
8953 } else {
8954 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8955 tt.Form(tf.Data(),fit->GetParameter(ipar));
8956 }
8957 stats->AddText(tt.Data());
8958 }
8959 }
8960 }
8961
8962 if (!done) fFunctions->Add(stats);
8963 stats->Paint(stats->GetOption());
8964}
8965
8966////////////////////////////////////////////////////////////////////////////////
8967/// [Draw the statistics box for 2D histograms.](\ref HP07)
8968
8970{
8971
8972 if (fH->GetDimension() != 2) return;
8973 TH2 *h2 = (TH2*)fH;
8974
8975 TString tt, tf;
8976 Int_t dofit;
8977 TPaveStats *stats = nullptr;
8978 TIter next(fFunctions);
8979 while (auto obj = next()) {
8980 if (obj->InheritsFrom(TPaveStats::Class())) {
8981 stats = (TPaveStats*)obj;
8982 break;
8983 }
8984 }
8985 if (stats && dostat) {
8986 dofit = stats->GetOptFit();
8987 dostat = stats->GetOptStat();
8988 } else {
8989 dofit = gStyle->GetOptFit();
8990 }
8991 if (dostat == 1) dostat = 1111;
8992 Int_t print_name = dostat%10;
8993 Int_t print_entries = (dostat/10)%10;
8994 Int_t print_mean = (dostat/100)%10;
8995 Int_t print_stddev = (dostat/1000)%10;
8996 Int_t print_under = (dostat/10000)%10;
8997 Int_t print_over = (dostat/100000)%10;
8998 Int_t print_integral= (dostat/1000000)%10;
8999 Int_t print_skew = (dostat/10000000)%10;
9000 Int_t print_kurt = (dostat/100000000)%10;
9001 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
9002 if (print_under || print_over) nlines += 3;
9003
9004 // Pavetext with statistics
9005 if (!gStyle->GetOptFit()) fit = nullptr;
9006 Bool_t done = kFALSE;
9007 if (!dostat && !fit) {
9008 if (stats) { fFunctions->Remove(stats); delete stats;}
9009 return;
9010 }
9011 Double_t statw = gStyle->GetStatW();
9012 if (fit) statw = 1.8*gStyle->GetStatW();
9013 Double_t stath = nlines*gStyle->GetStatFontSize();
9014 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9015 stath = 0.25*nlines*gStyle->GetStatH();
9016 }
9017 if (fit) stath += gStyle->GetStatH();
9018 if (stats) {
9019 stats->Clear();
9020 done = kTRUE;
9021 } else {
9022 stats = new TPaveStats(
9023 gStyle->GetStatX()-statw,
9024 gStyle->GetStatY()-stath,
9025 gStyle->GetStatX(),
9026 gStyle->GetStatY(),"brNDC");
9027
9028 stats->SetParent(fH);
9029 stats->SetOptFit(dofit);
9030 stats->SetOptStat(dostat);
9031 stats->SetFillColor(gStyle->GetStatColor());
9032 stats->SetFillStyle(gStyle->GetStatStyle());
9034 stats->SetName("stats");
9035
9037 stats->SetTextAlign(12);
9038 stats->SetTextFont(gStyle->GetStatFont());
9039 if (gStyle->GetStatFont()%10 > 2)
9041 stats->SetFitFormat(gStyle->GetFitFormat());
9043 stats->SetBit(kCanDelete);
9044 stats->SetBit(kMustCleanup);
9045 }
9046 if (print_name) stats->AddText(h2->GetName());
9047 if (print_entries) {
9048 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9049 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9050 stats->AddText(tt.Data());
9051 }
9052 if (print_mean) {
9053 if (print_mean == 1) {
9054 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9055 tt.Form(tf.Data(),h2->GetMean(1));
9056 stats->AddText(tt.Data());
9057 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9058 tt.Form(tf.Data(),h2->GetMean(2));
9059 stats->AddText(tt.Data());
9060 } else {
9061 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9062 ,"%",stats->GetStatFormat());
9063 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9064 stats->AddText(tt.Data());
9065 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9066 ,"%",stats->GetStatFormat());
9067 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9068 stats->AddText(tt.Data());
9069 }
9070 }
9071 if (print_stddev) {
9072 if (print_stddev == 1) {
9073 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9074 tt.Form(tf.Data(),h2->GetStdDev(1));
9075 stats->AddText(tt.Data());
9076 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9077 tt.Form(tf.Data(),h2->GetStdDev(2));
9078 stats->AddText(tt.Data());
9079 } else {
9080 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9081 ,"%",stats->GetStatFormat());
9082 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9083 stats->AddText(tt.Data());
9084 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9085 ,"%",stats->GetStatFormat());
9086 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9087 stats->AddText(tt.Data());
9088 }
9089 }
9090 if (print_integral) {
9091 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9092 tt.Form(tf.Data(),fH->Integral());
9093 stats->AddText(tt.Data());
9094 }
9095 if (print_skew) {
9096 if (print_skew == 1) {
9097 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9098 tt.Form(tf.Data(),h2->GetSkewness(1));
9099 stats->AddText(tt.Data());
9100 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9101 tt.Form(tf.Data(),h2->GetSkewness(2));
9102 stats->AddText(tt.Data());
9103 } else {
9104 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9105 ,"%",stats->GetStatFormat());
9106 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9107 stats->AddText(tt.Data());
9108 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9109 ,"%",stats->GetStatFormat());
9110 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9111 stats->AddText(tt.Data());
9112 }
9113 }
9114 if (print_kurt) {
9115 if (print_kurt == 1) {
9116 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9117 tt.Form(tf.Data(),h2->GetKurtosis(1));
9118 stats->AddText(tt.Data());
9119 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9120 tt.Form(tf.Data(),h2->GetKurtosis(2));
9121 stats->AddText(tt.Data());
9122 } else {
9123 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9124 ,"%",stats->GetStatFormat());
9125 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9126 stats->AddText(tt.Data());
9127 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9128 ,"%",stats->GetStatFormat());
9129 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9130 stats->AddText(tt.Data());
9131 }
9132 }
9133 if (print_under || print_over) {
9134 //get 3*3 under/overflows for 2d hist
9135 Double_t unov[9];
9136
9137 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9138 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9139 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9140 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9141 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9142 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9143
9144 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9145 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9146 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9147 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9148 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9149 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9150 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9151 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9152 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9153
9154 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9155 stats->AddText(tt.Data());
9156 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9157 stats->AddText(tt.Data());
9158 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9159 stats->AddText(tt.Data());
9160 }
9161
9162 // Draw Fit parameters
9163 if (fit) {
9164 Int_t ndf = fit->GetNDF();
9165 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9166 stats->AddText(tt.Data());
9167 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9168 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9169 ,fit->GetParameter(ipar)
9170 ,fit->GetParError(ipar));
9171 stats->AddText(tt.Data());
9172 }
9173 }
9174
9175 if (!done) fFunctions->Add(stats);
9176 stats->Paint(stats->GetOption());
9177}
9178
9179////////////////////////////////////////////////////////////////////////////////
9180/// [Draw the statistics box for 3D histograms.](\ref HP07)
9181
9183{
9184
9185 if (fH->GetDimension() != 3) return;
9186 TH3 *h3 = (TH3*)fH;
9187
9188 TString tt, tf;
9189 Int_t dofit;
9190 TPaveStats *stats = nullptr;
9191 TIter next(fFunctions);
9192 while (auto obj = next()) {
9193 if (obj->InheritsFrom(TPaveStats::Class())) {
9194 stats = (TPaveStats*)obj;
9195 break;
9196 }
9197 }
9198 if (stats && dostat) {
9199 dofit = stats->GetOptFit();
9200 dostat = stats->GetOptStat();
9201 } else {
9202 dofit = gStyle->GetOptFit();
9203 }
9204 if (dostat == 1) dostat = 1111;
9205 Int_t print_name = dostat%10;
9206 Int_t print_entries = (dostat/10)%10;
9207 Int_t print_mean = (dostat/100)%10;
9208 Int_t print_stddev = (dostat/1000)%10;
9209 Int_t print_under = (dostat/10000)%10;
9210 Int_t print_over = (dostat/100000)%10;
9211 Int_t print_integral= (dostat/1000000)%10;
9212 Int_t print_skew = (dostat/10000000)%10;
9213 Int_t print_kurt = (dostat/100000000)%10;
9214 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
9215 if (print_under || print_over) nlines += 3;
9216
9217 // Pavetext with statistics
9218 if (!gStyle->GetOptFit()) fit = nullptr;
9219 Bool_t done = kFALSE;
9220 if (!dostat && !fit) {
9221 if (stats) { fFunctions->Remove(stats); delete stats;}
9222 return;
9223 }
9224 Double_t statw = gStyle->GetStatW();
9225 if (fit) statw = 1.8*gStyle->GetStatW();
9226 Double_t stath = nlines*gStyle->GetStatFontSize();
9227 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9228 stath = 0.25*nlines*gStyle->GetStatH();
9229 }
9230 if (fit) stath += gStyle->GetStatH();
9231 if (stats) {
9232 stats->Clear();
9233 done = kTRUE;
9234 } else {
9235 stats = new TPaveStats(
9236 gStyle->GetStatX()-statw,
9237 gStyle->GetStatY()-stath,
9238 gStyle->GetStatX(),
9239 gStyle->GetStatY(),"brNDC");
9240
9241 stats->SetParent(fH);
9242 stats->SetOptFit(dofit);
9243 stats->SetOptStat(dostat);
9244 stats->SetFillColor(gStyle->GetStatColor());
9245 stats->SetFillStyle(gStyle->GetStatStyle());
9247 stats->SetName("stats");
9248
9250 stats->SetTextAlign(12);
9251 stats->SetTextFont(gStyle->GetStatFont());
9252 stats->SetFitFormat(gStyle->GetFitFormat());
9254 stats->SetBit(kCanDelete);
9255 stats->SetBit(kMustCleanup);
9256 }
9257 if (print_name) stats->AddText(h3->GetName());
9258 if (print_entries) {
9259 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9260 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9261 stats->AddText(tt.Data());
9262 }
9263 if (print_mean) {
9264 if (print_mean == 1) {
9265 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9266 tt.Form(tf.Data(),h3->GetMean(1));
9267 stats->AddText(tt.Data());
9268 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9269 tt.Form(tf.Data(),h3->GetMean(2));
9270 stats->AddText(tt.Data());
9271 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9272 tt.Form(tf.Data(),h3->GetMean(3));
9273 stats->AddText(tt.Data());
9274 } else {
9275 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9276 ,"%",stats->GetStatFormat());
9277 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9278 stats->AddText(tt.Data());
9279 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9280 ,"%",stats->GetStatFormat());
9281 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9282 stats->AddText(tt.Data());
9283 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9284 ,"%",stats->GetStatFormat());
9285 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9286 stats->AddText(tt.Data());
9287 }
9288 }
9289 if (print_stddev) {
9290 if (print_stddev == 1) {
9291 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9292 tt.Form(tf.Data(),h3->GetStdDev(1));
9293 stats->AddText(tt.Data());
9294 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9295 tt.Form(tf.Data(),h3->GetStdDev(2));
9296 stats->AddText(tt.Data());
9297 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9298 tt.Form(tf.Data(),h3->GetStdDev(3));
9299 stats->AddText(tt.Data());
9300 } else {
9301 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9302 ,"%",stats->GetStatFormat());
9303 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9304 stats->AddText(tt.Data());
9305 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9306 ,"%",stats->GetStatFormat());
9307 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9308 stats->AddText(tt.Data());
9309 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9310 ,"%",stats->GetStatFormat());
9311 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9312 stats->AddText(tt.Data());
9313 }
9314 }
9315 if (print_integral) {
9316 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9317 stats->AddText(tt.Data());
9318 }
9319 if (print_skew) {
9320 if (print_skew == 1) {
9321 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9322 tt.Form(tf.Data(),h3->GetSkewness(1));
9323 stats->AddText(tt.Data());
9324 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9325 tt.Form(tf.Data(),h3->GetSkewness(2));
9326 stats->AddText(tt.Data());
9327 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9328 tt.Form(tf.Data(),h3->GetSkewness(3));
9329 stats->AddText(tt.Data());
9330 } else {
9331 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9332 ,"%",stats->GetStatFormat());
9333 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9334 stats->AddText(tt.Data());
9335 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9336 ,"%",stats->GetStatFormat());
9337 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9338 stats->AddText(tt.Data());
9339 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9340 ,"%",stats->GetStatFormat());
9341 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9342 stats->AddText(tt.Data());
9343 }
9344 }
9345 if (print_kurt) {
9346 if (print_kurt == 1) {
9347 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9348 tt.Form(tf.Data(),h3->GetKurtosis(1));
9349 stats->AddText(tt.Data());
9350 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9351 tt.Form(tf.Data(),h3->GetKurtosis(2));
9352 stats->AddText(tt.Data());
9353 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9354 tt.Form(tf.Data(),h3->GetKurtosis(3));
9355 stats->AddText(tt.Data());
9356 } else {
9357 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9358 ,"%",stats->GetStatFormat());
9359 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9360 stats->AddText(tt.Data());
9361 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9362 ,"%",stats->GetStatFormat());
9363 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9364 stats->AddText(tt.Data());
9365 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9366 ,"%",stats->GetStatFormat());
9367 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9368 stats->AddText(tt.Data());
9369 }
9370 }
9371 if (print_under || print_over) {
9372 // no underflow - overflow printing for a 3D histogram
9373 // one would need a 3D table
9374 }
9375
9376 // Draw Fit parameters
9377 if (fit) {
9378 Int_t ndf = fit->GetNDF();
9379 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9380 stats->AddText(tt.Data());
9381 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9382 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9383 ,fit->GetParameter(ipar)
9384 ,fit->GetParError(ipar));
9385 stats->AddText(tt.Data());
9386 }
9387 }
9388
9389 if (!done) fFunctions->Add(stats);
9390 stats->Paint(stats->GetOption());
9391}
9392
9393////////////////////////////////////////////////////////////////////////////////
9394/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9395
9397{
9398
9399 const Double_t ydiff = 1;
9400 const Double_t yligh1 = 10;
9401 const Double_t qa = 0.15;
9402 const Double_t qd = 0.15;
9403 const Double_t qs = 0.8;
9404 Double_t fmin, fmax;
9405 Int_t raster = 0;
9406 Int_t irep = 0;
9407
9408 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9411 Double_t zmin = Hparam.zmin;
9412 Double_t zmax = Hparam.zmax;
9413 Double_t xlab1 = Hparam.xmin;
9414 Double_t xlab2 = Hparam.xmax;
9415 Double_t ylab1 = Hparam.ymin;
9416 Double_t ylab2 = Hparam.ymax;
9417 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9418 Double_t deltaz = TMath::Abs(zmin);
9419 if (deltaz == 0) deltaz = 1;
9420 if (zmin >= zmax) {
9421 zmin -= 0.5*deltaz;
9422 zmax += 0.5*deltaz;
9423 }
9424 Double_t z1c = zmin;
9425 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9426 // Compute the lego limits and instantiate a lego object
9427 fXbuf[0] = -1;
9428 fYbuf[0] = 1;
9429 fXbuf[1] = -1;
9430 fYbuf[1] = 1;
9431 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9432 if (Hoption.System == kPOLAR) {
9433 fXbuf[2] = z1c;
9434 fYbuf[2] = z2c;
9435 } else if (Hoption.System == kCYLINDRICAL) {
9436 if (Hoption.Logy) {
9437 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9438 else fXbuf[2] = 0;
9439 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9440 else fYbuf[2] = 0;
9441 } else {
9442 fXbuf[2] = ylab1;
9443 fYbuf[2] = ylab2;
9444 }
9445 z1c = 0; z2c = 1;
9446 } else if (Hoption.System == kSPHERICAL) {
9447 fXbuf[2] = -1;
9448 fYbuf[2] = 1;
9449 z1c = 0; z2c = 1;
9450 } else if (Hoption.System == kRAPIDITY) {
9451 fXbuf[2] = -1/TMath::Tan(dangle);
9452 fYbuf[2] = 1/TMath::Tan(dangle);
9453 } else {
9454 fXbuf[0] = xlab1;
9455 fYbuf[0] = xlab2;
9456 fXbuf[1] = ylab1;
9457 fYbuf[1] = ylab2;
9458 fXbuf[2] = z1c;
9459 fYbuf[2] = z2c;
9460 }
9461
9462 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9463 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9464 fLego->SetFillColor(fH->GetFillColor());
9465
9466 // Initialize the levels on the Z axis
9467 Int_t ndiv = fH->GetContour();
9468 if (ndiv == 0 ) {
9469 ndiv = gStyle->GetNumberContours();
9470 fH->SetContour(ndiv);
9471 }
9472 Int_t ndivz = TMath::Abs(ndiv);
9473 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9474
9475 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9476 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9477
9478 // Close the surface in case of non cartesian coordinates.
9479
9480 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9481
9482 // Now ready to draw the surface plot
9483
9484 TView *view = gPad ? gPad->GetView() : nullptr;
9485 if (!view) {
9486 Error("PaintSurface", "no TView in current pad");
9487 return;
9488 }
9489
9490 Double_t thedeg = 90 - gPad->GetTheta();
9491 Double_t phideg = -90 - gPad->GetPhi();
9492 Double_t psideg = view->GetPsi();
9493 view->SetView(phideg, thedeg, psideg, irep);
9494
9495 // Set color/style for back box
9496 if (Hoption.Same) {
9497 fLego->SetFillStyle(0);
9498 fLego->SetFillColor(1);
9499 } else {
9500 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9501 fLego->SetFillColor(gPad->GetFrameFillColor());
9502 }
9503 fLego->TAttFill::Modify();
9504
9505 Int_t backcolor = gPad->GetFrameFillColor();
9506 if (Hoption.System != kCARTESIAN) backcolor = 0;
9507 view->PadRange(backcolor);
9508
9509 fLego->SetFillStyle(fH->GetFillStyle());
9510 fLego->SetFillColor(fH->GetFillColor());
9511 fLego->TAttFill::Modify();
9512
9513 // Draw the filled contour on top
9514 Int_t icol1 = fH->GetFillColor();
9515
9516 Int_t hoption35 = Hoption.Surf;
9517 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9518 DefineColorLevels(ndivz);
9519 Hoption.Surf = 23;
9520 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9522 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9523 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9524 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9525 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9526 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9527 Hoption.Surf = hoption35;
9528 fLego->SetMesh(1);
9529 }
9530
9531 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9532 else fLego->InitMoveScreen(-1.1,1.1);
9533
9534 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9535 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9538 fLego->BackBox(90);
9539 }
9540 }
9541
9542 // Gouraud Shading surface
9543 if (Hoption.Surf == 14) {
9544 // Set light sources
9545 fLego->LightSource(0, ydiff, 0,0,0,irep);
9546 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9547 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9548 fmin = ydiff*qa;
9549 fmax = fmin + (yligh1+0.1)*(qd+qs);
9550 Int_t nbcol = 28;
9551 icol1 = 201;
9552 Double_t dcol = 0.5/Double_t(nbcol);
9553 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9554 if (!colref) return;
9555 Float_t r,g,b,hue,light,satur;
9556 colref->GetRGB(r,g,b);
9557 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9558 TColor *acol;
9559 for (Int_t col=0;col<nbcol;col++) {
9560 acol = gROOT->GetColor(col+icol1);
9561 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9562 if (acol) acol->SetRGB(r,g,b);
9563 }
9564 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9565 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9567 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9568 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9569 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9570 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9571 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9572 } else if (Hoption.Surf == 15) {
9573 // The surface is not drawn in this case.
9574 } else {
9575 // Draw the surface
9576 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9577 DefineColorLevels(ndivz);
9578 } else {
9579 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9580 }
9581 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9582 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9583 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9584 if (Hoption.System == kPOLAR) {
9585 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9586 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9587 } else if (Hoption.System == kCYLINDRICAL) {
9588 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9589 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9590 } else if (Hoption.System == kSPHERICAL) {
9591 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9592 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9593 } else if (Hoption.System == kRAPIDITY) {
9594 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9595 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9596 } else {
9597 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9598 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9599 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9600 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9601 }
9602 }
9603
9604 // Paint the line contour on top for option SURF7
9605 if (Hoption.Surf == 17) {
9606 fLego->InitMoveScreen(-1.1,1.1);
9607 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9608 Hoption.Surf = 23;
9609 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9611 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9612 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9613 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9614 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9615 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9616 }
9617
9618 if ((!Hoption.Same) &&
9619 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9622 fLego->BackBox(90);
9623 }
9624 }
9625 if (Hoption.System == kCARTESIAN) {
9626 fLego->InitMoveScreen(-1.1,1.1);
9628 if (Hoption.FrontBox) fLego->FrontBox(90);
9629 }
9630 if (!Hoption.Axis && !Hoption.Same) {
9631 TGaxis axis;
9632 PaintLegoAxis(&axis, 90);
9633 }
9634
9636
9637 fLego.reset();
9638}
9639
9640////////////////////////////////////////////////////////////////////////////////
9641/// Control function to draw a table using Delaunay triangles.
9642
9644{
9645
9646 TGraphDelaunay2D *dt = nullptr;
9647 TGraphDelaunay *dtOld = nullptr;
9648
9649 // Check if fH contains a TGraphDelaunay2D
9650 TList *hl = fH->GetListOfFunctions();
9651 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9652 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9653 if (!dt && !dtOld) return;
9654
9655 // If needed, create a TGraph2DPainter
9656 if (!fGraph2DPainter)
9657 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9658
9659 // Define the 3D view
9660 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9661 if (Hoption.Same) {
9662 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9663 if (!viewsame) {
9664 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9665 return;
9666 }
9667 Double_t *rmin = viewsame->GetRmin();
9668 Double_t *rmax = viewsame->GetRmax();
9669 if (!rmin || !rmax) return;
9670 fXbuf[0] = rmin[0];
9671 fYbuf[0] = rmax[0];
9672 fXbuf[1] = rmin[1];
9673 fYbuf[1] = rmax[1];
9674 fXbuf[2] = rmin[2];
9675 fYbuf[2] = rmax[2];
9676 fH->SetMaximum(rmax[2]);
9677 fH->SetMinimum(rmin[2]);
9678 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9679 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9680 } else {
9681 fXbuf[0] = Hparam.xmin;
9682 fYbuf[0] = Hparam.xmax;
9683 fXbuf[1] = Hparam.ymin;
9684 fYbuf[1] = Hparam.ymax;
9685 fXbuf[2] = Hparam.zmin;
9686 fYbuf[2] = Hparam.zmax;
9687 }
9688
9689 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9690 TView *view = gPad ? gPad->GetView() : nullptr;
9691 if (!view) {
9692 Error("PaintTriangles", "no TView in current pad");
9693 return;
9694 }
9695 Double_t thedeg = 90 - gPad->GetTheta();
9696 Double_t phideg = -90 - gPad->GetPhi();
9697 Double_t psideg = view->GetPsi();
9698 Int_t irep;
9699 view->SetView(phideg, thedeg, psideg, irep);
9700
9701 // Set color/style for back box
9702 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9703 fLego->SetFillColor(gPad->GetFrameFillColor());
9704 fLego->TAttFill::Modify();
9705 Int_t backcolor = gPad->GetFrameFillColor();
9706 if (Hoption.System != kCARTESIAN) backcolor = 0;
9707 view->PadRange(backcolor);
9708 fLego->SetFillStyle(fH->GetFillStyle());
9709 fLego->SetFillColor(fH->GetFillColor());
9710 fLego->TAttFill::Modify();
9711
9712 // Paint the Back Box if needed
9713 if (Hoption.BackBox && !Hoption.Same) {
9714 fLego->InitMoveScreen(-1.1,1.1);
9715 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9717 fLego->BackBox(90);
9718 }
9719
9720 // Paint the triangles
9721 fGraph2DPainter->Paint(option);
9722
9723 // Paint the Front Box if needed
9724 if (Hoption.FrontBox) {
9725 fLego->InitMoveScreen(-1.1,1.1);
9727 fLego->FrontBox(90);
9728 }
9729
9730 // Paint the Axis if needed
9731 if (!Hoption.Axis && !Hoption.Same) {
9732 TGaxis axis;
9733 PaintLegoAxis(&axis, 90);
9734 }
9735
9737
9738 fLego.reset();
9739}
9740
9741////////////////////////////////////////////////////////////////////////////////
9742/// Define the color levels used to paint legos, surfaces etc..
9743
9745{
9746
9747 Int_t i, irep;
9748
9749 // Initialize the color levels
9750 if (ndivz >= 100) {
9751 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9752 ndivz = 99;
9753 }
9754 std::vector<Double_t> funlevel(ndivz+1);
9755 std::vector<Int_t> colorlevel(ndivz+1);
9756 Int_t theColor;
9757 Int_t ncolors = gStyle->GetNumberOfColors();
9758 for (i = 0; i < ndivz; ++i) {
9759 funlevel[i] = fH->GetContourLevelPad(i);
9760 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9761 colorlevel[i] = gStyle->GetColorPalette(theColor);
9762 }
9763 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9764 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9765}
9766
9767////////////////////////////////////////////////////////////////////////////////
9768/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9769
9771{
9772
9773 // Fill Hparam structure with histo parameters
9774 if (!TableInit()) return;
9775
9776 // Draw histogram frame
9777 PaintFrame();
9778
9779 // If palette option not specified, delete a possible existing palette
9780 if (!Hoption.Zscale) {
9781 TObject *palette = fFunctions->FindObject("palette");
9782 if (palette) { fFunctions->Remove(palette); delete palette;}
9783 }
9784
9785 // Do not draw the histogram. Only the attached functions will be drawn.
9786 if (Hoption.Func == 2) {
9787 if (Hoption.Zscale) {
9788 Int_t ndiv = fH->GetContour();
9789 if (ndiv == 0 ) {
9790 ndiv = gStyle->GetNumberContours();
9791 fH->SetContour(ndiv);
9792 }
9793 PaintPalette();
9794 }
9795
9796 // Draw the histogram according to the option
9797 } else {
9798 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9799 if (Hoption.Fill) PaintTH2PolyBins("f");
9803 if (Hoption.Line) PaintTH2PolyBins("l");
9804 if (Hoption.Mark) PaintTH2PolyBins("P");
9805 } else if (Hoption.Axis<=0) {
9809 if (Hoption.Color) {
9812 }
9815 if (Hoption.Error >= 100) Paint2DErrors(option);
9817 }
9821 }
9822
9823 // Draw histogram title
9824 PaintTitle();
9825
9826 // Draw the axes
9827 if (!Hoption.Lego && !Hoption.Surf &&
9828 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9829
9830 TF1 *fit = nullptr;
9831 TIter next(fFunctions);
9832 while (auto obj = next()) {
9833 if (obj->InheritsFrom(TF1::Class())) {
9834 fit = (TF1*)obj;
9835 break;
9836 }
9837 }
9838 if ((Hoption.Same%10) != 1) {
9839 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9840 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9841 //ALWAYS executed on non-iOS platform.
9842 //On iOS, depends on mode.
9844 }
9845 }
9846 }
9847}
9848
9849////////////////////////////////////////////////////////////////////////////////
9850/// Control function to draw a TH2Poly bins' contours.
9851///
9852/// - option = "F" draw the bins as filled areas.
9853/// - option = "L" draw the bins as line.
9854/// - option = "P" draw the bins as markers.
9855
9857{
9858
9859 //Do not highlight the histogram, if its part was picked.
9860 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9861
9862 TString opt = option;
9863 opt.ToLower();
9864 Bool_t line = kFALSE;
9865 Bool_t fill = kFALSE;
9866 Bool_t mark = kFALSE;
9867 if (opt.Contains("l")) line = kTRUE;
9868 if (opt.Contains("f")) fill = kTRUE;
9869 if (opt.Contains("p")) mark = kTRUE;
9870
9871 TH2PolyBin *b;
9872 Double_t z;
9873
9874 TIter next(((TH2Poly*)fH)->GetBins());
9875 TObject *obj, *poly;
9876
9877 while ((obj=next())) {
9878 b = (TH2PolyBin*)obj;
9879 z = b->GetContent();
9880 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9881 poly = b->GetPolygon();
9882
9883 // Paint the TGraph bins.
9884 if (poly->IsA() == TGraph::Class()) {
9885 TGraph *g = (TGraph*)poly;
9886 g->TAttLine::Modify();
9887 g->TAttMarker::Modify();
9888 g->TAttFill::Modify();
9889 if (line) {
9890 Int_t fs = g->GetFillStyle();
9891 Int_t db = gStyle->GetDrawBorder();
9892 g->SetFillStyle(0);
9894 g->Paint("F");
9895 gStyle->SetDrawBorder(db);
9896 g->SetFillStyle(fs);
9897 }
9898 if (fill) g->Paint("F");
9899 if (mark) g->Paint("P");
9900 }
9901
9902 // Paint the TMultiGraph bins.
9903 if (poly->IsA() == TMultiGraph::Class()) {
9904 TMultiGraph *mg = (TMultiGraph*)poly;
9905 TList *gl = mg->GetListOfGraphs();
9906 if (!gl) return;
9907 TGraph *g;
9908 TIter nextg(gl);
9909 while ((g = (TGraph*) nextg())) {
9910 g->TAttLine::Modify();
9911 g->TAttMarker::Modify();
9912 g->TAttFill::Modify();
9913 if (line) {
9914 Int_t fs = g->GetFillStyle();
9915 Int_t db = gStyle->GetDrawBorder();
9916 g->SetFillStyle(0);
9918 g->Paint("F");
9919 gStyle->SetDrawBorder(db);
9920 g->SetFillStyle(fs);
9921 }
9922 if (fill) g->Paint("F");
9923 if (mark) g->Paint("P");
9924 }
9925 }
9926 }
9927}
9928
9929////////////////////////////////////////////////////////////////////////////////
9930/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9931
9933{
9934
9935 //Do not highlight the histogram, if its part was picked.
9936 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9937 return;
9938
9939 Int_t ncolors, color, theColor;
9940 Double_t z, zc;
9941 Double_t zmin = fH->GetMinimum();
9942 Double_t zmax = fH->GetMaximum();
9943 if (Hoption.Logz) {
9944 if (zmax > 0) {
9945 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9946 zmin = TMath::Log10(zmin);
9947 zmax = TMath::Log10(zmax);
9948 } else {
9949 return;
9950 }
9951 }
9952 Double_t dz = zmax - zmin;
9953
9954 // Initialize the levels on the Z axis
9955 ncolors = gStyle->GetNumberOfColors();
9956 Int_t ndiv = fH->GetContour();
9957 if (ndiv == 0 ) {
9958 ndiv = gStyle->GetNumberContours();
9959 fH->SetContour(ndiv);
9960 }
9961 Int_t ndivz = TMath::Abs(ndiv);
9962 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9963 Double_t scale = ndivz/dz;
9964
9965 TIter next(((TH2Poly*)fH)->GetBins());
9966
9967 while (auto obj = next()) {
9968 TH2PolyBin *b = (TH2PolyBin*)obj;
9969 TObject *poly = b->GetPolygon();
9970
9971 z = b->GetContent();
9972 if (z==0 && Hoption.Zero) continue;
9973 if (Hoption.Logz) {
9974 if (z > 0) z = TMath::Log10(z);
9975 else z = zmin;
9976 }
9977 if (z < zmin) continue;
9978
9979 // Define the bin color.
9981 zc = fH->GetContourLevelPad(0);
9982 if (z < zc) continue;
9983 color = -1;
9984 for (Int_t k=0; k<ndiv; k++) {
9985 zc = fH->GetContourLevelPad(k);
9986 if (z < zc) {
9987 continue;
9988 } else {
9989 color++;
9990 }
9991 }
9992 } else {
9993 color = Int_t(0.01+(z-zmin)*scale);
9994 }
9995 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9996 if (theColor > ncolors-1) theColor = ncolors-1;
9997
9998 auto rootColor = gStyle->GetColorPalette(theColor);
9999
10000 // Paint the TGraph bins.
10001 if (poly->IsA() == TGraph::Class()) {
10002 TGraph *g = (TGraph*)poly;
10003 auto origin = g->GetFillColor();
10004 g->SetFillColor(rootColor);
10005 g->TAttFill::Modify();
10006 g->Paint("F");
10007 g->SetFillColor(origin);
10008 }
10009
10010 // Paint the TMultiGraph bins.
10011 if (poly->IsA() == TMultiGraph::Class()) {
10012 TMultiGraph *mg = (TMultiGraph*)poly;
10013 TIter nextg(mg->GetListOfGraphs());
10014 while (auto g = (TGraph*) nextg()) {
10015 auto origin = g->GetFillColor();
10016 g->SetFillColor(rootColor);
10017 g->TAttFill::Modify();
10018 g->Paint("F");
10019 g->SetFillColor(origin);
10020 }
10021 }
10022 }
10024}
10025
10026////////////////////////////////////////////////////////////////////////////////
10027/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
10028
10030{
10031
10032 //Do not highlight the histogram, if its part was selected.
10033 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10034 return;
10035
10036 Int_t k, loop, marker=0;
10037 Double_t z, xk,xstep, yk, ystep, xp, yp;
10038 Double_t scale = 1;
10039 Double_t zmin = fH->GetMinimum();
10040 Double_t zmax = fH->GetMaximum();
10041 if (Hoption.Logz) {
10042 if (zmax > 0) {
10043 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10044 zmin = TMath::Log10(zmin);
10045 zmax = TMath::Log10(zmax);
10046 } else {
10047 return;
10048 }
10049 }
10050 Double_t dz = zmax - zmin;
10051 scale = (kNMAX-1)/dz;
10052
10053
10054 // use an independent instance of a random generator
10055 // instead of gRandom to avoid conflicts and
10056 // to get same random numbers when drawing the same histogram
10057 TRandom2 random;
10058
10059 TH2PolyBin *b;
10060
10061 TIter next(((TH2Poly*)fH)->GetBins());
10062 TObject *obj, *poly;
10063
10064 Double_t maxarea = 0, a;
10065 while ((obj=next())) {
10066 b = (TH2PolyBin*)obj;
10067 a = b->GetArea();
10068 if (a>maxarea) maxarea = a;
10069 }
10070
10071 next.Reset();
10072
10073 while ((obj=next())) {
10074 b = (TH2PolyBin*)obj;
10075 poly = b->GetPolygon();
10076 z = b->GetContent();
10077 if (z < zmin) z = zmin;
10078 if (z > zmax) z = zmax;
10079 if (Hoption.Logz) {
10080 if (z > 0) z = TMath::Log10(z) - zmin;
10081 } else {
10082 z -= zmin;
10083 }
10084 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10085 xk = b->GetXMin();
10086 yk = b->GetYMin();
10087 xstep = b->GetXMax()-xk;
10088 ystep = b->GetYMax()-yk;
10089
10090 // Paint the TGraph bins.
10091 if (poly->IsA() == TGraph::Class()) {
10092 TGraph *g = (TGraph*)poly;
10093 if (k <= 0 || z <= 0) continue;
10094 loop = 0;
10095 while (loop<k) {
10096 if (k+marker >= kNMAX) {
10097 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10098 marker=0;
10099 }
10100 xp = (random.Rndm()*xstep) + xk;
10101 yp = (random.Rndm()*ystep) + yk;
10102 if (g->IsInside(xp,yp)) {
10103 fXbuf[marker] = xp;
10104 fYbuf[marker] = yp;
10105 marker++;
10106 loop++;
10107 }
10108 }
10109 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10110 }
10111
10112 // Paint the TMultiGraph bins.
10113 if (poly->IsA() == TMultiGraph::Class()) {
10114 TMultiGraph *mg = (TMultiGraph*)poly;
10115 TList *gl = mg->GetListOfGraphs();
10116 if (!gl) return;
10117 if (k <= 0 || z <= 0) continue;
10118 loop = 0;
10119 while (loop<k) {
10120 if (k+marker >= kNMAX) {
10121 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10122 marker=0;
10123 }
10124 xp = (random.Rndm()*xstep) + xk;
10125 yp = (random.Rndm()*ystep) + yk;
10126 if (mg->IsInside(xp,yp)) {
10127 fXbuf[marker] = xp;
10128 fYbuf[marker] = yp;
10129 marker++;
10130 loop++;
10131 }
10132 }
10133 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10134 }
10135 }
10136 PaintTH2PolyBins("l");
10137}
10138
10139////////////////////////////////////////////////////////////////////////////////
10140/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10141
10143{
10144
10145 TLatex text;
10146 text.SetTextFont(gStyle->GetTextFont());
10147 text.SetTextColor(fH->GetMarkerColor());
10148 text.SetTextSize(0.02*fH->GetMarkerSize());
10149
10150 Double_t x, y, z, e, angle = 0;
10151 TString tt, tf;
10152 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10153 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10154 Int_t opt = (Int_t)Hoption.Text/1000;
10155
10156 text.SetTextAlign(22);
10157 if (Hoption.Text == 1) angle = 0;
10158 text.SetTextAngle(angle);
10159 text.TAttText::Modify();
10160
10161 TH2PolyBin *b;
10162
10163 TIter next(((TH2Poly*)fH)->GetBins());
10164 TObject *obj, *p;
10165
10166 while ((obj=next())) {
10167 b = (TH2PolyBin*)obj;
10168 p = b->GetPolygon();
10169 x = (b->GetXMin()+b->GetXMax())/2;
10170 if (Hoption.Logx) {
10171 if (x > 0) x = TMath::Log10(x);
10172 else continue;
10173 }
10174 y = (b->GetYMin()+b->GetYMax())/2;
10175 if (Hoption.Logy) {
10176 if (y > 0) y = TMath::Log10(y);
10177 else continue;
10178 }
10179 z = b->GetContent();
10180 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10181 if (opt==2) {
10182 e = fH->GetBinError(b->GetBinNumber());
10183 tf.Form("#splitline{%s%s}{#pm %s%s}",
10185 "%",gStyle->GetPaintTextFormat());
10186 tt.Form(tf.Data(),z,e);
10187 } else {
10188 tt.Form(tf.Data(),z);
10189 }
10190 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10191 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10192 }
10193
10194 PaintTH2PolyBins("l");
10195}
10196
10197////////////////////////////////////////////////////////////////////////////////
10198/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10199
10201{
10202
10203 TLatex text;
10204 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10205 text.SetTextColor(fH->GetMarkerColor());
10206 text.SetTextSize(0.02*fH->GetMarkerSize());
10207
10208 Double_t x, y, z, e, angle = 0;
10209 TString tt, tf;
10210 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10211 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10212
10213 // 1D histograms
10214 if (fH->GetDimension() == 1) {
10215 Bool_t getentries = kFALSE;
10216 Double_t yt;
10217 TProfile *hp = (TProfile*)fH;
10218 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10219 Hoption.Text = Hoption.Text-2000;
10220 getentries = kTRUE;
10221 }
10222 if (Hoption.Text == 1) angle = 90;
10223 text.SetTextAlign(11);
10224 if (angle == 90) text.SetTextAlign(12);
10225 if (angle == 0) text.SetTextAlign(21);
10226 text.TAttText::Modify();
10227 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10228 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10229 if (Hoption.Bar) {
10230 x = fH->GetXaxis()->GetBinLowEdge(i)+
10231 fH->GetXaxis()->GetBinWidth(i)*
10232 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10233 } else {
10234 x = fH->GetXaxis()->GetBinCenter(i);
10235 }
10236 y = fH->GetBinContent(i);
10237 yt = y;
10238 if (Hoption.MinimumZero && y<0) y = 0;
10239 if (getentries) yt = hp->GetBinEntries(i);
10240 if (yt == 0.) continue;
10241 tt.Form(tf.Data(),yt);
10242 if (Hoption.Logx) {
10243 if (x > 0) x = TMath::Log10(x);
10244 else continue;
10245 }
10246 if (Hoption.Logy) {
10247 if (y > 0) y = TMath::Log10(y);
10248 else continue;
10249 }
10250 if (y >= gPad->GetY2()) continue;
10251 if (y <= gPad->GetY1()) continue;
10252 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10253 }
10254
10255 // 2D histograms
10256 } else {
10257 Double_t zmin = Hparam.zmin;
10258 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10259
10260 text.SetTextAlign(22);
10261 if (Hoption.Text == 1) angle = 0;
10262 text.SetTextAngle(angle);
10263 text.TAttText::Modify();
10264 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10265 y = fYaxis->GetBinCenter(j);
10266 if (Hoption.Logy) {
10267 if (y > 0) y = TMath::Log10(y);
10268 else continue;
10269 }
10270 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10271 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10272 x = fXaxis->GetBinCenter(i);
10273 if (Hoption.Logx) {
10274 if (x > 0) x = TMath::Log10(x);
10275 else continue;
10276 }
10277 if (!IsInside(x,y)) continue;
10278 z = fH->GetBinContent(bin);
10279 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10280 if (Hoption.Text>2000) {
10281 e = fH->GetBinError(bin);
10282 tf.Form("#splitline{%s%s}{#pm %s%s}",
10284 "%",gStyle->GetPaintTextFormat());
10285 tt.Form(tf.Data(),z,e);
10286 } else {
10287 tt.Form(tf.Data(),z);
10288 }
10289 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10290 angle,0.02*fH->GetMarkerSize(),tt.Data());
10291 }
10292 }
10293 }
10294}
10295
10296////////////////////////////////////////////////////////////////////////////////
10297/// [Control function to draw a 3D implicit functions.](\ref HP27)
10298
10300{
10301
10302 Int_t irep;
10303
10304 TAxis *xaxis = fH->GetXaxis();
10305 TAxis *yaxis = fH->GetYaxis();
10306 TAxis *zaxis = fH->GetZaxis();
10307
10308 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10309 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10310 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10311 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10312 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10313 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10314
10315 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10316
10317 TView *view = gPad ? gPad->GetView() : nullptr;
10318 if (!view) {
10319 Error("PaintTF3", "no TView in current pad");
10320 return;
10321 }
10322 Double_t thedeg = 90 - gPad->GetTheta();
10323 Double_t phideg = -90 - gPad->GetPhi();
10324 Double_t psideg = view->GetPsi();
10325 view->SetView(phideg, thedeg, psideg, irep);
10326
10327 fLego->InitMoveScreen(-1.1,1.1);
10328
10329 if (Hoption.BackBox) {
10330 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10332 fLego->BackBox(90);
10333 }
10334
10336
10337 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10338 fH->GetNbinsY(),
10339 fH->GetNbinsZ(), "BF");
10340
10341 if (Hoption.FrontBox) {
10342 fLego->InitMoveScreen(-1.1,1.1);
10344 fLego->FrontBox(90);
10345 }
10346 if (!Hoption.Axis && !Hoption.Same) {
10347 TGaxis axis;
10348 PaintLegoAxis(&axis, 90);
10349 }
10350
10351 PaintTitle();
10352
10353 fLego.reset();
10354}
10355
10356/////////////////////////////////////////////////////////////new TGaxis///////////////////
10357/// Draw the histogram title
10358///
10359/// The title is drawn according to the title alignment returned by
10360/// `GetTitleAlign()`. It is a 2 digits integer): hv
10361///
10362/// where `h` is the horizontal alignment and `v` is the
10363/// vertical alignment.
10364///
10365/// - `h` can get the values 1 2 3 for left, center, and right
10366/// - `v` can get the values 1 2 3 for bottom, middle and top
10367///
10368/// for instance the default alignment is: 13 (left top)
10369
10371{
10372 // probably best place for calls PaintHighlightBin
10373 // calls after paint histo (1D or 2D) and before paint title and stats
10374 if (!gPad->GetView()) PaintHighlightBin();
10375
10376 if (Hoption.Same) return;
10377 if (fH->TestBit(TH1::kNoTitle)) return;
10378 Int_t nt = strlen(fH->GetTitle());
10379 TPaveText *title = nullptr;
10380 TObject *obj;
10381 TIter next(gPad->GetListOfPrimitives());
10382 while ((obj = next())) {
10383 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10384 title = (TPaveText*)obj;
10385 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10386 break;
10387 }
10388 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10389 if (title) delete title;
10390 return;
10391 }
10392 Double_t ht = gStyle->GetTitleH();
10393 Double_t wt = gStyle->GetTitleW();
10394
10395 if (ht <= 0) {
10396 if (gStyle->GetTitleFont("")%10 == 3) {
10397 Double_t hw = (Double_t) TMath::Max(gPad->GetPadWidth(), gPad->GetPadHeight());
10398 if (hw > 0)
10399 ht = 1.1 * (gStyle->GetTitleSize("")/hw);
10400 } else {
10401 ht = 1.1*gStyle->GetTitleFontSize();
10402 }
10403 }
10404 if (ht <= 0) ht = 0.05;
10405 if (wt <= 0) {
10406 TLatex l;
10407 l.SetTextSize(ht);
10408 l.SetTitle(fH->GetTitle());
10409 // adjustment in case the title has several lines (#splitline)
10410 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10411 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10412 wt = TMath::Min(0.7, 0.02+wndc);
10413 }
10414 if (title) {
10415 TText *t0 = (TText*)title->GetLine(0);
10416 if (t0) {
10417 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10418 t0->SetTitle(fH->GetTitle());
10419 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10420 }
10421 return;
10422 }
10423
10424 Int_t talh = gStyle->GetTitleAlign()/10;
10425 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10426 Int_t talv = gStyle->GetTitleAlign()%10;
10427 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10429 xpos = gStyle->GetTitleX();
10430 ypos = gStyle->GetTitleY();
10431 if (talh == 2) xpos = xpos-wt/2.;
10432 if (talh == 3) xpos = xpos-wt;
10433 if (talv == 2) ypos = ypos+ht/2.;
10434 if (talv == 1) ypos = ypos+ht;
10435
10436 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10437
10438 // box with the histogram title
10440 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10441 ptitle->SetName("title");
10444 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10445 if (gStyle->GetTitleFont("")%10 > 2)
10447 ptitle->AddText(fH->GetTitle());
10448 ptitle->SetBit(kCanDelete);
10449 ptitle->Draw();
10450 ptitle->Paint("blNDC");
10451
10452 if(!gPad->IsEditable()) delete ptitle;
10453}
10454
10455////////////////////////////////////////////////////////////////////////////////
10456/// Process message `mess`.
10457
10458void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10459{
10460 if (!strcmp(mess,"SetF3")) {
10461 fCurrentF3 = (TF3 *)obj;
10462 }
10463}
10464
10465////////////////////////////////////////////////////////////////////////////////
10466/// Static function.
10467///
10468/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10469/// This procedure can be used to create an all-sky map in Galactic
10470/// coordinates with an equal-area Aitoff projection. Output map
10471/// coordinates are zero longitude centered.
10472/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10473///
10474/// source: GMT
10475///
10476/// code from Ernst-Jan Buis
10477
10479{
10480
10481 Double_t x, y;
10482
10483 Double_t alpha2 = (l/2)*TMath::DegToRad();
10484 Double_t delta = b*TMath::DegToRad();
10485 Double_t r2 = TMath::Sqrt(2.);
10486 Double_t f = 2*r2/TMath::Pi();
10487 Double_t cdec = TMath::Cos(delta);
10488 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10489 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10490 y = TMath::Sin(delta)*r2/denom;
10491 x *= TMath::RadToDeg()/f;
10492 y *= TMath::RadToDeg()/f;
10493 // x *= -1.; // for a skymap swap left<->right
10494 Al = x;
10495 Ab = y;
10496
10497 return 0;
10498}
10499
10500////////////////////////////////////////////////////////////////////////////////
10501/// Static function
10502///
10503/// Probably the most famous of the various map projections, the Mercator projection
10504/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10505/// with no distortion along the equator.
10506/// The Mercator projection has been used extensively for world maps in which the distortion towards
10507/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10508/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10509/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10510/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10511/// code from Ernst-Jan Buis
10512
10514{
10515
10516 Al = l;
10518 Ab = TMath::Log(aid);
10519 return 0;
10520}
10521
10522////////////////////////////////////////////////////////////////////////////////
10523/// Static function code for sinusoidal projection
10524/// from Ernst-Jan Buis
10525/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10526
10528{
10529
10530 Al = l*cos(b*TMath::DegToRad());
10531 Ab = b;
10532 return 0;
10533}
10534
10535////////////////////////////////////////////////////////////////////////////////
10536/// Static function code for parabolic projection
10537/// from Ernst-Jan Buis
10538
10540{
10541
10542 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10543 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10544 return 0;
10545}
10546
10547////////////////////////////////////////////////////////////////////////////////
10548/// Static function.
10549///
10550/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10551/// This procedure can be used to create an all-sky map in Galactic
10552/// coordinates with an equal-area Mollweide projection. Output map
10553/// coordinates are zero longitude centered.
10554/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10555/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10556///
10557/// code from Marco Meyer-Conde
10558
10560{
10561
10562 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10563
10564 for (int i = 0; i < 100; i++) {
10565 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10566 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10567
10568 if (den < 1e-20) {
10569 theta = theta0;
10570 break;
10571 }
10572
10573 theta -= num / den;
10574
10575 if (TMath::Abs(num / den) < 1e-4) break;
10576 }
10577
10578 Al = l * TMath::Cos(theta);
10579 Ab = 90 * TMath::Sin(theta);
10580
10581 return 0;
10582}
10583
10584////////////////////////////////////////////////////////////////////////////////
10585/// Recompute the histogram range following graphics operations.
10586
10588{
10589
10590 if (Hoption.Same) return;
10591
10592 // Compute x,y range
10594 xmax = Hparam.xmax,
10595 ymin = Hparam.ymin,
10596 ymax = Hparam.ymax,
10597 xscale = 1;
10598
10599 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10600
10601 if (Hoption.Proj == 1) {
10602 func = ProjectAitoff2xy;
10603 xscale = 0.9999;
10604 } else if (Hoption.Proj == 2) {
10605 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10606 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10607 Hoption.Proj = 0;
10608 } else {
10611 }
10612 } else if (Hoption.Proj == 3) {
10613 func = ProjectSinusoidal2xy;
10614 } else if (Hoption.Proj == 4) {
10615 func = ProjectParabolic2xy;
10616 } else if (Hoption.Proj == 5) {
10617 func = ProjectMollweide2xy;
10618 }
10619
10620 if (func) {
10621 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10622
10623 func(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10624 func(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10625 func(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10626 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10627
10628 if (xmin > xmin_aid) xmin = xmin_aid;
10629 if (ymin > ymin_aid) ymin = ymin_aid;
10630 if (xmax < xmax_aid) xmax = xmax_aid;
10631 if (ymax < ymax_aid) ymax = ymax_aid;
10632 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10633 // there is an 'equator', check its range in the plot..
10634 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10635 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10636 if (xmin > xmin_aid) xmin = xmin_aid;
10637 if (xmax < xmax_aid) xmax = xmax_aid;
10638 }
10639 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10640 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10641 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10642 if (ymin > ymin_aid) ymin = ymin_aid;
10643 if (ymax < ymax_aid) ymax = ymax_aid;
10644 }
10645 }
10646
10647 Hparam.xmin = xmin;
10648 Hparam.xmax = xmax;
10649 Hparam.ymin = ymin;
10650 Hparam.ymax = ymax;
10651
10652 Double_t dx = xmax-xmin;
10653 Double_t dy = ymax-ymin;
10654 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10655 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10656
10657 // Range() could change the size of the pad pixmap and therefore should
10658 // be called before the other paint routines
10659 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10660 ymin - dyr*gPad->GetBottomMargin(),
10661 xmax + dxr*gPad->GetRightMargin(),
10662 ymax + dyr*gPad->GetTopMargin());
10663 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10664}
10665
10666////////////////////////////////////////////////////////////////////////////////
10667/// Set current histogram to `h`
10668
10670{
10671
10672 if (h == nullptr) return;
10673 fH = h;
10674 fXaxis = h->GetXaxis();
10675 fYaxis = h->GetYaxis();
10676 fZaxis = h->GetZaxis();
10678}
10679
10680////////////////////////////////////////////////////////////////////////////////
10681/// Initialize various options to draw 2D histograms.
10682
10684{
10685
10686 static const char *where = "TableInit";
10687
10688 Int_t first, last;
10689 Double_t yMARGIN= gStyle->GetHistTopMargin();
10690 Double_t zmin, zmax;
10691 Int_t maximum = 0;
10692 Int_t minimum = 0;
10693 if (fH->GetMaximumStored() != -1111) maximum = 1;
10694 if (fH->GetMinimumStored() != -1111) minimum = 1;
10695
10696 // ----------------- Compute X axis parameters
10697 first = fXaxis->GetFirst();
10698 last = fXaxis->GetLast();
10699 Hparam.xlast = last;
10700 Hparam.xfirst = first;
10705
10706 // if log scale in X, replace xmin,max by the log
10707 if (Hoption.Logx) {
10708 // find the first edge of a bin that is > 0
10709 if (Hparam.xlowedge <=0 ) {
10712 }
10713 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10714 Error(where, "cannot set X axis to log scale");
10715 return 0;
10716 }
10718 if (Hparam.xfirst < first) Hparam.xfirst = first;
10720 if (Hparam.xlast > last) Hparam.xlast = last;
10723 }
10724
10725 // ----------------- Compute Y axis parameters
10726 first = fYaxis->GetFirst();
10727 last = fYaxis->GetLast();
10728 Hparam.ylast = last;
10729 Hparam.yfirst = first;
10732 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10735
10736 // if log scale in Y, replace ymin,max by the log
10737 if (Hoption.Logy) {
10738 if (Hparam.ylowedge <=0 ) {
10741 }
10742 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10743 Error(where, "cannot set Y axis to log scale");
10744 return 0;
10745 }
10747 if (Hparam.yfirst < first) Hparam.yfirst = first;
10749 if (Hparam.ylast > last) Hparam.ylast = last;
10752 }
10753
10754
10755 // ----------------- Compute Z axis parameters
10756 Double_t bigp = TMath::Power(10,32);
10757 zmax = -bigp;
10758 zmin = bigp;
10759 Double_t c1, e1;
10760 Double_t allchan = 0;
10761 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10762 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10763 c1 = fH->GetBinContent(i,j);
10764 zmax = TMath::Max(zmax,c1);
10765 if (Hoption.Error) {
10766 e1 = fH->GetBinError(i,j);
10767 zmax = TMath::Max(zmax,c1+e1);
10768 }
10769 zmin = TMath::Min(zmin,c1);
10770 allchan += c1;
10771 }
10772 }
10773
10774 // Take into account maximum , minimum
10775
10776 if (maximum) zmax = fH->GetMaximumStored();
10777 if (minimum) zmin = fH->GetMinimumStored();
10778 if (Hoption.Logz && zmax < 0) {
10779 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10780 return 0;
10781 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10782 zmin = 0.01;
10783 zmax = 10.;
10784 }
10785 if (zmin >= zmax) {
10786 if (Hoption.Logz) {
10787 if (zmax > 0) zmin = 0.001*zmax;
10788 else {
10789 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10790 return 0;
10791 }
10792 }
10793 }
10794
10795 // take into account normalization factor
10796 Hparam.allchan = allchan;
10797 Double_t factor = allchan;
10798 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10799 if (allchan) factor /= allchan;
10800 if (factor == 0) factor = 1;
10801 Hparam.factor = factor;
10802 zmax = factor*zmax;
10803 zmin = factor*zmin;
10804 c1 = zmax;
10805 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10806
10807 // For log scales, histogram coordinates are log10(ymin) and
10808 // log10(ymax). Final adjustment (if not option "Same")
10809 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10810 // Maximum and Minimum are not defined.
10811 if (Hoption.Logz) {
10812 if (zmin <= 0) {
10813 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10814 fH->SetMinimum(zmin);
10815 }
10816 zmin = TMath::Log10(zmin);
10817 if (!minimum) zmin += TMath::Log10(0.5);
10818 zmax = TMath::Log10(zmax);
10819 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10820 goto LZMIN;
10821 }
10822
10823 // final adjustment of YMAXI for linear scale (if not option "Same"):
10824 // decrease histogram height to MAX% of allowed height if HMAXIM
10825 // has not been called.
10826 // MAX% is the value in percent which has been set in HPLSET
10827 // (default is 90%).
10828 if (!maximum) {
10829 zmax += yMARGIN*(zmax-zmin);
10830 }
10831
10832 // final adjustment of ymin for linear scale.
10833 // if minimum is not set , then ymin is set to zero if >0
10834 // or to ymin - yMARGIN if <0.
10835 if (!minimum) {
10836 if (Hoption.MinimumZero) {
10837 if (zmin >= 0) zmin = 0;
10838 else zmin -= yMARGIN*(zmax-zmin);
10839 } else {
10840 Double_t dzmin = yMARGIN*(zmax-zmin);
10841 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10842 else zmin -= dzmin;
10843 }
10844 }
10845
10846LZMIN:
10847 Hparam.zmin = zmin;
10848 Hparam.zmax = zmax;
10849
10850 // Set bar offset and width
10853
10854 return 1;
10855}
10856
10857////////////////////////////////////////////////////////////////////////////////
10858/// This function returns the best format to print the error value (e)
10859/// knowing the parameter value (v) and the format (f) used to print it.
10860
10862{
10863
10864 static TString ef;
10865 TString tf, tv;
10866
10867 // print v with the format f in tv.
10868 tf.Form("%s%s","%",f);
10869 tv.Form(tf.Data(),v);
10870
10871 // Analyse tv.
10872 int ie = tv.Index("e");
10873 int iE = tv.Index("E");
10874 int id = tv.Index(".");
10875
10876 // v has been printed with the exponent notation.
10877 // There is 2 cases, the exponent is positive or negative
10878 if (ie >= 0 || iE >= 0) {
10879 if (tv.Index("+") >= 0) {
10880 if (e < 1) {
10881 ef.Form("%s.1f","%");
10882 } else {
10883 if (ie >= 0) {
10884 ef.Form("%s.%de","%",ie-id-1);
10885 } else {
10886 ef.Form("%s.%dE","%",iE-id-1);
10887 }
10888 }
10889 } else {
10890 if (ie >= 0) {
10891 ef.Form("%s.%de","%",ie-id-1);
10892 } else {
10893 ef.Form("%s.%dE","%",iE-id-1);
10894 }
10895 }
10896
10897 // There is not '.' in tv. e will be printed with one decimal digit.
10898 } else if (id < 0) {
10899 ef.Form("%s.1f","%");
10900
10901 // There is a '.' in tv and no exponent notation. e's decimal part will
10902 // have the same number of digits as v's one.
10903 } else {
10904 ef.Form("%s.%df","%",tv.Length()-id-1);
10905 }
10906
10907 return ef.Data();
10908}
10909
10910
10911////////////////////////////////////////////////////////////////////////////////
10912/// Return projection kind from option string
10913
10915{
10916 TString opt = option;
10917 opt.ToLower();
10918 Int_t projection = 0;
10919 if (opt.BeginsWith("xy"))
10920 projection = 4;
10921 else if (opt.BeginsWith("yx"))
10922 projection = 5;
10923 else if (opt.BeginsWith("xz"))
10924 projection = 6;
10925 else if (opt.BeginsWith("zx"))
10926 projection = 7;
10927 else if (opt.BeginsWith("yz"))
10928 projection = 8;
10929 else if (opt.BeginsWith("zy"))
10930 projection = 9;
10931 else if (opt.BeginsWith("x"))
10932 projection = 1;
10933 else if (opt.BeginsWith("y"))
10934 projection = 2;
10935 else if (opt.BeginsWith("z"))
10936 projection = 3;
10937 return projection;
10938}
10939
10940
10941////////////////////////////////////////////////////////////////////////////////
10942/// Set projection.
10943
10945{
10946 if (fShowProjection2) {
10947 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10948 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10949 if (c2) c2->Close();
10950 fShowProjection2 = 0;
10951 }
10952 if (fShowProjection) {
10953 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10954 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10955 if (c1) c1->Close();
10956 fShowProjection = 0;
10957 }
10958
10959 if (nbins <= 0)
10960 return;
10961
10962 if ((fH->GetDimension() == 3) && (gPad->GetGLDevice() != -1)) {
10963 Error("SetShowProjection", "TH3 projections do not work in GL mode");
10964 return;
10965 }
10966
10967 Int_t projection = DetectProjectionKind(option);
10968 if (projection == 0)
10969 return;
10970
10971 // exclude x or xy from option, rest use as histogram draw option
10972 fShowOption = option + (projection < 4 ? 1 : 2);
10973 fShowProjection = projection + 100 * nbins;
10974 fShowProjection2 = 0;
10975
10976 gROOT->MakeDefCanvas();
10977 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10978 gPad->SetGrid();
10979}
10980
10981////////////////////////////////////////////////////////////////////////////////
10982/// Set projection XY.
10983
10984void THistPainter::SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX)
10985{
10986 if (fShowProjection2) {
10987 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10988 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10989 if (c2) c2->Close();
10990 fShowProjection2 = 0;
10991 }
10992 if (fShowProjection) {
10993 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10994 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10995 if (c1) c1->Close();
10996 fShowProjection = 0;
10997 }
10998
10999 if ((nbinsX <= 0) || (nbinsY <= 0))
11000 return;
11001
11002 if ((fH->GetDimension() == 3) && (gPad->GetGLDevice() != -1)) {
11003 Error("SetShowProjectionXY", "TH3 projections do not work in GL mode");
11004 return;
11005 }
11006
11007 Int_t projection = DetectProjectionKind(option);
11008 if (projection == 0)
11009 return;
11010
11011 // exclude x or xy from option, rest use as histogram draw option
11012 fShowOption = option + (projection < 4 ? 1 : 2);
11013 fShowProjection = projection + 100*nbinsY;
11014 fShowProjection2 = projection + 100*nbinsX;
11015
11016 gROOT->MakeDefCanvas();
11017 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
11018 gPad->SetGrid();
11019 gROOT->MakeDefCanvas();
11020 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
11021 gPad->SetGrid();
11022}
11023
11024
11025////////////////////////////////////////////////////////////////////////////////
11026/// Show projection onto X.
11027
11029{
11030 if (!gPad)
11031 return;
11032
11033 Int_t nbins = (Int_t)fShowProjection/100;
11034
11035 // Erase old position and draw a line at current position
11036 Double_t uxmin = gPad->GetUxmin();
11037 Double_t uxmax = gPad->GetUxmax();
11038 Float_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
11039 Int_t biny1 = fH->GetYaxis()->FindBin(y);
11040 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
11041 Double_t py1 = gPad->YtoPad(fH->GetYaxis()->GetBinLowEdge(biny1));
11042 Double_t py2 = gPad->YtoPad(fH->GetYaxis()->GetBinUpEdge(biny2));
11043
11044 gPad->PaintBox(uxmin,py1,uxmax,py2,"iprojX");
11045 gPad->UpdateAsync();
11046
11047 // Create or set the new canvas proj x
11048 TVirtualPad::TContext ctxt(true);
11049 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11050 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
11051 if (!c) {
11053 return;
11054 }
11055
11056 c->Clear();
11057 c->cd();
11058 c->SetLogy(ctxt.GetSaved()->GetLogz());
11059 c->SetLogx(ctxt.GetSaved()->GetLogx());
11060
11061 // Draw slice corresponding to mouse position
11062 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11063 if (auto hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2)) {
11064 hp->SetFillColor(38);
11065 // apply a patch from Oliver Freyermuth to set the title in the projection
11066 // using the range of the projected Y values
11067 if (biny1 == biny2) {
11068 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
11069 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
11070 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11071 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
11072 if (fH->GetYaxis()->GetLabels() != nullptr) {
11073 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11074 } else {
11075 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11076 }
11077 } else {
11078 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
11079 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
11080 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11081 // biny1 is used here to get equal precision no matter how large the binrange is,
11082 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11083 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
11084 if (fH->GetYaxis()->GetLabels() != nullptr) {
11085 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf] [%s..%s]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1), fH->GetYaxis()->GetBinLabel(biny2)));
11086 } else {
11087 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11088 }
11089 }
11090 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11091 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11092 c->Add(hp, fShowOption);
11093 c->UpdateAsync();
11094 }
11095}
11096
11097////////////////////////////////////////////////////////////////////////////////
11098/// Show projection onto Y.
11099
11101{
11102 if (!gPad)
11103 return;
11104
11105 Int_t nbins = (Int_t)fShowProjection/100;
11106 if (fShowProjection2)
11107 nbins = (Int_t)fShowProjection2/100;
11108
11109 Double_t uymin = gPad->GetUymin();
11110 Double_t uymax = gPad->GetUymax();
11111 Float_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
11112 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11113 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
11114 Double_t px1 = gPad->XtoPad(fH->GetXaxis()->GetBinLowEdge(binx1));
11115 Double_t px2 = gPad->XtoPad(fH->GetXaxis()->GetBinUpEdge(binx2));
11116
11117 gPad->PaintBox(px1, uymin, px2, uymax, "iprojY");
11118 gPad->UpdateAsync();
11119
11120 // Create or set the new canvas proj y
11121 TVirtualPad::TContext ctxt(true);
11122
11123 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11124 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11125
11126 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
11127 if (!c) {
11129 return;
11130 }
11131
11132 c->Clear();
11133 c->cd();
11134 c->SetLogy(ctxt.GetSaved()->GetLogz());
11135 c->SetLogx(ctxt.GetSaved()->GetLogy());
11136
11137 // Draw slice corresponding to mouse position
11138 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11139 if (auto hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2)) {
11140 hp->SetFillColor(38);
11141 // apply a patch from Oliver Freyermuth to set the title in the projection
11142 // using the range of the projected X values
11143 if (binx1 == binx2) {
11144 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
11145 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
11146 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11147 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
11148 if (fH->GetXaxis()->GetLabels()) {
11149 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11150 } else {
11151 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11152 }
11153 } else {
11154 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
11155 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
11156 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11157 // binx1 is used here to get equal precision no matter how large the binrange is,
11158 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11159 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
11160 if (fH->GetXaxis()->GetLabels()) {
11161 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf] [%s..%s]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1), fH->GetXaxis()->GetBinLabel(binx2)));
11162 } else {
11163 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11164 }
11165 }
11166 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11167 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11168 c->Add(hp, fShowProjection2 ? "hbar" + fShowOption : fShowOption);
11169 c->UpdateAsync();
11170 }
11171}
11172
11173////////////////////////////////////////////////////////////////////////////////
11174/// Show projection (specified by `fShowProjection`) of a `TH3`.
11175/// The drawing option for the projection is in `fShowOption`.
11176///
11177/// First implementation: R.Brun
11178///
11179/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11180///
11181/// Redesign: S. Linev September 2026
11182
11184{
11185 Int_t nbins = fShowProjection / 100; //decode nbins
11186 Int_t kind = fShowProjection % 100; // projection kinds
11187
11188 if (fH->GetDimension() < 3) {
11189 if (fShowProjection2 % 100 == 1) {
11190 ShowProjectionY(px, py);
11191 }
11192 if (fShowProjection % 100 == 1) {
11193 ShowProjectionX(px, py);
11194 return;
11195 }
11196 if (fShowProjection % 100 == 2) {
11197 ShowProjectionY(px, py);
11198 return;
11199 }
11200 }
11201
11202 auto &parent = *gPad;
11203
11204 // 3D protection does not work with GL painters
11205 if (parent.GetGLDevice() != -1)
11206 return;
11207
11208 auto view = parent.GetView();
11209 if (!view)
11210 return;
11211
11212 // check that ranges are set
11213 if ((parent.GetUxmin() == parent.GetUxmax()) || (parent.GetUymin() == parent.GetUymax()))
11214 return;
11215
11216 // calculated vertices
11217 Double_t rect1x[5] = {0,0,0,0,0}, rect1y[5] = {0,0,0,0,0}, rect2x[5] = {0,0,0,0,0}, rect2y[5] = {0,0,0,0,0};
11218
11219 auto cname = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11220 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(cname));
11221 auto h3 = dynamic_cast<TH3 *>(fH);
11222
11223 if (!c || !h3) {
11224 fShowProjection = 0;
11225 return;
11226 }
11227
11228 TAxis *xaxis = fH->GetXaxis();
11229 TAxis *yaxis = fH->GetYaxis();
11230 TAxis *zaxis = fH->GetZaxis();
11231
11232 static constexpr Int_t iMin = -111;
11233 static constexpr Int_t iMax = -11;
11234 static constexpr Int_t kMaxDist = 50; // maximal distance to detect bin
11235
11236 auto getx = [](TAxis *axis, Int_t indx) {
11237 return indx == iMin ? axis->GetBinLowEdge(axis->GetFirst())
11238 : (indx == iMax ? axis->GetBinUpEdge(axis->GetLast()) : axis->GetBinCenter(indx));
11239 };
11240
11241 auto findAxis = [&parent, px, py, xaxis, yaxis, zaxis, view, getx](Int_t &besti1, Int_t &besti2, char name) {
11242
11243 TAxis *axis1 = nullptr, *axis2 = nullptr;
11244 Int_t xindx = 0, yindx = 0, zindx = 0;
11245
11246 switch(name) {
11247 case 'x':
11248 axis1 = yaxis;
11249 axis2 = zaxis;
11250 xindx = TMath::Cos(view->GetLongitude() / 180. * TMath::Pi()) < 0 ? iMin : iMax;
11251 break;
11252 case 'y':
11253 axis1 = xaxis;
11254 axis2 = zaxis;
11255 yindx = TMath::Sin(view->GetLongitude() / 180. * TMath::Pi()) < 0 ? iMin : iMax;
11256 break;
11257 default:
11258 axis1 = xaxis;
11259 axis2 = yaxis;
11260 zindx = TMath::Cos(view->GetLatitude() / 180. * TMath::Pi()) > 0 ? iMax : iMin;
11261 break;
11262 }
11263
11264 Double_t best_dist = kMaxDist;
11265
11266 for (Int_t i1 = axis1->GetFirst(); i1 <= axis1->GetLast(); ++i1)
11267 for (Int_t i2 = axis2->GetFirst(); i2 <= axis2->GetLast(); ++i2) {
11268 switch(name) {
11269 case 'x': yindx = i1; zindx = i2; break;
11270 case 'y': xindx = i1; zindx = i2; break;
11271 default: xindx = i1; yindx = i2; break;
11272 }
11273 Double_t v[3] = {getx(xaxis, xindx), getx(yaxis, yindx), getx(zaxis, zindx)};
11274 Double_t ndc[3];
11275 view->WCtoNDC(v, ndc);
11276 Int_t px1 = parent.XtoAbsPixel(ndc[0]);
11277 Int_t py1 = parent.YtoAbsPixel(ndc[1]);
11278 Double_t distance = TMath::Sqrt(1. * (px1 - px) * (px1 - px) + 1. * (py1 - py) * (py1 - py));
11279 if (distance < best_dist) {
11280 best_dist = distance;
11281 besti1 = i1;
11282 besti2 = i2;
11283 }
11284 }
11285
11286 return best_dist < kMaxDist;
11287 };
11288
11289 auto convert = [view, getx, xaxis, yaxis, zaxis](Int_t ix, Int_t iy, Int_t iz,
11290 Double_t &resx, Double_t &resy) {
11291 Double_t vvv[3] = {getx(xaxis, ix), getx(yaxis, iy), getx(zaxis, iz)};
11292 Double_t uu[3];
11293 view->WCtoNDC(vvv, uu);
11294 resx = uu[0];
11295 resy = uu[1];
11296 };
11297
11298 auto draw_rects = [&parent, nbins, kind, &rect1x, &rect2x, &rect1y, &rect2y]() {
11299 rect1x[4] = rect1x[0];
11300 rect1y[4] = rect1y[0];
11301 rect2x[4] = rect2x[0];
11302 rect2y[4] = rect2y[0];
11303 if (kind > 3) {
11304 parent.PaintPolyLine(5, rect1x, rect1y, "iproj3_rect1");
11305 if (nbins > 1)
11306 parent.PaintPolyLine(5, rect2x, rect2y, "iproj3_rect2");
11307 } else {
11308 parent.PaintPolyLine(nbins > 1 ? 5 : 2, rect1x, rect1y, "iproj3_rect1");
11309 if (nbins > 1) {
11310 parent.PaintPolyLine(5, rect2x, rect2y, "iproj3_rect2");
11311 for (Int_t n = 0; n < 4; ++n) {
11312 Double_t xx[2] = {rect1x[n], rect2x[n]};
11313 Double_t yy[2] = {rect1y[n], rect2y[n]};
11314 parent.PaintPolyLine(2, xx, yy, TString::Format("iproj3_line%d", n).Data());
11315 }
11316 }
11317 }
11318 parent.UpdateAsync();
11319 };
11320
11321 Int_t binx = -1, biny = -1, binz = -1, binx2 = -1, biny2 = -1, binz2 = -1, dummy = -1;
11322
11323 auto extend_bin = [nbins](TAxis *axis, Int_t &bin) {
11324 Int_t bin2 = bin;
11325 if (nbins > 1) {
11326 bin2 = TMath::Min(bin + nbins / 2, axis->GetLast());
11327 bin = TMath::Max(bin2 - nbins + 1, axis->GetFirst());
11328 }
11329 return bin2;
11330 };
11331
11332 auto make_proj = [h3, &binx, &biny, &binz, &binx2, &biny2, &binz2, xaxis, yaxis, zaxis](const char *proj_kind) {
11333 Int_t firstX = xaxis->GetFirst();
11334 Int_t lastX = xaxis->GetLast();
11335 Int_t firstY = yaxis->GetFirst();
11336 Int_t lastY = yaxis->GetLast();
11337 Int_t firstZ = zaxis->GetFirst();
11338 Int_t lastZ = zaxis->GetLast();
11339 if (binx >= 0)
11340 xaxis->SetRange(binx, binx2);
11341 if (biny >= 0)
11342 yaxis->SetRange(biny, biny2);
11343 if (binz >= 0)
11344 zaxis->SetRange(binz, binz2);
11345 auto hp = h3->Project3D(proj_kind);
11346 if (binx >= 0)
11347 xaxis->SetRange(firstX,lastX);
11348 if (biny >= 0)
11349 yaxis->SetRange(firstY, lastY);
11350 if (binz >= 0)
11351 zaxis->SetRange(firstZ,lastZ);
11352 return hp;
11353 };
11354
11355 TVirtualPad::TContext ctxt(true);
11356
11357 switch (kind) {
11358 case 1: { // "x"
11359 if (!findAxis(biny, binz, 'x'))
11360 break;
11361
11362 biny2 = extend_bin(yaxis, biny);
11363 binz2 = extend_bin(zaxis, binz);
11364
11365 convert(iMin, biny, binz, rect1x[0], rect1y[0]);
11366 convert(iMax, biny, binz, rect1x[1], rect1y[1]);
11367 convert(iMax, biny, binz2, rect1x[2], rect1y[2]);
11368 convert(iMin, biny, binz2, rect1x[3], rect1y[3]);
11369 convert(iMin, biny2, binz, rect2x[0], rect2y[0]);
11370 convert(iMax, biny2, binz, rect2x[1], rect2y[1]);
11371 convert(iMax, biny2, binz2, rect2x[2], rect2y[2]);
11372 convert(iMin, biny2, binz2, rect2x[3], rect2y[3]);
11373
11374 draw_rects();
11375
11376 c->Clear();
11377
11378 if (auto hp = make_proj("x")) {
11379 hp->SetFillColor(38);
11380 if ((biny == biny2) && (binz == binz2))
11381 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11382 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11383 else
11384 hp->SetTitle(TString::Format("ProjectionX, biny=[%d,%d] [y=%.1f..%.1f], binz=[%d,%d] [z=%.1f..%.1f]", biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2),
11385 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11386 hp->SetXTitle(xaxis->GetTitle());
11387 hp->SetYTitle("Number of Entries");
11388 c->Add(hp, fShowOption);
11389 }
11390 break;
11391 }
11392
11393 case 2: { // "y"
11394 if (!findAxis(binx, binz, 'y'))
11395 break;
11396
11397 binx2 = extend_bin(xaxis, binx);
11398 binz2 = extend_bin(zaxis, binz);
11399
11400 convert(binx, iMin, binz, rect1x[0], rect1y[0]);
11401 convert(binx, iMax, binz, rect1x[1], rect1y[1]);
11402 convert(binx, iMax, binz2, rect1x[2], rect1y[2]);
11403 convert(binx, iMin, binz2, rect1x[3], rect1y[3]);
11404 convert(binx2, iMin, binz, rect2x[0], rect2y[0]);
11405 convert(binx2, iMax, binz, rect2x[1], rect2y[1]);
11406 convert(binx2, iMax, binz2, rect2x[2], rect2y[2]);
11407 convert(binx2, iMin, binz2, rect2x[3], rect2y[3]);
11408
11409 draw_rects();
11410
11411 c->Clear();
11412 if (auto hp = make_proj("y")) {
11413 hp->SetFillColor(38);
11414 if ((binx == binx2) && (binz == binz2))
11415 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11416 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11417 else
11418 hp->SetTitle(TString::Format("ProjectionY, binx=[%d,%d] [x=%.1f..%.1f], binz=[%d,%d] [z=%.1f..%.1f]", binx, binx2, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2),
11419 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11420 hp->SetXTitle(yaxis->GetTitle());
11421 hp->SetYTitle("Number of Entries");
11422 c->Add(hp, fShowOption);
11423 }
11424 break;
11425 }
11426
11427 case 3: { // "z"
11428 if (!findAxis(binx, biny, 'z'))
11429 break;
11430 binx2 = extend_bin(xaxis, binx);
11431 biny2 = extend_bin(yaxis, biny);
11432
11433 convert(binx, biny, iMin, rect1x[0], rect1y[0]);
11434 convert(binx, biny, iMax, rect1x[1], rect1y[1]);
11435 convert(binx, biny2, iMax, rect1x[2], rect1y[2]);
11436 convert(binx, biny2, iMin, rect1x[3], rect1y[3]);
11437 convert(binx2, biny, iMin, rect2x[0], rect2y[0]);
11438 convert(binx2, biny, iMax, rect2x[1], rect2y[1]);
11439 convert(binx2, biny2, iMax, rect2x[2], rect2y[2]);
11440 convert(binx2, biny2, iMin, rect2x[3], rect2y[3]);
11441
11442 draw_rects();
11443
11444 c->Clear();
11445 if (auto hp = make_proj("z")) {
11446 hp->SetFillColor(38);
11447 if ((binx == binx2) && (biny == biny2))
11448 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11449 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11450 else
11451 hp->SetTitle(TString::Format("ProjectionZ, binx=[%d,%d] [x=%.1f..%.1f], biny=[%d,%d] [y=%.1f..%.1f]", binx, binx2, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2),
11452 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11453 hp->SetXTitle(zaxis->GetTitle());
11454 hp->SetYTitle("Number of Entries");
11455 c->Add(hp, fShowOption);
11456 }
11457 break;
11458 }
11459
11460 case 4: // "xy"
11461 case 5: { // "yx"
11462 if (!findAxis(dummy, binz, 'x') && !findAxis(dummy, binz, 'y'))
11463 break;
11464 binz2 = extend_bin(zaxis, binz);
11465
11466 convert(iMin, iMax, binz, rect1x[0], rect1y[0]);
11467 convert(iMax, iMax, binz, rect1x[1], rect1y[1]);
11468 convert(iMax, iMin, binz, rect1x[2], rect1y[2]);
11469 convert(iMin, iMin, binz, rect1x[3], rect1y[3]);
11470 if (binz != binz2) {
11471 convert(iMin, iMax, binz2, rect2x[0], rect2y[0]);
11472 convert(iMax, iMax, binz2, rect2x[1], rect2y[1]);
11473 convert(iMax, iMin, binz2, rect2x[2], rect2y[2]);
11474 convert(iMin, iMin, binz2, rect2x[3], rect2y[3]);
11475 }
11476
11477 draw_rects();
11478
11479 c->Clear();
11480
11481 if (auto hp = make_proj(kind == 4 ? "xy" : "yx")) {
11482 hp->SetFillColor(38);
11483 TString sbins = (binz == binz2) ? TString::Format("%d", binz) : TString::Format("[%d,%d]", binz, binz2);
11484 hp->SetTitle(TString::Format("Projection%s, binz=%s [z=%.1f..%.1f]", kind == 4 ? "XY" : "YX", sbins.Data(),
11485 zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2)));
11486 if (kind == 4) {
11487 hp->SetXTitle(yaxis->GetTitle());
11488 hp->SetYTitle(xaxis->GetTitle());
11489 } else {
11490 hp->SetXTitle(xaxis->GetTitle());
11491 hp->SetYTitle(yaxis->GetTitle());
11492 }
11493 hp->SetZTitle("Number of Entries");
11494 c->Add(hp, fShowOption);
11495 }
11496 break;
11497 }
11498
11499 case 6: // "xz"
11500 case 7: { // "zx"
11501 if (!findAxis(biny, dummy, 'x') && !findAxis(dummy, biny, 'z'))
11502 break;
11503
11504 biny2 = extend_bin(yaxis, biny);
11505
11506 convert(iMin, biny, iMax, rect1x[0], rect1y[0]);
11507 convert(iMax, biny, iMax, rect1x[1], rect1y[1]);
11508 convert(iMax, biny, iMin, rect1x[2], rect1y[2]);
11509 convert(iMin, biny, iMin, rect1x[3], rect1y[3]);
11510
11511 if (biny != biny2) {
11512 convert(iMin, biny2, iMax, rect2x[0], rect2y[0]);
11513 convert(iMax, biny2, iMax, rect2x[1], rect2y[1]);
11514 convert(iMax, biny2, iMin, rect2x[2], rect2y[2]);
11515 convert(iMin, biny2, iMin, rect2x[3], rect2y[3]);
11516 }
11517
11518 draw_rects();
11519
11520 c->Clear();
11521
11522 if (auto hp = make_proj(kind == 6 ? "xz" : "zx")) {
11523 hp->SetFillColor(38);
11524 TString sbins = (biny == biny2) ? TString::Format("%d", biny) : TString::Format("[%d,%d]", biny, biny2);
11525 hp->SetTitle(TString::Format("Projection%s, biny=%s [y=%.1f..%.1f]", kind == 6 ? "XZ" : "ZX", sbins.Data(),
11526 yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2)));
11527 if (kind == 6) {
11528 hp->SetXTitle(zaxis->GetTitle());
11529 hp->SetYTitle(xaxis->GetTitle());
11530 } else {
11531 hp->SetXTitle(xaxis->GetTitle());
11532 hp->SetYTitle(zaxis->GetTitle());
11533 }
11534 hp->SetZTitle("Number of Entries");
11535 c->Add(hp, fShowOption);
11536 }
11537 break;
11538 }
11539
11540 case 8: // "yz"
11541 case 9: { // "zy"
11542 if (!findAxis(binx, dummy, 'y') && !findAxis(binx, dummy, 'z'))
11543 break;
11544
11545 binx2 = extend_bin(xaxis, binx);
11546
11547 convert(binx, iMax, iMin, rect1x[0], rect1y[0]);
11548 convert(binx, iMax, iMax, rect1x[1], rect1y[1]);
11549 convert(binx, iMin, iMax, rect1x[2], rect1y[2]);
11550 convert(binx, iMin, iMin, rect1x[3], rect1y[3]);
11551 if (binx != binx2) {
11552 convert(binx2, iMax, iMin, rect2x[0], rect2y[0]);
11553 convert(binx2, iMax, iMax, rect2x[1], rect2y[1]);
11554 convert(binx2, iMin, iMax, rect2x[2], rect2y[2]);
11555 convert(binx2, iMin, iMin, rect2x[3], rect2y[3]);
11556 }
11557
11558 draw_rects();
11559
11560 c->Clear();
11561 if (auto hp = make_proj(kind == 8 ? "yz" : "zy")) {
11562 hp->SetFillColor(38);
11563 TString sbins = (binx == binx2) ? TString::Format("%d", binx) : TString::Format("[%d,%d]", binx, binx2);
11564 hp->SetTitle(TString::Format("Projection%s of binx=%s [x=%.1f..%.f]", kind == 8 ? "YZ" : "ZY", sbins.Data(),
11565 xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2)));
11566 if (kind == 8) {
11567 hp->SetXTitle(zaxis->GetTitle());
11568 hp->SetYTitle(yaxis->GetTitle());
11569 } else {
11570 hp->SetXTitle(yaxis->GetTitle());
11571 hp->SetYTitle(zaxis->GetTitle());
11572 }
11573 hp->SetZTitle("Number of Entries");
11574 c->Add(hp, fShowOption);
11575 }
11576 break;
11577 }
11578 }
11579 c->Update();
11580}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:375
@ kPointer
Definition GuiTypes.h:376
#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 g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
cudaEvent_t event
short Style_t
Style number (short)
Definition RtypesCore.h:97
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Width_t
Line width (short)
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#define BIT(n)
Definition Rtypes.h:90
@ kBlack
Definition Rtypes.h:65
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:142
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:417
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
const Int_t kCARTESIAN
Definition TView3D.cxx:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#define gPad
Int_t fN
Definition TArray.h:38
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual void SetImageQuality(EImageQuality lquality)
Definition TAttImage.h:99
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:35
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:34
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:36
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:52
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1090
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1061
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
void SetLog(int x, int y, int z)
Definition TCandle.h:126
CandleOption
Definition TCandle.h:30
void SetHistoWidth(const Double_t width)
Definition TCandle.h:130
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition TCandle.cxx:665
Bool_t IsViolinScaled() const
Returns true if violin plot should be scaled.
Definition TCandle.cxx:190
Bool_t IsHorizontal() const
Definition TCandle.h:120
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:243
void SetOption(CandleOption opt)
Definition TCandle.h:125
void SetHistogram(TH1D *proj)
Definition TCandle.h:131
Bool_t IsCandleScaled() const
Returns true if candle plot should be scaled.
Definition TCandle.cxx:182
void SetCandleWidth(const Double_t width)
Definition TCandle.h:129
void SetAxisPosition(const Double_t candlePos)
Definition TCandle.h:127
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2505
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2999
void SetName(const char *name)
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Paint(Option_t *option="") override
Paint all objects in this collection.
The color creation and management class.
Definition TColor.h:22
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its "dark" and "bright" associated colors.
Definition TColor.cxx:1868
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:55
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1939
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2108
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2151
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
void Paint(Option_t *option="") override
Paint this crown with its current attributes.
Definition TCrown.cxx:216
void SetYXRatio(Double_t v=1)
Definition TCrown.h:29
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1940
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1991
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1981
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3450
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1951
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3463
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1447
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:806
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2937
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1006
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2910
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:953
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2902
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2015
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:2024
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7816
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9293
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7744
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7880
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8669
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5137
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:8778
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9309
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3193
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:8170
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9452
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9382
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4574
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7784
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8964
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8810
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5239
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8640
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9393
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8716
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9340
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7864
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:8868
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5423
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1445
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7953
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y (integration along X).
Definition TH2.cxx:2444
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X (integration along Y).
Definition TH2.cxx:2401
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:97
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1293
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH3.cxx:1419
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
Set projection XY.
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t DetectProjectionKind(Option_t *option)
Return projection kind from option string.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=nullptr)
Definition TImage.h:116
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:70
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:170
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:444
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:424
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:267
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
virtual TClass * IsA() const
Definition TObject.h:248
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:630
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
void Paint(Option_t *option="") override
Paint the palette.
void SetHistogram(TH1 *h)
TH1 * GetHistogram()
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
void Draw(Option_t *option="") override
Draw this pavetext with its current attributes.
void Paint(Option_t *option="") override
Paint this pavetext with its current attributes.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Profile Histogram.
Definition TProfile.h:32
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition TProfile.cxx:864
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Double_t Rndm() override
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:56
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
const char * Data() const
Definition TString.h:385
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:633
TString & Remove(Ssiz_t pos)
Definition TString.h:695
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1879
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
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()
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:58
auto GetSaved() const
Definition TVirtualPad.h:66
Helper class to store interactive parameters for individual objects Should be used via MakeInteractiv...
Definition TVirtualPad.h:72
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:53
virtual Double_t PadtoX(Double_t x) const =0
virtual void UpdateAsync()=0
virtual Double_t AbsPixeltoX(Double_t px)=0
virtual void PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option="")=0
virtual Double_t PadtoY(Double_t y) const =0
virtual void Close(Option_t *option="")=0
virtual Double_t AbsPixeltoY(Double_t py)=0
virtual Bool_t OpaqueMoving() const =0
TZoomInteractive(TVirtualPad &parent, Int_t px, Int_t py)
void ChangeRange(TAxis *xaxis, TAxis *yaxis)
void MovePoint(TVirtualPad &parent, Int_t px, Int_t py)
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:706
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:653
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:769
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:734
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:613
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:775
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
Histograms' drawing options structure.
Definition Hoption.h:27
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:35
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:63
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:33
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:44
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:52
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:54
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:46
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:64
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:62
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:74
int Zscale
"Z" Display the color palette.
Definition Hoption.h:59
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:67
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:48
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:38
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:49
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:57
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:65
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:60
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:56
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:42
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:66
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:76
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:55
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:61
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:40
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:43
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:39
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:41
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:51
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:34
int Polar
"POL" Draw 2D plot with Polar coordinates.
Definition Hoption.h:47
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:37
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:50
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:53
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:75
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:58
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:36
Histogram parameters structure.
Definition Hparam.h:31
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:46
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:37
Double_t xmin
Minimum value along X.
Definition Hparam.h:34
Int_t ylast
Last bin number along Y.
Definition Hparam.h:51
Int_t xfirst
First bin number along X.
Definition Hparam.h:48
Double_t zmin
Minimum value along Z.
Definition Hparam.h:42
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t ymin
Minimum value along y.
Definition Hparam.h:38
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:45
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:33
Double_t ymax
Maximum value along y.
Definition Hparam.h:39
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:44
Int_t xlast
Last bin number along X.
Definition Hparam.h:49
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:36
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:47
Double_t zmax
Maximum value along Z.
Definition Hparam.h:43
Double_t xmax
Maximum value along X.
Definition Hparam.h:35
Int_t yfirst
First bin number along Y.
Definition Hparam.h:50
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16